diff --git a/doc/addressbook-sdk.qdoc b/doc/addressbook-sdk.qdoc index 1974c129edec49962354569525e650d0a2a908e6..3194ad70b2f3d60e55b4519f993f496c763ce77d 100644 --- a/doc/addressbook-sdk.qdoc +++ b/doc/addressbook-sdk.qdoc @@ -315,6 +315,12 @@ \snippet examples/addressbook-sdk/part2/addressbook.h members1 + The Qt types used for our private members, e.g., QPushButton, QLineEdit, + QTextEdit, etc., need to be included with the \c include directive, as + shown below: + + \snippet examples/addressbook-sdk/part2/addressbook.h include + \note The names, e.g., \c addButton etc., correspond to the name of the actual object. You can modify them by double-clicking on their names within \QD's \gui{Object Inspector}. @@ -727,6 +733,7 @@ dialog that can prompt the user for a contact's name. Qt provides QDialog, which we subclass in this chapter, to implement a FindDialog class. + \section1 Designing \c FindDialog #image @@ -743,6 +750,7 @@ in a horizontal layout. Then set a top level layout - either horizontal or vertical. + \section1 Implementing \c FindDialog Let's look at \c{FindDialog}'s header file. Here, we need to provide @@ -751,8 +759,38 @@ \snippet examples/addressbook-sdk/part5/finddialog.h private members + We define a public function, \c getFindText(), to be used by classes that + instantiate \c FindDialog. This function allows the these classes to obtain + the search string entered by the user. A public slot, \c findClicked(), is + also defined to handle the search string when the user clicks the \gui Find + button. + + \snippet examples/addressbook-sdk/part5/finddialog.h getFindText + \dots + \snippet examples/addressbook-sdk/part5/finddialog.h findClicked + + Now, lets look at our constructor in the \c{finddialog.cpp} file. Here, we + set up the private variables, \c lineEdit, \c findButton, and \c findText. + + \snippet examples/addressbook-sdk/part5/finddialog.cpp constructor + + We connect our signals to their respective slots. Notice that + \c{findButton}'s \l{QPushButton:}{clicked()} signal is connected to + \c findClicked() and \l{QDialog::}{accept()}. The \l{QDialog::}{accept()} + slot provided by QDialog hides the dialog and sets the result code to + \l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s + \c findContact() function know when the \c FindDialog object has been + closed. We will explain this logic in further detail when discussing the + \c findContact() function. + + \image addressbook-tutorial-part5-signals-and-slots.png + In \c findClicked(), we validate to ensure that the user did not click the + \gui Find button without entering a contact's name. Then, we set + \c findText to the search string, extracted from \c lineEdit. After that, + we clear the contents of \c lineEdit and hide the dialog. + \snippet examples/addressbook-sdk/part5/finddialog.cpp findClicked */ diff --git a/doc/examples/addressbook-sdk/part2/addressbook.h b/doc/examples/addressbook-sdk/part2/addressbook.h index efea5d177b3d2f359fb0278441c7a4e373f56b25..69486cb8cf2684d67472f98bc4fe7d1b0d3072ea 100644 --- a/doc/examples/addressbook-sdk/part2/addressbook.h +++ b/doc/examples/addressbook-sdk/part2/addressbook.h @@ -1,13 +1,13 @@ -//! [class definition] #ifndef ADDRESSBOOK_H #define ADDRESSBOOK_H +//! [include] #include <QtGui/QWidget> #include <QtGui/QPushButton> #include <QtGui/QLineEdit> #include <QtGui/QTextEdit> #include <QtGui/QMessageBox> - +//! [include] namespace Ui { @@ -48,4 +48,3 @@ private: }; #endif // ADDRESSBOOK_H -//! [class definition] diff --git a/doc/examples/addressbook-sdk/part5/finddialog.cpp b/doc/examples/addressbook-sdk/part5/finddialog.cpp index 89ee5e083a2e954339dfad0696e53ef5e01a7d5c..1a464b70903511d3680df80657f1cdc42a30d8d1 100644 --- a/doc/examples/addressbook-sdk/part5/finddialog.cpp +++ b/doc/examples/addressbook-sdk/part5/finddialog.cpp @@ -1,6 +1,7 @@ #include "finddialog.h" #include "ui_finddialog.h" +//! [constructor] FindDialog::FindDialog(QWidget *parent) : QDialog(parent), m_ui(new Ui::FindDialog) @@ -18,12 +19,14 @@ FindDialog::FindDialog(QWidget *parent) : setWindowTItle(tr("Find a Contact")); } +//! [constructor] FindDialog::~FindDialog() { delete m_ui; } +//! [findClicked] void FindDialog::findClicked() { QString text = lineEdit->text(); @@ -38,6 +41,7 @@ void FindDialog::findClicked() hide(); } } +//! [findClicked] QString FindDialog::getFindText() { diff --git a/doc/examples/addressbook-sdk/part5/finddialog.h b/doc/examples/addressbook-sdk/part5/finddialog.h index 9df1df899885d98a1759945e085d213fb6561736..aef5aee9fa37e48c8a12435b59640c081f40b78a 100644 --- a/doc/examples/addressbook-sdk/part5/finddialog.h +++ b/doc/examples/addressbook-sdk/part5/finddialog.h @@ -2,8 +2,8 @@ #define FINDDIALOG_H #include <QtGui/QDialog> -#include <QLineEdit> -#include <QPushButton> +#include <QtGui/QLineEdit> +#include <QtGui/QPushButton> namespace Ui { class FindDialog; @@ -14,10 +14,14 @@ class FindDialog : public QDialog { public: FindDialog(QWidget *parent = 0); ~FindDialog(); +//! [getFindText] QString getFindText(); +//! [getFindText] +//! [findClicked] public slots: void findClicked(); +//! [findClicked] //! [private members] private: diff --git a/doc/images/addressbook-tutorial-part5-signals-and-slots.png b/doc/images/addressbook-tutorial-part5-signals-and-slots.png new file mode 100644 index 0000000000000000000000000000000000000000..1771e7bbbf54d69aed3121adf4a96ff8ec7b6353 Binary files /dev/null and b/doc/images/addressbook-tutorial-part5-signals-and-slots.png differ diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 10493f47e4a22dba5c60645a576364585279ee52..b903916acff6784dea82f72a47e4f368e9fb8bf6 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -279,8 +279,12 @@ void BreakHandler::removeAt(int index) void BreakHandler::clear() { - for (int index = size(); --index >= 0; ) - removeAt(index); + qDeleteAll(m_bp); + m_bp.clear(); + m_enabled.clear(); + m_disabled.clear(); + m_removed.clear(); + m_inserted.clear(); } int BreakHandler::findBreakpoint(const BreakpointData &needle) @@ -326,19 +330,19 @@ void BreakHandler::saveBreakpoints() const BreakpointData *data = at(index); QMap<QString, QVariant> map; if (!data->fileName.isEmpty()) - map["filename"] = data->fileName; + map.insert(QLatin1String("filename"), data->fileName); if (!data->lineNumber.isEmpty()) - map["linenumber"] = data->lineNumber; + map.insert(QLatin1String("linenumber"), data->lineNumber); if (!data->funcName.isEmpty()) - map["funcname"] = data->funcName; + map.insert(QLatin1String("funcname"), data->funcName); if (!data->condition.isEmpty()) - map["condition"] = data->condition; + map.insert(QLatin1String("condition"), data->condition); if (!data->ignoreCount.isEmpty()) - map["ignorecount"] = data->ignoreCount; + map.insert(QLatin1String("ignorecount"), data->ignoreCount); if (!data->enabled) - map["disabled"] = "1"; + map.insert(QLatin1String("disabled"), QLatin1String("1")); if (data->useFullPath) - map["usefullpath"] = "1"; + map.insert(QLatin1String("usefullpath"), QLatin1String("1")); list.append(map); } setSessionValueRequested("Breakpoints", list); @@ -349,18 +353,31 @@ void BreakHandler::loadBreakpoints() QVariant value; sessionValueRequested("Breakpoints", &value); QList<QVariant> list = value.toList(); - clear(); foreach (const QVariant &var, list) { const QMap<QString, QVariant> map = var.toMap(); BreakpointData *data = new BreakpointData(this); - data->fileName = map["filename"].toString(); - data->lineNumber = map["linenumber"].toString(); - data->condition = map["condition"].toString(); - data->ignoreCount = map["ignorecount"].toString(); - data->funcName = map["funcname"].toString(); - data->enabled = !map["disabled"].toInt(); - data->useFullPath = bool(map["usefullpath"].toInt()); + QVariant v = map.value(QLatin1String("filename")); + if (v.isValid()) + data->fileName = v.toString(); + v = map.value(QLatin1String("linenumber")); + if (v.isValid()) + data->lineNumber = v.toString(); + v = map.value(QLatin1String("condition")); + if (v.isValid()) + data->condition = v.toString(); + v = map.value(QLatin1String("ignorecount")); + if (v.isValid()) + data->ignoreCount = v.toInt(); + v = map.value(QLatin1String("funcname")); + if (v.isValid()) + data->funcName = v.toString(); + v = map.value(QLatin1String("disabled")); + if (v.isValid()) + data->enabled = !v.toInt(); + v = map.value(QLatin1String("usefullpath")); + if (v.isValid()) + data->useFullPath = bool(v.toInt()); data->markerFileName = data->fileName; data->markerLineNumber = data->lineNumber.toInt(); append(data); diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index a785e33febf5fdaeeec43098ac2436d3831a6e23..ee10e1e70b5a7dcf13619d4a10349e214950004b 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -407,12 +407,19 @@ static bool setBreakPointEnabledById(CIDebugControl *ctl, unsigned long id, bool return true; } +static inline QString msgCannotSetBreakAtFunction(const QString &func, const QString &why) +{ + return QString::fromLatin1("Cannot set a breakpoint at '%1': %2").arg(func, why); +} + // Synchronize (halted) engine breakpoints with those of the BreakHandler. bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl, CIDebugSymbols *syms, BreakHandler *handler, - QString *errorMessage) + QString *errorMessage, QStringList *warnings) { + errorMessage->clear(); + warnings->clear(); // Do an initial check whether we are in a state that allows // for modifying breakPoints ULONG engineCount; @@ -420,25 +427,29 @@ bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl, *errorMessage = QString::fromLatin1("Cannot modify breakpoints: %1").arg(*errorMessage); return false; } + QString warning; // Insert new ones bool updateMarkers = false; foreach (BreakpointData *nbd, handler->insertedBreakpoints()) { + warning.clear(); // Function breakpoints: Are the module names specified? bool breakPointOk = false; if (nbd->funcName.isEmpty()) { breakPointOk = true; } else { - switch (resolveSymbol(syms, &nbd->funcName, errorMessage)) { + switch (resolveSymbol(syms, &nbd->funcName, &warning)) { case ResolveSymbolOk: breakPointOk = true; break; case ResolveSymbolAmbiguous: - qWarning("Warning: %s\n", qPrintable(*errorMessage)); + warnings->push_back(msgCannotSetBreakAtFunction(nbd->funcName, warning)); + warning.clear(); breakPointOk = true; break; case ResolveSymbolNotFound: case ResolveSymbolError: - qWarning("Warning: %s\n", qPrintable(*errorMessage)); + warnings->push_back(msgCannotSetBreakAtFunction(nbd->funcName, warning)); + warning.clear(); break; }; } // function breakpoint @@ -447,7 +458,7 @@ bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl, quint64 address; unsigned long id; CDBBreakPoint ncdbbp(*nbd); - breakPointOk = ncdbbp.add(debugControl, &address, &id, errorMessage); + breakPointOk = ncdbbp.add(debugControl, &address, &id, &warning); if (breakPointOk) { if (debugBP) qDebug() << "Added " << id << " at " << address << ncdbbp; @@ -464,22 +475,21 @@ bool CDBBreakPoint::synchronizeBreakPoints(CIDebugControl* debugControl, nbd->bpFuncName = nbd->funcName; } } // had symbol - if (!breakPointOk) - qWarning("%s\n", qPrintable(*errorMessage)); - } + if (!breakPointOk && !warning.isEmpty()) + warnings->push_back(warning); } // Delete foreach (BreakpointData *rbd, handler->takeRemovedBreakpoints()) { - if (!removeBreakPointById(debugControl, rbd->bpNumber.toUInt(), errorMessage)) - qWarning("%s\n", qPrintable(*errorMessage)); + if (!removeBreakPointById(debugControl, rbd->bpNumber.toUInt(), &warning)) + warnings->push_back(warning); delete rbd; } // Enable/Disable foreach (BreakpointData *ebd, handler->takeEnabledBreakpoints()) - if (!setBreakPointEnabledById(debugControl, ebd->bpNumber.toUInt(), true, errorMessage)) - qWarning("%s\n", qPrintable(*errorMessage)); + if (!setBreakPointEnabledById(debugControl, ebd->bpNumber.toUInt(), true, &warning)) + warnings->push_back(warning); foreach (BreakpointData *dbd, handler->takeDisabledBreakpoints()) - if (!setBreakPointEnabledById(debugControl, dbd->bpNumber.toUInt(), false, errorMessage)) - qWarning("%s\n", qPrintable(*errorMessage)); + if (!setBreakPointEnabledById(debugControl, dbd->bpNumber.toUInt(), false, &warning)) + warnings->push_back(warning); if (updateMarkers) handler->updateMarkers(); diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.h b/src/plugins/debugger/cdb/cdbbreakpoint.h index c739866ff09ea44ec21dba65b7ba9395f91e603d..7383687a615ba0d9388db5fc765d0e077d960201 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.h +++ b/src/plugins/debugger/cdb/cdbbreakpoint.h @@ -73,7 +73,8 @@ struct CDBBreakPoint static bool getBreakPoints(CIDebugControl* debugControl, QList<CDBBreakPoint> *bps, QString *errorMessage); // Synchronize (halted) engine with BreakHandler. static bool synchronizeBreakPoints(CIDebugControl* ctl, CIDebugSymbols *syms, - BreakHandler *bh, QString *errorMessage); + BreakHandler *bh, + QString *errorMessage, QStringList *warnings); // Return a 'canonical' file (using '/' and capitalized drive letter) static QString canonicalSourceFile(const QString &f); diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index fbac6838d1542492da2fccacd8467dc29a657115..798f5234ff46edfc5d6879d4f29d6c1695ab6a94 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -1182,6 +1182,8 @@ void CdbDebugEngine::selectThread(int index) void CdbDebugEngine::attemptBreakpointSynchronization() { + if (!m_d->m_hDebuggeeProcess) // Sometimes called from the breakpoint Window + return; QString errorMessage; if (!m_d->attemptBreakpointSynchronization(&errorMessage)) warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); @@ -1215,10 +1217,15 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa return true; } - return CDBBreakPoint::synchronizeBreakPoints(m_cif.debugControl, + QStringList warnings; + const bool ok = CDBBreakPoint::synchronizeBreakPoints(m_cif.debugControl, m_cif.debugSymbols, m_debuggerManagerAccess->breakHandler(), - errorMessage); + errorMessage, &warnings); + if (const int warningsCount = warnings.size()) + for (int w = 0; w < warningsCount; w++) + m_engine->warning(warnings.at(w)); + return ok; } void CdbDebugEngine::reloadDisassembler() diff --git a/src/plugins/debugger/cdb/cdbmodules.cpp b/src/plugins/debugger/cdb/cdbmodules.cpp index a7e2e87754335ee085f9a56086ce49df042ddcef..7385bc27d466b94bf01a9a23d30e96c5ac7b34ff 100644 --- a/src/plugins/debugger/cdb/cdbmodules.cpp +++ b/src/plugins/debugger/cdb/cdbmodules.cpp @@ -138,6 +138,7 @@ static ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol, QStringList *matches, QString *errorMessage) { + errorMessage->clear(); // Is it an incomplete symbol? if (symbol->contains(QLatin1Char('!'))) return ResolveSymbolOk; diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 7a0a2c41cb181c0d0a4d6626767bddc8d66bd40f..5328a7c148f3b375a3fada42f398d727f870e7a2 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -168,19 +168,16 @@ static QStringList readLines(const QString &absoluteFileName) return lines; } -bool GenericProject::addFiles(const QStringList &filePaths) +bool GenericProject::setFiles(const QStringList &filePaths) { // Make sure we can open the file for writing QFile file(filesFileName()); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return false; - QStringList newFileList = m_files; - newFileList.append(filePaths); - QTextStream stream(&file); QDir baseDir(QFileInfo(m_fileName).dir()); - foreach (const QString &filePath, newFileList) + foreach (const QString &filePath, filePaths) stream << baseDir.relativeFilePath(filePath) << QLatin1Char('\n'); file.close(); @@ -188,6 +185,27 @@ bool GenericProject::addFiles(const QStringList &filePaths) return true; } +bool GenericProject::addFiles(const QStringList &filePaths) +{ + QStringList newFileList = m_files; + newFileList.append(filePaths); + + return setFiles(newFileList); +} + +bool GenericProject::removeFiles(const QStringList &filePaths) +{ + QStringList newFileList; + QSet<QString> filesToRemove = filePaths.toSet(); + + foreach (const QString &file, m_files) { + if (!filesToRemove.contains(file)) + newFileList.append(file); + } + + return setFiles(newFileList); +} + void GenericProject::parseProject(RefreshOptions options) { if (options & Files) diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index a22f2abda0ad1419a73f9e6c3a2d96d4f6c2fc36..cf9565644ac9d61bd7ccb177d0765067c8c62f6b 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -94,7 +94,9 @@ public: QString buildParser(const QString &buildConfiguration) const; ProjectExplorer::ToolChain *toolChain() const; + bool setFiles(const QStringList &filePaths); bool addFiles(const QStringList &filePaths); + bool removeFiles(const QStringList &filePaths); enum RefreshOptions { Files = 0x01, diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.cpp b/src/plugins/genericprojectmanager/genericprojectnodes.cpp index 26e1eb812564f7ed0467da18dd18d05ad686ead4..e8668a0d7c1d362fc93c127799c72de6d37609e0 100644 --- a/src/plugins/genericprojectmanager/genericprojectnodes.cpp +++ b/src/plugins/genericprojectmanager/genericprojectnodes.cpp @@ -167,7 +167,8 @@ bool GenericProjectNode::hasTargets() const QList<ProjectExplorer::ProjectNode::ProjectAction> GenericProjectNode::supportedActions() const { return QList<ProjectAction>() - << AddFile; + << AddFile + << RemoveFile; } bool GenericProjectNode::addSubProjects(const QStringList &proFilePaths) @@ -195,9 +196,9 @@ bool GenericProjectNode::removeFiles(const ProjectExplorer::FileType fileType, const QStringList &filePaths, QStringList *notRemoved) { Q_UNUSED(fileType); - Q_UNUSED(filePaths); Q_UNUSED(notRemoved); - return false; + + return m_project->removeFiles(filePaths); } bool GenericProjectNode::renameFile(const ProjectExplorer::FileType fileType,