From a48ee6f7a8cb8d1d2c49724e9cf2f86957f9c3ce Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Dec 2008 10:39:08 +0100 Subject: [PATCH 01/41] Fixes: Allow directories to be entered into the class wizard file names Task: 237390 Details: Add 'allowDirectories' property to the widgets involved. --- src/libs/utils/filenamevalidatinglineedit.cpp | 86 ++++++++++++++----- src/libs/utils/filenamevalidatinglineedit.h | 13 ++- src/libs/utils/filewizardpage.cpp | 2 +- src/libs/utils/newclasswidget.cpp | 15 ++++ src/libs/utils/newclasswidget.h | 4 +- .../utils/projectnamevalidatinglineedit.cpp | 2 +- src/plugins/cppeditor/cppclasswizard.cpp | 1 + .../designer/cpp/formclasswizardpage.cpp | 1 + 8 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/libs/utils/filenamevalidatinglineedit.cpp b/src/libs/utils/filenamevalidatinglineedit.cpp index 57a0ed7a5f9..5b308f5ce47 100644 --- a/src/libs/utils/filenamevalidatinglineedit.cpp +++ b/src/libs/utils/filenamevalidatinglineedit.cpp @@ -33,26 +33,65 @@ #include "filenamevalidatinglineedit.h" +#include +#include + namespace Core { namespace Utils { -FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) : - BaseValidatingLineEdit(parent) -{ - -} - -/* Validate a file base name, check for forbidden characters/strings. */ - -static const char *notAllowedChars = "/?:&\\*\"|#%<> "; -static const char *notAllowedSubStrings[] = {".."}; - // Naming a file like a device name will break on Windows, even if it is // "com1.txt". Since we are cross-platform, we generally disallow such file // names. -static const char *notAllowedStrings[] = {"CON", "AUX", "PRN", "COM1", "COM2", "LPT1", "LPT2" }; +static const QRegExp &windowsDeviceNoSubDirPattern() +{ + static const QRegExp rc(QLatin1String("CON|AUX|PRN|COM1|COM2|LPT1|LPT2|NUL"), + Qt::CaseInsensitive); + Q_ASSERT(rc.isValid()); + return rc; +} -bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *errorMessage /* = 0*/) +static const QRegExp &windowsDeviceSubDirPattern() +{ + static const QRegExp rc(QLatin1String(".*[/\\\\]CON|.*[/\\\\]AUX|.*[/\\\\]PRN|.*[/\\\\]COM1|.*[/\\\\]COM2|.*[/\\\\]LPT1|.*[/\\\\]LPT2|.*[/\\\\]NUL"), + Qt::CaseInsensitive); + Q_ASSERT(rc.isValid()); + return rc; +} + +// ----------- FileNameValidatingLineEdit +FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) : + BaseValidatingLineEdit(parent), + m_allowDirectories(false), + m_unused(0) +{ +} + +bool FileNameValidatingLineEdit::allowDirectories() const +{ + return m_allowDirectories; +} + +void FileNameValidatingLineEdit::setAllowDirectories(bool v) +{ + m_allowDirectories = v; +} + +/* Validate a file base name, check for forbidden characters/strings. */ + +#ifdef Q_OS_WIN +# define SLASHES "/\\" +#else +# define SLASHES "/" +#endif + +static const char *notAllowedCharsSubDir = "?:&*\"|#%<> "; +static const char *notAllowedCharsNoSubDir = "?:&*\"|#%<> "SLASHES; + +static const char *notAllowedSubStrings[] = {".."}; + +bool FileNameValidatingLineEdit::validateFileName(const QString &name, + bool allowDirectories, + QString *errorMessage /* = 0*/) { if (name.isEmpty()) { if (errorMessage) @@ -60,6 +99,7 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString * return false; } // Characters + const char *notAllowedChars = allowDirectories ? notAllowedCharsSubDir : notAllowedCharsNoSubDir; for (const char *c = notAllowedChars; *c; c++) if (name.contains(QLatin1Char(*c))) { if (errorMessage) @@ -76,22 +116,22 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString * return false; } } - // Strings - const int notAllowedStringCount = sizeof(notAllowedStrings)/sizeof(const char *); - for (int s = 0; s < notAllowedStringCount; s++) { - const QLatin1String notAllowedString(notAllowedStrings[s]); - if (name == notAllowedString) { - if (errorMessage) - *errorMessage = tr("The name must not be '%1'.").arg(QString(notAllowedString)); - return false; - } + // Windows devices + bool matchesWinDevice = windowsDeviceNoSubDirPattern().exactMatch(name); + if (!matchesWinDevice && allowDirectories) + matchesWinDevice = windowsDeviceSubDirPattern().exactMatch(name); + if (matchesWinDevice) { + if (errorMessage) + *errorMessage = tr("The name must not match that of a MS Windows device. (%1)."). + arg(windowsDeviceNoSubDirPattern().pattern().replace(QLatin1Char('|'), QLatin1Char(','))); + return false; } return true; } bool FileNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const { - return validateFileName(value, errorMessage); + return validateFileName(value, m_allowDirectories, errorMessage); } } // namespace Utils diff --git a/src/libs/utils/filenamevalidatinglineedit.h b/src/libs/utils/filenamevalidatinglineedit.h index 5476e3cd5e9..042a48fc5f1 100644 --- a/src/libs/utils/filenamevalidatinglineedit.h +++ b/src/libs/utils/filenamevalidatinglineedit.h @@ -43,14 +43,23 @@ class QWORKBENCH_UTILS_EXPORT FileNameValidatingLineEdit : public BaseValidating { Q_OBJECT Q_DISABLE_COPY(FileNameValidatingLineEdit) - + Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories) public: explicit FileNameValidatingLineEdit(QWidget *parent = 0); - static bool validateFileName(const QString &name, QString *errorMessage /* = 0*/); + static bool validateFileName(const QString &name, + bool allowDirectories = false, + QString *errorMessage = 0); + + bool allowDirectories() const; + void setAllowDirectories(bool v); protected: virtual bool validate(const QString &value, QString *errorMessage) const; + +private: + bool m_allowDirectories; + void *m_unused; }; } // namespace Utils diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp index 8a12e4c0f3c..3e85b34d44b 100644 --- a/src/libs/utils/filewizardpage.cpp +++ b/src/libs/utils/filewizardpage.cpp @@ -123,7 +123,7 @@ void FileWizardPage::slotActivated() bool FileWizardPage::validateBaseName(const QString &name, QString *errorMessage /* = 0*/) { - return FileNameValidatingLineEdit::validateFileName(name, errorMessage); + return FileNameValidatingLineEdit::validateFileName(name, false, errorMessage); } } // namespace Utils diff --git a/src/libs/utils/newclasswidget.cpp b/src/libs/utils/newclasswidget.cpp index df7d81e7b39..b34ee40d4fe 100644 --- a/src/libs/utils/newclasswidget.cpp +++ b/src/libs/utils/newclasswidget.cpp @@ -346,6 +346,21 @@ void NewClassWidget::setFormExtension(const QString &e) m_d->m_formExtension = fixSuffix(e); } +bool NewClassWidget::allowDirectories() const +{ + return m_d->m_ui.headerFileLineEdit->allowDirectories(); +} + +void NewClassWidget::setAllowDirectories(bool v) +{ + // We keep all in sync + if (allowDirectories() != v) { + m_d->m_ui.sourceFileLineEdit->setAllowDirectories(v); + m_d->m_ui.headerFileLineEdit->setAllowDirectories(v); + m_d->m_ui.formFileLineEdit->setAllowDirectories(v); + } +} + void NewClassWidget::slotValidChanged() { const bool newValid = isValid(); diff --git a/src/libs/utils/newclasswidget.h b/src/libs/utils/newclasswidget.h index 04c2aaf58a4..40c850d28e9 100644 --- a/src/libs/utils/newclasswidget.h +++ b/src/libs/utils/newclasswidget.h @@ -73,6 +73,7 @@ class QWORKBENCH_UTILS_EXPORT NewClassWidget : public QWidget Q_PROPERTY(QString formExtension READ formExtension WRITE setFormExtension DESIGNABLE true) Q_PROPERTY(bool formInputCheckable READ formInputCheckable WRITE setFormInputCheckable DESIGNABLE true) Q_PROPERTY(bool formInputChecked READ formInputChecked WRITE setFormInputChecked DESIGNABLE true) + Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories) // Utility "USER" property for wizards containing file names. Q_PROPERTY(QStringList files READ files DESIGNABLE false USER true) public: @@ -97,7 +98,7 @@ public: QString sourceExtension() const; QString headerExtension() const; QString formExtension() const; - + bool allowDirectories() const; bool isValid(QString *error = 0) const; @@ -125,6 +126,7 @@ public slots: void setSourceExtension(const QString &e); void setHeaderExtension(const QString &e); void setFormExtension(const QString &e); + void setAllowDirectories(bool v); /* Suggest a class name from the base class by stripping the leading 'Q' * character. This will happen automagically if the base class combo diff --git a/src/libs/utils/projectnamevalidatinglineedit.cpp b/src/libs/utils/projectnamevalidatinglineedit.cpp index df77af8e832..4160bc18792 100644 --- a/src/libs/utils/projectnamevalidatinglineedit.cpp +++ b/src/libs/utils/projectnamevalidatinglineedit.cpp @@ -45,7 +45,7 @@ ProjectNameValidatingLineEdit::ProjectNameValidatingLineEdit(QWidget *parent) bool ProjectNameValidatingLineEdit::validateProjectName(const QString &name, QString *errorMessage /* = 0*/) { // Validation is file name + checking for dots - if (!FileNameValidatingLineEdit::validateFileName(name, errorMessage)) + if (!FileNameValidatingLineEdit::validateFileName(name, false, errorMessage)) return false; // We don't want dots in the directory name for some legacy Windows diff --git a/src/plugins/cppeditor/cppclasswizard.cpp b/src/plugins/cppeditor/cppclasswizard.cpp index 6730f5b9ed9..652eec535f1 100644 --- a/src/plugins/cppeditor/cppclasswizard.cpp +++ b/src/plugins/cppeditor/cppclasswizard.cpp @@ -73,6 +73,7 @@ ClassNamePage::ClassNamePage(const QString &sourceSuffix, m_newClassWidget->setBaseClassEditable(true); m_newClassWidget->setFormInputVisible(false); m_newClassWidget->setNamespacesEnabled(true); + m_newClassWidget->setAllowDirectories(true); connect(m_newClassWidget, SIGNAL(validChanged()), this, SLOT(slotValidChanged())); diff --git a/src/plugins/designer/cpp/formclasswizardpage.cpp b/src/plugins/designer/cpp/formclasswizardpage.cpp index d076753374b..eac7271b404 100644 --- a/src/plugins/designer/cpp/formclasswizardpage.cpp +++ b/src/plugins/designer/cpp/formclasswizardpage.cpp @@ -63,6 +63,7 @@ FormClassWizardPage::FormClassWizardPage(QWidget * parent) : m_ui->newClassWidget->setBaseClassInputVisible(false); m_ui->newClassWidget->setNamespacesEnabled(true); + m_ui->newClassWidget->setAllowDirectories(true); connect(m_ui->newClassWidget, SIGNAL(validChanged()), this, SLOT(slotValidChanged())); From f9fbfb8f8322b8c8d7eb22100cb2c9e27b7ca871 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 5 Dec 2008 11:24:18 +0100 Subject: [PATCH 02/41] increas alert time for breakpoints to 300 --- src/plugins/debugger/gdbengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 80d0a046fc3..1802c018001 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1276,7 +1276,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; - QApplication::alert(q->mainWindow(), 200); + QApplication::alert(q->mainWindow(), 3000); sendCommand("-file-list-exec-source-files", GdbQuerySources); sendCommand("-break-list", BreakList); QVariant var = QVariant::fromValue(data); From 0c3a7df7465890a4634051aa2dad83ce9eeb0c0a Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Thu, 4 Dec 2008 17:27:29 +0100 Subject: [PATCH 03/41] Fixes: More documentation fixes (cherry picked from commit a02c5e61962a64ca3ebe455f9b7f1b67cb338515) --- doc/qtcreator.qdoc | 80 ++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index a1f7ab3ed6f..4521b7e2fa4 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -814,21 +814,26 @@ a pointer to some private data structure, you will see a list of children, signals and slots. - Similarily, instead of showing a bunch of pointers and ints, - a QHash or QMap will display its contents in an orderly fashion, - a QFileInfo will expose e.g. access data, and the otherwise - "opaque" QVariant gives access to the "real" contents. + Similarly, instead of displaying many pointers and integers, Qt Creator's + debugger will display the contents of a QHash or QMap in an orderly manner. + Also, the debugger will display access data for QFileInfo and provide + access to the "real" contents of QVariant. - The \gui{Locals and Watchers View} can be used to change the - contents of variables of simple data types like int or float - while the program is stopped. To do so, click into the 'Value' - column, modify the value there, and hit \key{Return}. + The \gui{Locals and Watchers} view can be used to change the contents of + variables of simple data types such as \c int or \c float when the program + is stopped. To do so, click on the \gui Value column, modify the value + with the inplace editor, and hit \key Enter (or \key Return). - \section2 Modules - The \gui{Modules View} is hidden by default and only useful in + By default, the \gui Modules view is hidden as it is only useful with the + experimental delayed debug information loading feature. You can turn this + feature on by selecting \gui{Fast Debugger Start} + + + + The \gui Modules view is hidden by default and only useful in connection with the experimental feature of delayed debug information loading. This feature is accessible by selecting \gui{Debug} and \gui{Fast Debugger Start}. When using the @@ -849,29 +854,28 @@ commands + \section1 A Walkthrough for the Debugger Frontend - \section1 A short walk through the debugger frontend - - In our \l{Writing a Simple Program with Qt Creator}{TextFinder} - example, we read a text file into a QString and then display it with a - QTextEdit. Suppose, you would like to look at this QString, \c{line}, - and see what data it actually stores. Follow the steps described below - to place a break point and view the QString object's data. + In our \l{Writing a Simple Program with Qt Creator}{TextFinder} example, we + read a text file into a QString and then display it with a QTextEdit. + Suppose, you would like to look at this QString, \c{line}, and see what + data it actually stores. Follow the steps described below to place a + breakpoint and view the QString object's data. \table \row - \i \inlineimage qtcreator-setting-breakpoint1.png + \i \inlineimage qtcreator-setting-breakpoint1.png \i \bold{Setting a Breakpoint} First, we set a breakpoint on the line where we invoke - \l{QTextEdit::}{setPlainText()} by clicking between the line number and - the window border. Then, select \gui{Start Debugging} from the - \gui{Debug} menu or press \key{F5}. + \l{QTextEdit::}{setPlainText()} by clicking between the line number and the + window border. Then, select \gui{Start Debugging} from the \gui{Debug} menu + or press \key{F5}. \endtable Breakpoints are visible in the \gui{Breakpoints} view, shown below, in - \gui{Debug} mode. If you wish to remove a breakpoint, simply right - click on it and select \gui{Delete breakpoint} from the context menu. + \gui{Debug} mode. If you wish to remove a breakpoint, simply right-click on + it and select \gui{Delete breakpoint} from the context menu. \image qtcreator-setting-breakpoint2.png @@ -880,10 +884,10 @@ \image qtcreator-watcher.png - Suppose we modify our \c{on_findButton_clicked()} function to move back - to the start of the document and continue searching once the cursor - hits the end of the document. Adding this functionality can be done - with the code snippet below: + Suppose we modify our \c{on_findButton_clicked()} function to move back to + the start of the document and continue searching once the cursor hits the + end of the document. Adding this functionality can be done with the code + snippet below: \code void TextFinder::on_findButton_clicked() @@ -915,9 +919,9 @@ } \endcode - However, if you compile and run this code, the application will not - work correctly due to a logic error. To locate this logic error, you - can step through the code using the following buttons: + However, if you compile and run this code, the application will not work + correctly due to a logic error. To locate this logic error, you can step + through the code using the following buttons: \image qtcreator-debugging-buttons.png */ @@ -931,20 +935,20 @@ \title Tips and Tricks - \bold{Quick mode switch} + \bold{Quickly Switching between Modes} You can quickly switch between modes by pressing \key{Ctrl+1}, - \key{Ctrl+2}, etc. + \key{Ctrl+2}, and so on. - \bold{Other keyboard shortcuts} + \bold{Keyboard Shortcuts} - There are a lot of other \l{keyboard-shortcuts}{keyboard shortcuts}. + Qt Creator provides a lot of useful keyboard shortcuts. A complete list can + be found \l{Keyboard Shortcuts}{here}. - \bold{Command line} + \bold{Running Qt Creator from the Command Line} - You can start Qt Creator from a command prompt with an already - existing session or \c{.pro} file by giving the name as argument on the - command line. + You can start Qt Creator from a command prompt with an existing session or + \c{.pro} file by giving the name as argument on the command line. \bold{Sidebar} From 786e183aa67729e4d465bab77c77c394a231b85f Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 5 Dec 2008 12:12:20 +0100 Subject: [PATCH 04/41] markContextMenuRequested signal in ITextEditor --- src/plugins/texteditor/basetexteditor.cpp | 9 +++------ src/plugins/texteditor/basetexteditor.h | 2 -- src/plugins/texteditor/itexteditor.h | 2 ++ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 1e6a266e6da..ea9da5cb6bd 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -488,10 +488,6 @@ ITextEditable *BaseTextEditor::editableInterface() const d->m_editable, SIGNAL(contentsChanged())); connect(this, SIGNAL(changed()), d->m_editable, SIGNAL(changed())); - connect(this, - SIGNAL(markRequested(TextEditor::ITextEditor *, int)), - d->m_editable, - SIGNAL(markRequested(TextEditor::ITextEditor *, int))); } return d->m_editable; } @@ -2434,9 +2430,10 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) } } else if (e->button() == Qt::RightButton) { QMenu * contextMenu = new QMenu(this); - emit lineContextMenuRequested(editableInterface(), cursor.blockNumber(), contextMenu); + emit d->m_editable->markContextMenuRequested(editableInterface(), cursor.blockNumber(), contextMenu); if (!contextMenu->isEmpty()) contextMenu->exec(e->globalPos()); + delete contextMenu; } } else if (d->extraAreaSelectionAnchorBlockNumber >= 0) { QTextCursor selection = cursor; @@ -2471,7 +2468,7 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) d->extraAreaToggleMarkBlockNumber = -1; if (cursor.blockNumber() == n) { int line = n + 1; - emit markRequested(editableInterface(), line); + emit d->m_editable->markRequested(editableInterface(), line); } } } diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index a6cc14f36e4..714b1a507c8 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -431,8 +431,6 @@ protected slots: signals: - void markRequested(TextEditor::ITextEditor *editor, int line); - void lineContextMenuRequested(TextEditor::ITextEditor *editor, int line, QMenu *menu); void requestBlockUpdate(const QTextBlock &); void requestAutoCompletion(ITextEditable *editor, bool forced); diff --git a/src/plugins/texteditor/itexteditor.h b/src/plugins/texteditor/itexteditor.h index 432c3c9c585..514f311472a 100644 --- a/src/plugins/texteditor/itexteditor.h +++ b/src/plugins/texteditor/itexteditor.h @@ -44,6 +44,7 @@ #include QT_BEGIN_NAMESPACE +class QMenu; class QTextBlock; QT_END_NAMESPACE @@ -124,6 +125,7 @@ public: signals: void contentsChanged(); void markRequested(TextEditor::ITextEditor *editor, int line); + void markContextMenuRequested(TextEditor::ITextEditor *editor, int line, QMenu *menu); void tooltipRequested(TextEditor::ITextEditor *editor, const QPoint &globalPos, int position); void contextHelpIdRequested(TextEditor::ITextEditor *editor, int position); }; From 5c6be3a83cf5045b2584a46fe1661a09251df851 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 5 Dec 2008 12:19:04 +0100 Subject: [PATCH 05/41] Fixes: Do not display f1, f2 while waiting for wizard extension page data --- src/plugins/projectexplorer/projectwizardpage.ui | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/projectwizardpage.ui b/src/plugins/projectexplorer/projectwizardpage.ui index bc31f8c49e1..7c21ec5a910 100644 --- a/src/plugins/projectexplorer/projectwizardpage.ui +++ b/src/plugins/projectexplorer/projectwizardpage.ui @@ -104,8 +104,9 @@ The following files will be added: -f1 -f2 + + + From 6d37029be86594ce1721452c49a04d04d6e5b879 Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 5 Dec 2008 13:19:57 +0100 Subject: [PATCH 06/41] support different selection kinds in basetexteditor. enum ExtraSelectionKind { CurrentLineSelection, ParenthesesMatchingSelection, CodeWarningsSelection, CodeSemanticsSelection, OtherSelection, NExtraSelectionKinds }; void setExtraSelections(ExtraSelectionKind kind, const QList &selections); QList extraSelections(ExtraSelectionKind kind) const; This is mainly for the benefit of the cppmodelmanager. --- src/plugins/cpptools/cppmodelmanager.cpp | 2 +- src/plugins/texteditor/basetexteditor.cpp | 30 +++++++++++++---------- src/plugins/texteditor/basetexteditor.h | 13 +++++++--- src/plugins/texteditor/basetexteditor_p.h | 3 +-- src/plugins/vcsbase/vcsbaseeditor.cpp | 21 ++++------------ 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index b3f9fb604c3..042b93cc74d 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -683,7 +683,7 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc) sel.cursor = c; selections.append(sel); } - ed->setExtraExtraSelections(selections); + ed->setExtraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection, selections); break; } } diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index ea9da5cb6bd..49d29b75c93 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -2477,6 +2477,9 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) void BaseTextEditor::slotCursorPositionChanged() { QList extraSelections; + setExtraSelections(ParenthesesMatchingSelection, extraSelections); // clear + if (d->m_parenthesesMatchingEnabled) + d->m_parenthesesMatchingTimer->start(50); if (d->m_highlightCurrentLine) { QTextEdit::ExtraSelection sel; @@ -2487,11 +2490,7 @@ void BaseTextEditor::slotCursorPositionChanged() extraSelections.append(sel); } - if (d->m_parenthesesMatchingEnabled) - d->m_parenthesesMatchingTimer->start(50); - - d->m_extraSelections = extraSelections; - setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections); + setExtraSelections(CurrentLineSelection, extraSelections); } QTextBlock TextBlockUserData::testCollapse(const QTextBlock& block) @@ -3133,7 +3132,7 @@ void BaseTextEditor::_q_matchParentheses() if (backwardMatchType == TextBlockUserData::NoMatch && forwardMatchType == TextBlockUserData::NoMatch) return; - QList extraSelections = d->m_extraSelections; + QList extraSelections; if (backwardMatch.hasSelection()) { QTextEdit::ExtraSelection sel; @@ -3186,8 +3185,7 @@ void BaseTextEditor::_q_matchParentheses() } extraSelections.append(sel); } - d->m_extraSelections = extraSelections; - setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections); + setExtraSelections(ParenthesesMatchingSelection, extraSelections); } void BaseTextEditor::setActionHack(QObject *hack) @@ -3234,15 +3232,21 @@ void BaseTextEditor::deleteLine() cut(); } -void BaseTextEditor::setExtraExtraSelections(const QList &selections) +void BaseTextEditor::setExtraSelections(ExtraSelectionKind kind, const QList &selections) { - d->m_extraExtraSelections = selections; - setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections); + if (selections.isEmpty() && d->m_extraSelections[kind].isEmpty()) + return; + d->m_extraSelections[kind] = selections; + + QList all; + for (int i = 0; i < NExtraSelectionKinds; ++i) + all += d->m_extraSelections[i]; + QPlainTextEdit::setExtraSelections(all); } -QList BaseTextEditor::extraExtraSelections() const +QList BaseTextEditor::extraSelections(ExtraSelectionKind kind) const { - return d->m_extraExtraSelections; + return d->m_extraSelections[kind]; } diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index 714b1a507c8..40454a9c7d4 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -369,7 +369,6 @@ private: Internal::BaseTextEditorPrivate *d; friend class Internal::BaseTextEditorPrivate; - public: QWidget *extraArea() const; virtual int extraAreaWidth(int *markWidthPtr = 0) const; @@ -385,8 +384,16 @@ public: void ensureCursorVisible(); - void setExtraExtraSelections(const QList &selections); - QList extraExtraSelections() const; + enum ExtraSelectionKind { + CurrentLineSelection, + ParenthesesMatchingSelection, + CodeWarningsSelection, + CodeSemanticsSelection, + OtherSelection, + NExtraSelectionKinds + }; + void setExtraSelections(ExtraSelectionKind kind, const QList &selections); + QList extraSelections(ExtraSelectionKind kind) const; struct BlockRange { BlockRange():first(0), last(-1){} diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h index 56b1071e1c6..9f1e5a7eb67 100644 --- a/src/plugins/texteditor/basetexteditor_p.h +++ b/src/plugins/texteditor/basetexteditor_p.h @@ -204,8 +204,7 @@ public: QObject *m_actionHack; - QList m_extraSelections; - QList m_extraExtraSelections; + QList m_extraSelections[BaseTextEditor::NExtraSelectionKinds]; // block selection mode bool m_inBlockSelectionMode; diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index dcfe55d195b..eb65457c109 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -225,23 +225,12 @@ void VCSBaseEditor::mouseMoveEvent(QMouseEvent *e) sel.format.setFontUnderline(true); change = changeUnderCursor(cursor); sel.format.setProperty(QTextFormat::UserProperty, change); - bool found = false; - foreach (QTextEdit::ExtraSelection es, extraSelections()) { - if (es.format.stringProperty(QTextFormat::UserProperty) == sel.format.stringProperty(QTextFormat::UserProperty)) { - found = true; - break; - } - } - if (!found) { - setExtraSelections(QList() << sel); - viewport()->setCursor(Qt::PointingHandCursor); - } - } else { - if (!extraSelections().isEmpty()) { - setExtraSelections(QList()); - viewport()->setCursor(Qt::IBeamCursor); - } + setExtraSelections(OtherSelection, QList() << sel); + viewport()->setCursor(Qt::PointingHandCursor); } + } else { + setExtraSelections(OtherSelection, QList()); + viewport()->setCursor(Qt::IBeamCursor); } TextEditor::BaseTextEditor::mouseMoveEvent(e); } From ecfb77d469e3410f06c093a7696fe8939f4f0632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 5 Dec 2008 12:21:18 +0100 Subject: [PATCH 07/41] Separate scope in classes quickopen filter The scope of the classes is now separated and displayed in the second column, and not included in the search. --- src/libs/cplusplus/Icons.cpp | 4 +- src/libs/cplusplus/Icons.h | 2 +- src/libs/utils/pathchooser.h | 1 + src/plugins/cpptools/cppclassesfilter.cpp | 1 + src/plugins/cpptools/searchsymbols.cpp | 79 +++++++++++++++-------- src/plugins/cpptools/searchsymbols.h | 14 ++++ 6 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp index 94b6469ea46..3b7ee24da3c 100644 --- a/src/libs/cplusplus/Icons.cpp +++ b/src/libs/cplusplus/Icons.cpp @@ -61,11 +61,11 @@ Icons::Icons() { } -QIcon Icons::iconForSymbol(Symbol *symbol) const +QIcon Icons::iconForSymbol(const Symbol *symbol) const { if (symbol->isFunction() || (symbol->isDeclaration() && symbol->type()->isFunction())) { - Function *function = symbol->asFunction(); + const Function *function = symbol->asFunction(); if (!function) function = symbol->type()->asFunction(); diff --git a/src/libs/cplusplus/Icons.h b/src/libs/cplusplus/Icons.h index c49bcde12d1..6d4e0bb25d6 100644 --- a/src/libs/cplusplus/Icons.h +++ b/src/libs/cplusplus/Icons.h @@ -47,7 +47,7 @@ class CPLUSPLUS_EXPORT Icons public: Icons(); - QIcon iconForSymbol(Symbol *symbol) const; + QIcon iconForSymbol(const Symbol *symbol) const; QIcon keywordIcon() const; QIcon macroIcon() const; diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index 7ae60a255bf..ab821d5df1e 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -30,6 +30,7 @@ ** version 1.2, included in the file GPL_EXCEPTION.txt in this package. ** ***************************************************************************/ + #ifndef PATHCHOOSER_H #define PATHCHOOSER_H diff --git a/src/plugins/cpptools/cppclassesfilter.cpp b/src/plugins/cpptools/cppclassesfilter.cpp index 3d8da9a7387..6aa6734fca9 100644 --- a/src/plugins/cpptools/cppclassesfilter.cpp +++ b/src/plugins/cpptools/cppclassesfilter.cpp @@ -42,6 +42,7 @@ CppClassesFilter::CppClassesFilter(CppModelManager *manager, Core::EditorManager setIncludedByDefault(false); search.setSymbolsToSearchFor(SearchSymbols::Classes); + search.setSeparateScope(true); } CppClassesFilter::~CppClassesFilter() diff --git a/src/plugins/cpptools/searchsymbols.cpp b/src/plugins/cpptools/searchsymbols.cpp index 4b1e48abdf7..670d0d6d471 100644 --- a/src/plugins/cpptools/searchsymbols.cpp +++ b/src/plugins/cpptools/searchsymbols.cpp @@ -40,7 +40,8 @@ using namespace CPlusPlus; using namespace CppTools::Internal; SearchSymbols::SearchSymbols(): - symbolsToSearchFor(Classes | Functions | Enums) + symbolsToSearchFor(Classes | Functions | Enums), + separateScope(false) { } @@ -49,6 +50,11 @@ void SearchSymbols::setSymbolsToSearchFor(SymbolTypes types) symbolsToSearchFor = types; } +void SearchSymbols::setSeparateScope(bool separateScope) +{ + this->separateScope = separateScope; +} + QList SearchSymbols::operator()(Document::Ptr doc, const QString &scope) { QString previousScope = switchScope(scope); @@ -73,13 +79,12 @@ bool SearchSymbols::visit(Enum *symbol) return false; QString name = symbolName(symbol); - QString previousScope = switchScope(name); - QIcon icon = icons.iconForSymbol(symbol); + QString scopedName = scopedSymbolName(name); + QString previousScope = switchScope(scopedName); + appendItem(separateScope ? name : scopedName, + separateScope ? previousScope : QString(), + ModelItemInfo::Enum, symbol); Scope *members = symbol->members(); - items.append(ModelItemInfo(name, QString(), ModelItemInfo::Enum, - QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()), - symbol->line(), - icon)); for (unsigned i = 0; i < members->symbolCount(); ++i) { accept(members->symbolAt(i)); } @@ -93,18 +98,18 @@ bool SearchSymbols::visit(Function *symbol) return false; QString name = symbolName(symbol); - QString type = overview.prettyType(symbol->type()); - QIcon icon = icons.iconForSymbol(symbol); - items.append(ModelItemInfo(name, type, ModelItemInfo::Method, - QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()), - symbol->line(), - icon)); + QString scopedName = scopedSymbolName(name); + QString type = overview.prettyType(symbol->type(), + separateScope ? symbol->name() : 0); + appendItem(separateScope ? type : scopedName, + separateScope ? _scope : type, + ModelItemInfo::Method, symbol); return false; } bool SearchSymbols::visit(Namespace *symbol) { - QString name = symbolName(symbol); + QString name = findOrInsert(scopedSymbolName(symbol)); QString previousScope = switchScope(name); Scope *members = symbol->members(); for (unsigned i = 0; i < members->symbolCount(); ++i) { @@ -118,12 +123,9 @@ bool SearchSymbols::visit(Namespace *symbol) bool SearchSymbols::visit(Declaration *symbol) { if (symbol->type()->isFunction()) { - QString name = symbolName(symbol); + QString name = scopedSymbolName(symbol); QString type = overview.prettyType(symbol->type()); - //QIcon icon = ...; - items.append(ModelItemInfo(name, type, ModelItemInfo::Method, - QString::fromUtf8(symbol->fileName(), symbol->line()), - symbol->line())); + appendItems(name, type, ModelItemInfo::Method, symbol->fileName()); } return false; } @@ -135,12 +137,11 @@ bool SearchSymbols::visit(Class *symbol) return false; QString name = symbolName(symbol); - QString previousScope = switchScope(name); - QIcon icon = icons.iconForSymbol(symbol); - items.append(ModelItemInfo(name, QString(), ModelItemInfo::Class, - QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()), - symbol->line(), - icon)); + QString scopedName = scopedSymbolName(name); + QString previousScope = switchScope(scopedName); + appendItem(separateScope ? name : scopedName, + separateScope ? previousScope : QString(), + ModelItemInfo::Class, symbol); Scope *members = symbol->members(); for (unsigned i = 0; i < members->symbolCount(); ++i) { accept(members->symbolAt(i)); @@ -149,11 +150,22 @@ bool SearchSymbols::visit(Class *symbol) return false; } -QString SearchSymbols::symbolName(const Symbol *symbol) const +QString SearchSymbols::scopedSymbolName(const QString &symbolName) const { QString name = _scope; if (! name.isEmpty()) name += QLatin1String("::"); + name += symbolName; + return name; +} + +QString SearchSymbols::scopedSymbolName(const Symbol *symbol) const +{ + return scopedSymbolName(symbolName(symbol)); +} + +QString SearchSymbols::symbolName(const Symbol *symbol) const +{ QString symbolName = overview.prettyName(symbol->name()); if (symbolName.isEmpty()) { QString type; @@ -176,6 +188,17 @@ QString SearchSymbols::symbolName(const Symbol *symbol) const symbolName += type; symbolName += QLatin1String(">"); } - name += symbolName; - return name; + return symbolName; +} + +void SearchSymbols::appendItem(const QString &name, + const QString &info, + ModelItemInfo::ItemType type, + const CPlusPlus::Symbol *symbol) +{ + const QIcon icon = icons.iconForSymbol(symbol); + items.append(ModelItemInfo(name, info, type, + QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()), + symbol->line(), + icon)); } diff --git a/src/plugins/cpptools/searchsymbols.h b/src/plugins/cpptools/searchsymbols.h index 948f9d78e84..d82f2859721 100644 --- a/src/plugins/cpptools/searchsymbols.h +++ b/src/plugins/cpptools/searchsymbols.h @@ -90,6 +90,7 @@ public: SearchSymbols(); void setSymbolsToSearchFor(SymbolTypes types); + void setSeparateScope(bool separateScope); QList operator()(CPlusPlus::Document::Ptr doc) { return operator()(doc, QString()); } @@ -111,14 +112,27 @@ protected: virtual bool visit(CPlusPlus::Declaration *symbol); #endif virtual bool visit(CPlusPlus::Class *symbol); + + QString scopedSymbolName(const QString &symbolName) const; + QString scopedSymbolName(const CPlusPlus::Symbol *symbol) const; QString symbolName(const CPlusPlus::Symbol *symbol) const; + void appendItem(const QString &name, + const QString &info, + ModelItemInfo::ItemType type, + const CPlusPlus::Symbol *symbol); private: + QString findOrInsert(const QString &s) + { return *strings.insert(s); } + + QSet strings; // Used to avoid QString duplication + QString _scope; CPlusPlus::Overview overview; CPlusPlus::Icons icons; QList items; SymbolTypes symbolsToSearchFor; + bool separateScope; }; Q_DECLARE_OPERATORS_FOR_FLAGS(SearchSymbols::SymbolTypes) From d6e726ec68968c0bd64cc2d3350394afe808608a Mon Sep 17 00:00:00 2001 From: dt Date: Fri, 5 Dec 2008 14:29:18 +0100 Subject: [PATCH 08/41] Fixes: Memory usage for loading projects.pro Details: Free the whole ProFile*, ProItem*, ProValue* and etc structure after parsing, that frees around 200Mb for projects.pro. --- .../qt4projectmanager/profilereader.cpp | 32 ++-- src/plugins/qt4projectmanager/profilereader.h | 2 +- src/plugins/qt4projectmanager/qt4nodes.cpp | 175 +++++++++--------- src/plugins/qt4projectmanager/qt4nodes.h | 21 +-- src/plugins/qt4projectmanager/qt4project.cpp | 39 ++-- src/plugins/qt4projectmanager/qt4project.h | 2 +- 6 files changed, 126 insertions(+), 145 deletions(-) diff --git a/src/plugins/qt4projectmanager/profilereader.cpp b/src/plugins/qt4projectmanager/profilereader.cpp index 0e7dd7ece2a..9f65cc890d0 100644 --- a/src/plugins/qt4projectmanager/profilereader.cpp +++ b/src/plugins/qt4projectmanager/profilereader.cpp @@ -61,14 +61,6 @@ void ProFileReader::setQtVersion(QtVersion *qtVersion) { bool ProFileReader::readProFile(const QString &fileName) { //disable caching -> list of include files is not updated otherwise -// ProFile *pro = proFileFromCache(fileName); -// if (!pro) { -// pro = new ProFile(fileName); -// if (!queryProFile(pro)) { -// delete pro; -// return false; -// } -// } QString fn = QFileInfo(fileName).filePath(); ProFile *pro = new ProFile(fn); if (!queryProFile(pro)) { @@ -82,9 +74,6 @@ bool ProFileReader::readProFile(const QString &fileName) ProFile *ProFileReader::parsedProFile(const QString &fileName) { -// ProFile *pro = proFileFromCache(fileName); -// if (pro) -// return pro; QString fn = QFileInfo(fileName).filePath(); ProFile *pro = ProFileEvaluator::parsedProFile(fn); if (pro) { @@ -99,16 +88,6 @@ void ProFileReader::releaseParsedProFile(ProFile *) return; } -ProFile *ProFileReader::proFileFromCache(const QString &fileName) const -{ - - QString fn = QFileInfo(fileName).filePath(); - ProFile *pro = 0; - if (m_includeFiles.contains(fn)) - pro = m_includeFiles.value(fn); - return pro; -} - QList ProFileReader::includeFiles() const { QString qmakeMkSpecDir = propertyValue("QMAKE_MKSPECS"); @@ -196,3 +175,14 @@ void ProFileReader::errorMessage(const QString &message) { emit errorFound(message); } + +ProFile *ProFileReader::proFileFor(const QString &name) +{ + qDebug()<<"Asking for "<::const_iterator it = m_includeFiles.constFind(name); + if (it == m_includeFiles.constEnd()) + return 0; + else + return it.value(); +} diff --git a/src/plugins/qt4projectmanager/profilereader.h b/src/plugins/qt4projectmanager/profilereader.h index 46e1f600386..ace88866041 100644 --- a/src/plugins/qt4projectmanager/profilereader.h +++ b/src/plugins/qt4projectmanager/profilereader.h @@ -63,7 +63,7 @@ public: const QString &baseDirectory, PathValuesMode mode, const ProFile *pro = 0) const; - ProFile *proFileFromCache(const QString &fileName) const; + ProFile *proFileFor(const QString &name); signals: void errorFound(const QString &error); diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 8c4010aac5e..73e3620f9bc 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -79,35 +79,22 @@ namespace { Implements abstract ProjectNode class */ -Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, - const QString &filePath) +Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNode, const QString &filePath) : ProjectNode(filePath), - m_core(project->qt4ProjectManager()->core()), m_project(project), + m_qt4ProFileNode(qt4ProFileNode), m_projectFilePath(QDir::fromNativeSeparators(filePath)), - m_projectDir(QFileInfo(filePath).absolutePath()), - m_includeFile(0), - m_saveTimer(new QTimer(this)), - m_reader(0) + m_projectDir(QFileInfo(filePath).absolutePath()) { Q_ASSERT(project); setFolderName(QFileInfo(filePath).baseName()); setIcon(QIcon(":/qt4projectmanager/images/qt_project.png")); - - // m_saveTimer is used for the delayed saving of the pro file - // so that multiple insert/remove calls in one event loop run - // trigger just one save call. - m_saveTimer->setSingleShot(true); - connect(m_saveTimer, SIGNAL(timeout()), this, SLOT(save())); } void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader) { Q_ASSERT(includeFile); Q_ASSERT(reader); - m_reader = reader; - - m_includeFile = includeFile; // add project file node if (m_fileNodes.isEmpty()) @@ -175,47 +162,42 @@ void Qt4PriFileNode::update(ProFile *includeFile, ProFileReader *reader) QList Qt4PriFileNode::supportedActions() const { QList actions; - if (m_includeFile) { - const FolderNode *folderNode = this; - const Qt4ProFileNode *proFileNode; - while (!(proFileNode = qobject_cast(folderNode))) - folderNode = folderNode->parentFolderNode(); - Q_ASSERT(proFileNode); - switch (proFileNode->projectType()) { - case ApplicationTemplate: - case LibraryTemplate: - actions << AddFile << RemoveFile; - break; - case SubDirsTemplate: - actions << AddSubProject << RemoveSubProject; - break; - default: - break; - } + const FolderNode *folderNode = this; + const Qt4ProFileNode *proFileNode; + while (!(proFileNode = qobject_cast(folderNode))) + folderNode = folderNode->parentFolderNode(); + Q_ASSERT(proFileNode); + + switch (proFileNode->projectType()) { + case ApplicationTemplate: + case LibraryTemplate: + actions << AddFile << RemoveFile; + break; + case SubDirsTemplate: + actions << AddSubProject << RemoveSubProject; + break; + default: + break; } return actions; } bool Qt4PriFileNode::addSubProjects(const QStringList &proFilePaths) { - if (!m_includeFile) - return false; - return changeIncludes(m_includeFile, proFilePaths, AddToProFile); + Q_UNUSED(proFilePaths); + return false; //changeIncludes(m_includeFile, proFilePaths, AddToProFile); } bool Qt4PriFileNode::removeSubProjects(const QStringList &proFilePaths) { - if (!m_includeFile) - return false; - return changeIncludes(m_includeFile, proFilePaths, RemoveFromProFile); + Q_UNUSED(proFilePaths); + return false; //changeIncludes(m_includeFile, proFilePaths, RemoveFromProFile); } bool Qt4PriFileNode::addFiles(const FileType fileType, const QStringList &filePaths, QStringList *notAdded) { - if (!m_includeFile) - return false; QStringList failedFiles; changeFiles(fileType, filePaths, &failedFiles, AddToProFile); @@ -227,8 +209,6 @@ bool Qt4PriFileNode::addFiles(const FileType fileType, const QStringList &filePa bool Qt4PriFileNode::removeFiles(const FileType fileType, const QStringList &filePaths, QStringList *notRemoved) { - if (!m_includeFile) - return false; QStringList failedFiles; changeFiles(fileType, filePaths, &failedFiles, RemoveFromProFile); if (notRemoved) @@ -239,7 +219,7 @@ bool Qt4PriFileNode::removeFiles(const FileType fileType, const QStringList &fil bool Qt4PriFileNode::renameFile(const FileType fileType, const QString &filePath, const QString &newFilePath) { - if (!m_includeFile || newFilePath.isEmpty()) + if (newFilePath.isEmpty()) return false; if (!QFile::rename(filePath, newFilePath)) @@ -268,18 +248,19 @@ bool Qt4PriFileNode::changeIncludes(ProFile *includeFile, const QStringList &pro bool Qt4PriFileNode::priFileWritable(const QString &path) { const QString dir = QFileInfo(path).dir().path(); - Core::IVersionControl *versionControl = m_core->vcsManager()->findVersionControlForDirectory(dir); - switch (Core::EditorManager::promptReadOnlyFile(path, versionControl, m_core->mainWindow(), false)) { + Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); + Core::IVersionControl *versionControl = core->vcsManager()->findVersionControlForDirectory(dir); + switch (Core::EditorManager::promptReadOnlyFile(path, versionControl, core->mainWindow(), false)) { case Core::EditorManager::RO_OpenVCS: if (!versionControl->vcsOpen(path)) { - QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC.")); + QMessageBox::warning(core->mainWindow(), tr("Failed!"), tr("Could not open the file for edit with SCC.")); return false; } break; case Core::EditorManager::RO_MakeWriteable: { const bool permsOk = QFile::setPermissions(path, QFile::permissions(path) | QFile::WriteUser); if (!permsOk) { - QMessageBox::warning(m_core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable.")); + QMessageBox::warning(core->mainWindow(), tr("Failed!"), tr("Could not set permissions to writable.")); return false; } break; @@ -296,11 +277,13 @@ bool Qt4PriFileNode::saveModifiedEditors(const QString &path) QList allFileHandles; QList modifiedFileHandles; - foreach (Core::IFile *file, m_core->fileManager()->managedFiles(path)) { + Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); + + foreach (Core::IFile *file, core->fileManager()->managedFiles(path)) { allFileHandles << file; } - foreach (Core::IEditor *editor, m_core->editorManager()->editorsForFileName(path)) { + foreach (Core::IEditor *editor, core->editorManager()->editorsForFileName(path)) { if (Core::IFile *editorFile = editor->file()) { if (editorFile->isModified()) modifiedFileHandles << editorFile; @@ -309,7 +292,7 @@ bool Qt4PriFileNode::saveModifiedEditors(const QString &path) if (!modifiedFileHandles.isEmpty()) { bool cancelled; - m_core->fileManager()->saveModifiedFiles(modifiedFileHandles, &cancelled, + core->fileManager()->saveModifiedFiles(modifiedFileHandles, &cancelled, tr("There are unsaved changes for project file %1.").arg(path)); if (cancelled) return false; @@ -330,6 +313,18 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, if (filePaths.isEmpty()) return; + ProFileReader *reader = m_qt4ProFileNode->createProFileReader(); + if (!reader->readProFile(m_qt4ProFileNode->path())) { + m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath)); + delete reader; + return; + } + + ProFile *includeFile = reader->proFileFor(m_projectFilePath); + if(!includeFile) { + m_project->proFileParseError(tr("Error while changing pro file %1.").arg(m_projectFilePath)); + } + *notChanged = filePaths; // Check for modified editors @@ -338,7 +333,7 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, // Check if file is readonly ProEditorModel proModel; - proModel.setProFiles(QList() << m_includeFile); + proModel.setProFiles(QList() << includeFile); const QStringList vars = varNames(fileType); QDir priFileDir = QDir(m_projectDir); @@ -413,26 +408,27 @@ void Qt4PriFileNode::changeFiles(const FileType fileType, } // save file - if (!m_saveTimer->isActive()) - m_saveTimer->start(); + save(includeFile); + delete reader; } -void Qt4PriFileNode::save() +void Qt4PriFileNode::save(ProFile *includeFile) { - Core::FileManager *fileManager = m_core->fileManager(); - QList allFileHandles = fileManager->managedFiles(m_includeFile->fileName()); + Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); + Core::FileManager *fileManager = core->fileManager(); + QList allFileHandles = fileManager->managedFiles(includeFile->fileName()); Core::IFile *modifiedFileHandle = 0; foreach(Core::IFile *file, allFileHandles) - if (file->fileName() == m_includeFile->fileName()) + if (file->fileName() == includeFile->fileName()) modifiedFileHandle = file; if (modifiedFileHandle) fileManager->blockFileChange(modifiedFileHandle); ProWriter pw; - const bool ok = pw.write(m_includeFile, m_includeFile->fileName()); + const bool ok = pw.write(includeFile, includeFile->fileName()); Q_UNUSED(ok) - m_includeFile->setModified(false); - m_project->qt4ProjectManager()->notifyChanged(m_includeFile->fileName()); + includeFile->setModified(false); + m_project->qt4ProjectManager()->notifyChanged(includeFile->fileName()); if (modifiedFileHandle) fileManager->unblockFileChange(modifiedFileHandle); @@ -487,12 +483,11 @@ QStringList Qt4PriFileNode::varNames(FileType type) Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project, const QString &filePath, QObject *parent) - : Qt4PriFileNode(project, filePath), + : Qt4PriFileNode(project, this, filePath), // own stuff m_projectType(InvalidProject), m_isQBuildProject(false), - m_dirWatcher(new DirectoryWatcher(this)), - m_reader(0) + m_dirWatcher(new DirectoryWatcher(this)) { if (parent) setParent(parent); @@ -507,7 +502,7 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project, Qt4ProFileNode::~Qt4ProFileNode() { - delete m_reader; + } bool Qt4ProFileNode::hasTargets() const @@ -527,11 +522,10 @@ QStringList Qt4ProFileNode::variableValue(const Qt4Variable var) const void Qt4ProFileNode::update() { - delete m_reader; - m_reader = createProFileReader(); - if (!m_reader->readProFile(m_projectFilePath)) { + ProFileReader *reader = createProFileReader(); + if (!reader->readProFile(m_projectFilePath)) { m_project->proFileParseError(tr("Error while parsing file %1. Giving up.").arg(m_projectFilePath)); - delete m_reader; + delete reader; invalidate(); return; } @@ -546,7 +540,7 @@ void Qt4ProFileNode::update() #endif Qt4ProjectType projectType = InvalidProject; - switch (m_reader->templateType()) { + switch (reader->templateType()) { case ProFileEvaluator::TT_Unknown: case ProFileEvaluator::TT_Application: { projectType = ApplicationTemplate; @@ -585,11 +579,11 @@ void Qt4ProFileNode::update() ProFile *fileForCurrentProject = 0; { if (projectType == SubDirsTemplate) { - foreach (const QString &subDirProject, subDirsPaths(m_reader)) + foreach (const QString &subDirProject, subDirsPaths(reader)) newProjectFiles << subDirProject; } - foreach (ProFile *includeFile, m_reader->includeFiles()) { + foreach (ProFile *includeFile, reader->includeFiles()) { if (includeFile->fileName() == m_projectFilePath) { // this file fileForCurrentProject = includeFile; } else { @@ -616,9 +610,9 @@ void Qt4ProFileNode::update() } else if ((*existingNodeIter)->path() > *newProjectFileIter) { if (ProFile *file = includeFiles.value(*newProjectFileIter)) { Qt4PriFileNode *priFileNode - = new Qt4PriFileNode(m_project, + = new Qt4PriFileNode(m_project, this, *newProjectFileIter); - priFileNode->update(file, m_reader); + priFileNode->update(file, reader); toAdd << priFileNode; } else { toAdd << createSubProFileNode(*newProjectFileIter); @@ -627,7 +621,7 @@ void Qt4ProFileNode::update() } else { // *existingNodeIter->path() == *newProjectFileIter if (ProFile *file = includeFiles.value(*newProjectFileIter)) { Qt4PriFileNode *priFileNode = static_cast(*existingNodeIter); - priFileNode->update(file, m_reader); + priFileNode->update(file, reader); } ++existingNodeIter; @@ -641,9 +635,9 @@ void Qt4ProFileNode::update() while (newProjectFileIter != newProjectFiles.constEnd()) { if (ProFile *file = includeFiles.value(*newProjectFileIter)) { Qt4PriFileNode *priFileNode - = new Qt4PriFileNode(m_project, + = new Qt4PriFileNode(m_project, this, *newProjectFileIter); - priFileNode->update(file, m_reader); + priFileNode->update(file, reader); toAdd << priFileNode; } else { toAdd << createSubProFileNode(*newProjectFileIter); @@ -656,15 +650,15 @@ void Qt4ProFileNode::update() if (!toAdd.isEmpty()) addProjectNodes(toAdd); - Qt4PriFileNode::update(fileForCurrentProject, m_reader); + Qt4PriFileNode::update(fileForCurrentProject, reader); // update other variables QHash newVarValues; - newVarValues[CxxCompilerVar] << m_reader->value(QLatin1String("QMAKE_CXX")); - newVarValues[DefinesVar] = m_reader->values(QLatin1String("DEFINES")); - newVarValues[IncludePathVar] = includePaths(m_reader); - newVarValues[UiDirVar] = uiDirPaths(m_reader); - newVarValues[MocDirVar] = mocDirPaths(m_reader); + newVarValues[CxxCompilerVar] << reader->value(QLatin1String("QMAKE_CXX")); + newVarValues[DefinesVar] = reader->values(QLatin1String("DEFINES")); + newVarValues[IncludePathVar] = includePaths(reader); + newVarValues[UiDirVar] = uiDirPaths(reader); + newVarValues[MocDirVar] = mocDirPaths(reader); if (m_varValues != newVarValues) { m_varValues = newVarValues; @@ -678,12 +672,14 @@ void Qt4ProFileNode::update() foreach (NodesWatcher *watcher, watchers()) if (Qt4NodesWatcher *qt4Watcher = qobject_cast(watcher)) emit qt4Watcher->proFileUpdated(this); + + delete reader; } void Qt4ProFileNode::fileChanged(const QString &filePath) { CppTools::CppModelManagerInterface *modelManager = - m_core->pluginManager()->getObject(); + ExtensionSystem::PluginManager::instance()->getObject(); modelManager->updateSourceFiles(QStringList() << filePath); } @@ -789,7 +785,7 @@ void Qt4ProFileNode::updateGeneratedFiles() } } -ProFileReader *Qt4ProFileNode::createProFileReader() const +ProFileReader *Qt4PriFileNode::createProFileReader() const { ProFileReader *reader = new ProFileReader(); connect(reader, SIGNAL(errorFound(const QString &)), @@ -801,7 +797,7 @@ ProFileReader *Qt4ProFileNode::createProFileReader() const } QHash variables; - variables.insert(QLatin1String("OUT_PWD"), QStringList(buildDir())); + variables.insert(QLatin1String("OUT_PWD"), QStringList(m_qt4ProFileNode->buildDir())); reader->addVariables(variables); return reader; @@ -916,7 +912,7 @@ QStringList Qt4ProFileNode::qBuildSubDirsPaths(const QString &scanDir) const return subProjectPaths; } -QString Qt4ProFileNode::buildDir() const +QString Qt4PriFileNode::buildDir() const { const QDir srcDirRoot = QFileInfo(m_project->rootProjectNode()->path()).absoluteDir(); const QString relativeDir = srcDirRoot.relativeFilePath(m_projectDir); @@ -951,11 +947,6 @@ void Qt4ProFileNode::invalidate() } -ProFile *Qt4ProFileNode::proFileFromCache(const QString &fileName) -{ - return m_reader->proFileFromCache(fileName); -} - Qt4NodesWatcher::Qt4NodesWatcher(QObject *parent) : NodesWatcher(parent) { diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index f4d7c9bd17f..97bc06a08f4 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -102,8 +102,7 @@ class Qt4PriFileNode : public ProjectExplorer::ProjectNode { Q_OBJECT Q_DISABLE_COPY(Qt4PriFileNode) public: - Qt4PriFileNode(Qt4Project *project, - const QString &filePath); + Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNode, const QString &filePath); void update(ProFile *includeFile, ProFileReader *reader); @@ -122,9 +121,6 @@ public: bool renameFile(const FileType fileType, const QString &filePath, const QString &newFilePath); -private slots: - void save(); - protected: void clear(); static QStringList varNames(FileType type); @@ -142,18 +138,20 @@ protected: const QStringList &filePaths, QStringList *notChanged, ChangeType change); - + + QString buildDir() const; + ProFileReader *createProFileReader() const; + private: + void save(ProFile *includeFile); bool priFileWritable(const QString &path); bool saveModifiedEditors(const QString &path); - Core::ICore *m_core; Qt4Project *m_project; + Qt4ProFileNode *m_qt4ProFileNode; QString m_projectFilePath; QString m_projectDir; - ProFile *m_includeFile; QTimer *m_saveTimer; - ProFileReader *m_reader; // managed by Qt4ProFileNode friend class Qt4ProFileNode; @@ -174,7 +172,6 @@ public: Qt4ProjectType projectType() const; QStringList variableValue(const Qt4Variable var) const; - ProFile *proFileFromCache(const QString &fileName); public slots: void update(); @@ -185,7 +182,6 @@ private slots: private: void updateGeneratedFiles(); - ProFileReader *createProFileReader() const; Qt4ProFileNode *createSubProFileNode(const QString &path); QStringList uiDirPaths(ProFileReader *reader) const; @@ -194,7 +190,7 @@ private: QStringList subDirsPaths(ProFileReader *reader) const; QStringList qBuildSubDirsPaths(const QString &scanDir) const; - QString buildDir() const; + void invalidate(); @@ -203,7 +199,6 @@ private: bool m_isQBuildProject; DirectoryWatcher *m_dirWatcher; - ProFileReader *m_reader; friend class Qt4NodeHierarchy; }; diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index b07900f9103..501068af004 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -179,12 +179,8 @@ Qt4ProjectFile::Qt4ProjectFile(Qt4Project *project, const QString &filePath, QOb bool Qt4ProjectFile::save(const QString &) { - ProFile *file = m_project->proFileFromCache(m_filePath); - ProWriter pw; - bool ok = pw.write(file, file->fileName()); - file->setModified(false); - m_project->qt4ProjectManager()->notifyChanged(file->fileName()); - return ok; + // This is never used + return false; } QString Qt4ProjectFile::fileName() const @@ -209,7 +205,7 @@ QString Qt4ProjectFile::mimeType() const bool Qt4ProjectFile::isModified() const { - return m_project->proFileFromCache(m_filePath)->isModified(); + return false; // we save after changing anyway } bool Qt4ProjectFile::isReadOnly() const @@ -895,16 +891,24 @@ MakeStep *Qt4Project::makeStep() const return 0; } -ProFile *Qt4Project::proFileFromCache(const QString &fileName) +bool Qt4Project::hasSubNode(Qt4PriFileNode *root, const QString &path) { - return rootProjectNode()->proFileFromCache(fileName); + if (root->path() == path) + return true; + foreach (FolderNode *fn, root->subFolderNodes()) { + if (qobject_cast(fn)) { + // we aren't interested in pro file nodes + } else if(Qt4PriFileNode *qt4prifilenode = qobject_cast(fn)) { + if (hasSubNode(qt4prifilenode, path)) + return true; + } + } + return false; } void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QList &list) { - if (root->path() == fileName) - list.append(root); - else if (root->proFileFromCache(fileName)) + if (hasSubNode(root, fileName)) list.append(root); foreach (FolderNode *fn, root->subFolderNodes()) @@ -914,9 +918,10 @@ void Qt4Project::findProFile(const QString& fileName, Qt4ProFileNode *root, QLis void Qt4Project::notifyChanged(const QString &name) { - QList list; - findProFile(name, rootProjectNode(), list); - foreach(Qt4ProFileNode *node, list) - node->update(); - + if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) { + QList list; + findProFile(name, rootProjectNode(), list); + foreach(Qt4ProFileNode *node, list) + node->update(); + } } diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h index 18a7bf7f4f5..2a236a84c63 100644 --- a/src/plugins/qt4projectmanager/qt4project.h +++ b/src/plugins/qt4projectmanager/qt4project.h @@ -180,7 +180,6 @@ public: QMakeStep *qmakeStep() const; MakeStep *makeStep() const; - ProFile *proFileFromCache(const QString &fileName); void notifyChanged(const QString &name); public slots: @@ -209,6 +208,7 @@ protected: private: static void collectApplicationProFiles(QList &list, Internal::Qt4ProFileNode *node); static void findProFile(const QString& fileName, Internal::Qt4ProFileNode *root, QList &list); + static bool hasSubNode(Internal::Qt4PriFileNode *root, const QString &path); QList m_applicationProFileChange; ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const; From 376e2983d2615504e0036b6fcb4e8c69393115c2 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Fri, 5 Dec 2008 15:24:45 +0100 Subject: [PATCH 09/41] Fixes: Some documentation fixes --- doc/qtcreator.qdoc | 78 ++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4521b7e2fa4..4dd7a5fb53c 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -950,24 +950,23 @@ You can start Qt Creator from a command prompt with an existing session or \c{.pro} file by giving the name as argument on the command line. - \bold{Sidebar} + \bold{Show and Hide the Sidebar} - You can hide/unhide the sidebar in the edit and debug mode - by clicking on the corresponding icon on the left bottom. - Keyboard shortcut is \key{Alt+0}. + You can show and hide the the sidebar in \gui Edit and \gui Debug mode by + clicking on the corresponding icon, or by pressing \key{Alt+0}. - \bold{Display signals and slots} + \bold{Display Signals and Slots} - If you have an instance of a class derived from QObject and - want to find all other objects connected to one of its - slots by Qt's signals-and-slots mechanism, enable - \gui{Debug} and \gui{Use Custom Display for Qt Objects}. - In the \gui{Locals and Watchers View}, expand the object's - entry and open the wanted slot in the "slots" subitem. The - objects connect to this slot are exposed as children of - this slot. The same works with signals. + If you have an instance of a class that is derived from QObject, and you + you would like to find all other objects connected to one of your object's + slots using Qt's signals and slots mechanism -- you can enable + \gui{Use Custom Display for Qt Objects} feature under the \gui Debug menu. - \bold{Low level display} + In the \gui{Locals and Watchers} view, expand the object's entry and open + the slot in the \e slots subitem. The objects connected to this slot are + exposed as children of the slot. This method works with signals too. + + \bold{Display Low Level Data} If the special debugging of Qt objects fails due to data corruption within the debugged objects, you can switch the @@ -983,33 +982,38 @@ \title Glossary - \bold{System Qt} + \table + \header + \o Term + \o Meaning - \target glossary-system-qt - The version of Qt installed on your system. - This is the one whose \c qmake command is found in the \c PATH. + \row + \o System Qt \target glossary-system-qt + \o The version of Qt installed on your system. This is the Qt + version for the \c qmake command found in your \c PATH. - \bold{Default Qt} + \row + \o Default Qt \target glossary-default-qt + \o The version of Qt configured in \gui{Tools -> Options -> Qt 4 + -> Default Qt Version}. This is the Qt version used by your + new projects. It defaults to System Qt. - \target glossary-default-qt - The version of Qt configured in \gui{Tools - -> Options -> Qt 4 -> Default Qt Version}. This is the version - used by new projects. It defaults to the System Qt. + \row + \o Project Qt \target glossary-project-qt + \o The version of Qt configured in \gui{Build&Run -> Build + Settings -> Build Configurations}. This is the Qt version that + is actually used by a particular project. It defaults to + Default Qt. - \bold{Project Qt} - - \target glossary-project-qt - The version of Qt configured in \gui{Build&Run - -> Build Settings -> Build Configurations}. This is the version - actually used by the project. It defaults to the Default Qt. - - \bold{Shadow Build} - - \target glossary-shadow-build - Shadow building means building the project not in the source directory, - but in a seperate \bold{build directory}. This has the benefit of keeping - the source directory clean. It is also considered "best practice" if - you need many build configurations for a single set of sources. + \row + \o Shadow Build \target glossary-shadow-build + \o Shadow building means building a project in a separate + directory, the \e{build directory}. The build directory is + different from the source directory. One of the benefits of + shadow building is that it keeps your source directory clean. + Shadow building is the best practice if you need many build + configurations for a single set of source. + \endtable */ From 04f79bc9659663238594d8c725def0b0f1a93a06 Mon Sep 17 00:00:00 2001 From: con Date: Fri, 5 Dec 2008 15:06:11 +0100 Subject: [PATCH 10/41] Fixes: - Show in method combo box if there aren't any MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task: - 234321 RevBy: - Thorbjørn --- src/plugins/cppeditor/cppeditor.cpp | 24 +++++++++++++++++++----- src/plugins/cppeditor/cppeditor.h | 2 ++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index da52bb3d601..8567f81d751 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -79,6 +79,7 @@ #include #include #include +#include using namespace CPlusPlus; using namespace CppEditor::Internal; @@ -202,7 +203,9 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable) m_methodCombo->setMaxVisibleItems(20); m_overviewModel = new OverviewModel(this); - m_methodCombo->setModel(m_overviewModel); + m_noSymbolsModel = new QStringListModel(this); + m_noSymbolsModel->setStringList(QStringList() << tr("")); + m_methodCombo->setModel(m_noSymbolsModel); connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int))); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex())); @@ -315,9 +318,16 @@ void CPPEditor::onDocumentUpdated(Document::Ptr doc) return; m_overviewModel->rebuild(doc); - OverviewTreeView *treeView = static_cast(m_methodCombo->view()); - treeView->sync(); - updateMethodBoxIndex(); + if (m_overviewModel->rowCount() > 0) { + if (m_methodCombo->model() != m_overviewModel) + m_methodCombo->setModel(m_overviewModel); + OverviewTreeView *treeView = static_cast(m_methodCombo->view()); + treeView->sync(); + updateMethodBoxIndex(); + } else { + if (m_methodCombo->model() != m_noSymbolsModel) + m_methodCombo->setModel(m_noSymbolsModel); + } } void CPPEditor::updateFileName() @@ -325,6 +335,8 @@ void CPPEditor::updateFileName() void CPPEditor::jumpToMethod(int) { + if (m_methodCombo->model() != m_overviewModel) + return; QModelIndex index = m_methodCombo->view()->currentIndex(); Symbol *symbol = m_overviewModel->symbolFromIndex(index); if (! symbol) @@ -339,12 +351,14 @@ void CPPEditor::jumpToMethod(int) void CPPEditor::updateMethodBoxIndex() { + if (m_methodCombo->model() != m_overviewModel) + return; int line = 0, column = 0; convertPosition(position(), &line, &column); QModelIndex lastIndex; - const int rc = m_overviewModel->rowCount(QModelIndex()); + const int rc = m_overviewModel->rowCount(); for (int row = 0; row < rc; ++row) { const QModelIndex index = m_overviewModel->index(row, 0, QModelIndex()); Symbol *symbol = m_overviewModel->symbolFromIndex(index); diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 2420bcf4e5e..33745eddef2 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class QAction; class QComboBox; +class QStringListModel; QT_END_NAMESPACE namespace Core { @@ -138,6 +139,7 @@ private: QList m_contexts; QComboBox *m_methodCombo; CPlusPlus::OverviewModel *m_overviewModel; + QStringListModel *m_noSymbolsModel; }; } // namespace Internal From 1b33b75fc3441d668d1b25e5a3110eee8f9015ec Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 5 Dec 2008 12:55:31 +0100 Subject: [PATCH 11/41] Fixes: Build on msvc RevBy: Found by me. (cherry picked from commit 58827feb20c58ae39c610149d94df5b1f739ce01) --- src/plugins/qt4projectmanager/qtversionmanager.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 0c68fcd98eb..012e05b858a 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -963,7 +963,7 @@ void QtVersion::updateVersionInfo() const QString line = stream.readLine(); int index = line.indexOf(":"); if (index != -1) - m_versionInfo.insert(line.left(index), line.mid(index+1)); + m_versionInfo.insert(line.left(index), QDir::fromNativeSeparators(line.mid(index+1))); } } @@ -1035,6 +1035,7 @@ void QtVersion::updateMkSpec() const mkspec = mkspec.mid(QString("$$QT_BUILD_TREE/mkspecs/").length()); else if (mkspec.startsWith("$$QT_BUILD_TREE\\mkspecs\\")) mkspec = mkspec.mid(QString("$$QT_BUILD_TREE\\mkspecs\\").length()); + mkspec = QDir::fromNativeSeparators(mkspec); } break; } @@ -1097,10 +1098,11 @@ void QtVersion::updateMkSpec() const #endif } - int index =mkspec.lastIndexOf('/'); + int index = mkspec.lastIndexOf('/'); if(index == -1) index = mkspec.lastIndexOf('\\'); - if (index >= 0 && QDir(mkspec.left(index)).canonicalPath() == QDir(m_path + "/mkspecs/").canonicalPath()) + QString mkspecDir = QDir(m_path + "/mkspecs/").canonicalPath(); + if (index >= 0 && QDir(mkspec.left(index)).canonicalPath() == mkspecDir) mkspec = mkspec.mid(index+1).trimmed(); m_mkspec = mkspec; @@ -1112,7 +1114,7 @@ QString QtVersion::makeCommand() const { #ifdef Q_OS_WIN const QString &spec = mkspec(); - if (spec.startsWith("win32-msvc") || spec == QLatin1String("win32-icc")) + if (spec.contains("win32-msvc") || spec.contains(QLatin1String("win32-icc"))) return "nmake.exe"; else if(spec.startsWith("wince")) return "nmake.exe"; @@ -1149,7 +1151,7 @@ QtVersion::ToolchainType QtVersion::toolchainType() const if (!isValid()) return INVALID; const QString &spec = mkspec(); - if(spec.startsWith("win32-msvc") || spec == QLatin1String("win32-icc")) + if(spec.contains("win32-msvc") || spec.contains(QLatin1String("win32-icc"))) return MSVC; else if(spec == "win32-g++") return MinGW; From 440053f71e52c630ddf2da72d186b5c4f2f0d215 Mon Sep 17 00:00:00 2001 From: dt Date: Fri, 5 Dec 2008 16:30:26 +0100 Subject: [PATCH 12/41] Fixes: Add the cmakestep and makestep to a buildconfigratuion. Task: - RevBy: - AutoTest: - Details: Actually building only works on unix (since the generator is hardcoded.) and make is called without any parameters which is wrong. A lot is missing for basic build support, but this is a start. --- .../cmakeprojectmanager/cmakeproject.cpp | 22 +++++++++++++++++-- src/plugins/cmakeprojectmanager/cmakestep.cpp | 2 +- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 1268c57b967..fe591fa0041 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -34,6 +34,8 @@ #include "cmakeproject.h" #include "cmakeprojectconstants.h" #include "cmakeprojectnodes.h" +#include "cmakestep.h" +#include "makestep.h" #include #include @@ -187,7 +189,7 @@ QString CMakeProject::buildDirectory(const QString &buildConfiguration) const { Q_UNUSED(buildConfiguration) //TODO - return ""; + return QFileInfo(m_fileName).absolutePath(); } ProjectExplorer::BuildStepConfigWidget *CMakeProject::createConfigWidget() @@ -230,7 +232,23 @@ void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &w void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader) { // TODO - Q_UNUSED(reader) + Q_UNUSED(reader); + if (buildConfigurations().isEmpty()) { + // No build configuration, adding those + + // TODO do we want to create one build configuration per target? + // or how do we want to handle that? + + CMakeStep *cmakeStep = new CMakeStep(this); + MakeStep *makeStep = new MakeStep(this); + + insertBuildStep(0, cmakeStep); + insertBuildStep(1, makeStep); + + addBuildConfiguration("all"); + setActiveBuildConfiguration("all"); + } + // Restoring is fine } diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp index 523741c92ba..0c267ca2c4c 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp @@ -54,7 +54,7 @@ bool CMakeStep::init(const QString &buildConfiguration) setEnabled(buildConfiguration, true); setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration)); setCommand(buildConfiguration, "cmake"); // TODO give full path here? - setArguments(buildConfiguration, QStringList()); // TODO + setArguments(buildConfiguration, QStringList() << "-GUnix Makefiles"); // TODO setEnvironment(buildConfiguration, m_pro->environment(buildConfiguration)); return AbstractProcessStep::init(buildConfiguration); } From 0e8d02aab400f4cec14c29026350248d346874c1 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 5 Dec 2008 16:39:33 +0100 Subject: [PATCH 13/41] populate texteditor margin context menu --- shared/help/bookmarkmanager.h | 16 +++--- src/plugins/bookmarks/bookmarkmanager.cpp | 11 +++-- src/plugins/bookmarks/bookmarkmanager.h | 29 ++++++----- src/plugins/bookmarks/bookmarksplugin.cpp | 49 ++++++++++++++++++- src/plugins/bookmarks/bookmarksplugin.h | 29 +++++++++-- .../coreplugin/editormanager/ieditor.h | 2 +- src/plugins/cpptools/searchsymbols.h | 2 + src/plugins/debugger/debuggerplugin.cpp | 26 ++++++++++ src/plugins/debugger/debuggerplugin.h | 8 +++ 9 files changed, 143 insertions(+), 29 deletions(-) diff --git a/shared/help/bookmarkmanager.h b/shared/help/bookmarkmanager.h index a8afa867e65..c40d8672db0 100644 --- a/shared/help/bookmarkmanager.h +++ b/shared/help/bookmarkmanager.h @@ -95,8 +95,10 @@ private: QSortFilterProxyModel *proxyModel; }; -class TreeView : public QTreeView { +class TreeView : public QTreeView +{ Q_OBJECT + public: TreeView(QWidget* parent = 0) : QTreeView(parent) {} void subclassKeyPressEvent(QKeyEvent* event) @@ -159,18 +161,18 @@ class BookmarkManager : public QObject Q_OBJECT public: - BookmarkManager(QHelpEngineCore* helpEngine); + BookmarkManager(QHelpEngineCore *helpEngine); ~BookmarkManager(); - BookmarkModel* treeBookmarkModel(); - BookmarkModel* listBookmarkModel(); + BookmarkModel *treeBookmarkModel(); + BookmarkModel *listBookmarkModel(); void saveBookmarks(); QStringList bookmarkFolders() const; - QModelIndex addNewFolder(const QModelIndex& index); + QModelIndex addNewFolder(const QModelIndex &index); void removeBookmarkItem(QTreeView *treeView, const QModelIndex& index); - void showBookmarkDialog(QWidget* parent, const QString &name, const QString &url); - void addNewBookmark(const QModelIndex& index, const QString &name, const QString &url); + void showBookmarkDialog(QWidget *parent, const QString &name, const QString &url); + void addNewBookmark(const QModelIndex &index, const QString &name, const QString &url); void setupBookmarkModels(); private slots: diff --git a/src/plugins/bookmarks/bookmarkmanager.cpp b/src/plugins/bookmarks/bookmarkmanager.cpp index 0e8482b6f98..fd4541a01dd 100644 --- a/src/plugins/bookmarks/bookmarkmanager.cpp +++ b/src/plugins/bookmarks/bookmarkmanager.cpp @@ -396,11 +396,16 @@ void BookmarkManager::toggleBookmark() if (!editor) return; - const QFileInfo fi(editor->file()->fileName()); - const int editorLine = editor->currentLine(); + toggleBookmark(editor->file()->fileName(), editor->currentLine()); +} + +void BookmarkManager::toggleBookmark(const QString &fileName, int lineNumber) +{ + const QFileInfo fi(fileName); + const int editorLine = lineNumber; // Remove any existing bookmark on this line - if (Bookmark *mark = findBookmark(fi.path(), fi.fileName(), editorLine)) { + if (Bookmark *mark = findBookmark(fi.path(), fi.fileName(), lineNumber)) { // TODO check if the bookmark is really on the same markable Interface removeBookmark(mark); return; diff --git a/src/plugins/bookmarks/bookmarkmanager.h b/src/plugins/bookmarks/bookmarkmanager.h index 3b03e32d670..d3a2fc9a322 100644 --- a/src/plugins/bookmarks/bookmarkmanager.h +++ b/src/plugins/bookmarks/bookmarkmanager.h @@ -34,15 +34,15 @@ #ifndef BOOKMARKMANAGER_H #define BOOKMARKMANAGER_H -#include -#include -#include -#include -#include - #include #include +#include +#include +#include +#include +#include + namespace ProjectExplorer { class SessionManager; } @@ -89,10 +89,16 @@ public: // this QItemSelectionModel is shared by all views QItemSelectionModel *selectionModel() const; - enum Roles {Filename = Qt::UserRole, LineNumber = Qt::UserRole + 1, Directory = Qt::UserRole + 2, LineText = Qt::UserRole + 3}; + enum Roles { + Filename = Qt::UserRole, + LineNumber = Qt::UserRole + 1, + Directory = Qt::UserRole + 2, + LineText = Qt::UserRole + 3 + }; public slots: void toggleBookmark(); + void toggleBookmark(const QString &fileName, int lineNumber); void nextInDocument(); void prevInDocument(); void next(); @@ -108,6 +114,7 @@ private slots: void updateActionStatus(); void gotoBookmark(Bookmark *bookmark); void loadBookmarks(); + private: TextEditor::ITextEditor *currentTextEditor() const; ProjectExplorer::SessionManager* sessionManager() const; @@ -120,8 +127,8 @@ private: static QString bookmarkToString(const Bookmark *b); void saveBookmarks(); - typedef QMultiMap FileNameBookmarksMap; - typedef QMap DirectoryFileBookmarksMap; + typedef QMultiMap FileNameBookmarksMap; + typedef QMap DirectoryFileBookmarksMap; DirectoryFileBookmarksMap m_bookmarksMap; Core::ICore *m_core; @@ -138,7 +145,7 @@ class BookmarkView : public QListView public: BookmarkView(QWidget *parent = 0); ~BookmarkView(); - void setModel(QAbstractItemModel * model); + void setModel(QAbstractItemModel *model); public slots: void gotoBookmark(const QModelIndex &index); protected slots: @@ -146,7 +153,7 @@ protected slots: void removeAll(); protected: void contextMenuEvent(QContextMenuEvent *event); - void removeBookmark(const QModelIndex& index); + void removeBookmark(const QModelIndex &index); private: BookmarkContext *m_bookmarkContext; QModelIndex m_contextMenuIndex; diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp index fa749f7bef9..83c8ec397ee 100644 --- a/src/plugins/bookmarks/bookmarksplugin.cpp +++ b/src/plugins/bookmarks/bookmarksplugin.cpp @@ -36,17 +36,22 @@ #include "bookmarks_global.h" #include +#include #include +#include +#include #include #include #include #include +#include + #include -#include using namespace Bookmarks::Constants; using namespace Bookmarks::Internal; +using namespace TextEditor; BookmarksPlugin *BookmarksPlugin::m_instance = 0; @@ -159,6 +164,19 @@ bool BookmarksPlugin::initialize(const QStringList & /*arguments*/, QString *) updateActions(m_bookmarkManager->state()); addAutoReleasedObject(new BookmarkViewFactory(m_bookmarkManager)); + m_bookmarkMarginAction = new QAction(this); + m_bookmarkMarginAction->setText("Toggle Bookmark"); + //m_bookmarkAction->setIcon(QIcon(":/gdbdebugger/images/breakpoint.svg")); + connect(m_bookmarkMarginAction, SIGNAL(triggered()), + this, SLOT(bookmarkMarginActionTriggered())); + + // EditorManager + QObject *editorManager = m_core->editorManager(); + connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)), + this, SLOT(editorAboutToClose(Core::IEditor*))); + connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)), + this, SLOT(editorOpened(Core::IEditor*))); + return true; } @@ -169,7 +187,6 @@ BookmarksPlugin::~BookmarksPlugin() void BookmarksPlugin::updateActions(int state) { - const bool hasbm = state >= BookmarkManager::HasBookMarks; const bool hasdocbm = state == BookmarkManager::HasBookmarksInDocument; @@ -182,4 +199,32 @@ void BookmarksPlugin::updateActions(int state) m_moveDownAction->setEnabled(hasbm); } +void BookmarksPlugin::editorOpened(Core::IEditor *editor) +{ + connect(editor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); +} + +void BookmarksPlugin::editorAboutToClose(Core::IEditor *editor) +{ + disconnect(editor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); +} + +void BookmarksPlugin::requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu) +{ + m_bookmarkMarginActionLineNumber = lineNumber; + m_bookmarkMarginActionFileName = editor->file()->fileName(); + menu->addAction(m_bookmarkMarginAction); +} + +void BookmarksPlugin::bookmarkMarginActionTriggered() +{ + m_bookmarkManager->toggleBookmark( + m_bookmarkMarginActionFileName, + m_bookmarkMarginActionLineNumber + ); +} + Q_EXPORT_PLUGIN(BookmarksPlugin) diff --git a/src/plugins/bookmarks/bookmarksplugin.h b/src/plugins/bookmarks/bookmarksplugin.h index a5d919eb974..2a60bb04a34 100644 --- a/src/plugins/bookmarks/bookmarksplugin.h +++ b/src/plugins/bookmarks/bookmarksplugin.h @@ -31,18 +31,26 @@ ** ***************************************************************************/ -#ifndef BOOKMARKS_H -#define BOOKMARKS_H +#ifndef BOOKMARKSPLUGIN_H +#define BOOKMARKSPLUGIN_H + +#include #include #include -#include - -QT_FORWARD_DECLARE_CLASS(QAction) +QT_BEGIN_NAMESPACE +class QAction; +class QMenu; +QT_END_NAMESPACE namespace Core { class ICore; +class IEditor; +} + +namespace TextEditor { +class ITextEditor; } namespace Bookmarks { @@ -67,6 +75,13 @@ public: public slots: void updateActions(int stateMask); +private slots: + void editorOpened(Core::IEditor *editor); + void editorAboutToClose(Core::IEditor *editor); + void requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu); + void bookmarkMarginActionTriggered(); + private: static BookmarksPlugin *m_instance; BookmarkManager *m_bookmarkManager; @@ -79,6 +94,10 @@ private: QAction *m_docNextAction; QAction *m_moveUpAction; QAction *m_moveDownAction; + + QAction *m_bookmarkMarginAction; + int m_bookmarkMarginActionLineNumber; + QString m_bookmarkMarginActionFileName; }; } // namespace Internal diff --git a/src/plugins/coreplugin/editormanager/ieditor.h b/src/plugins/coreplugin/editormanager/ieditor.h index 7cbac8130ff..1f087e67e97 100644 --- a/src/plugins/coreplugin/editormanager/ieditor.h +++ b/src/plugins/coreplugin/editormanager/ieditor.h @@ -100,4 +100,4 @@ signals: } // namespace Core -#endif //IEDITOR_H +#endif // IEDITOR_H diff --git a/src/plugins/cpptools/searchsymbols.h b/src/plugins/cpptools/searchsymbols.h index 948f9d78e84..1fe276b6bea 100644 --- a/src/plugins/cpptools/searchsymbols.h +++ b/src/plugins/cpptools/searchsymbols.h @@ -44,6 +44,8 @@ #include #include +#include + namespace CppTools { namespace Internal { diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index b11472a5243..feb63fa0c30 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -250,6 +250,12 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *error_mes m_gdbRunningContext = uidm->uniqueIdentifier(Constants::GDBRUNNING); + m_breakpointMarginAction = new QAction(this); + m_breakpointMarginAction->setText("Toggle Breakpoint"); + //m_breakpointMarginAction->setIcon(QIcon(":/gdbdebugger/images/breakpoint.svg")); + connect(m_breakpointMarginAction, SIGNAL(triggered()), + this, SLOT(breakpointMarginActionTriggered())); + //Core::IActionContainer *mcppcontext = // actionManager->actionContainer(CppEditor::Constants::M_CONTEXT); @@ -502,6 +508,8 @@ void DebuggerPlugin::editorOpened(Core::IEditor *editor) this, SLOT(requestMark(TextEditor::ITextEditor*,int))); connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); + connect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); } } @@ -512,9 +520,27 @@ void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor) this, SLOT(requestMark(TextEditor::ITextEditor*,int))); disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)), this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int))); + disconnect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)), + this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*))); } } +void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu) +{ + m_breakpointMarginActionLineNumber = lineNumber; + m_breakpointMarginActionFileName = editor->file()->fileName(); + menu->addAction(m_breakpointMarginAction); +} + +void DebuggerPlugin::breakpointMarginActionTriggered() +{ + m_manager->toggleBreakpoint( + m_breakpointMarginActionFileName, + m_breakpointMarginActionLineNumber + ); +} + void DebuggerPlugin::requestMark(TextEditor::ITextEditor *editor, int lineNumber) { m_manager->toggleBreakpoint(editor->file()->fileName(), lineNumber); diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index 7dfcae1ffe7..91ffe4dbf77 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -84,10 +84,14 @@ private slots: void setSessionValue(const QString &name, const QVariant &value); void queryConfigValue(const QString &name, QVariant *value); void setConfigValue(const QString &name, const QVariant &value); + void requestContextMenu(TextEditor::ITextEditor *editor, + int lineNumber, QMenu *menu); void resetLocation(); void gotoLocation(const QString &fileName, int line, bool setMarker); + void breakpointMarginActionTriggered(); + private: friend class DebuggerManager; friend class DebugMode; // FIXME: Just a hack now so that it can access the views @@ -104,6 +108,10 @@ private: QString m_previousMode; LocationMark *m_locationMark; int m_gdbRunningContext; + + QAction *m_breakpointMarginAction; + int m_breakpointMarginActionLineNumber; + QString m_breakpointMarginActionFileName; }; } // namespace Internal From 9ef62848ac042fce4f38e1e0779c249c42f600ad Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 5 Dec 2008 17:06:17 +0100 Subject: [PATCH 14/41] avoid parentheses matching flicker when navigationt to block end / start. --- src/plugins/texteditor/basetexteditor.cpp | 29 ++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 49d29b75c93..82a4201b264 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -602,29 +602,44 @@ void BaseTextEditor::slotSelectionChanged() void BaseTextEditor::gotoBlockStart() { QTextCursor cursor = textCursor(); - if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, false)) + if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, false)) { setTextCursor(cursor); + _q_matchParentheses(); + } } void BaseTextEditor::gotoBlockEnd() { QTextCursor cursor = textCursor(); - if (TextBlockUserData::findNextClosingParenthesis(&cursor, false)) + if (TextBlockUserData::findNextClosingParenthesis(&cursor, false)) { setTextCursor(cursor); + _q_matchParentheses(); + } } void BaseTextEditor::gotoBlockStartWithSelection() { QTextCursor cursor = textCursor(); - if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, true)) + if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, true)) { setTextCursor(cursor); + _q_matchParentheses(); + } } void BaseTextEditor::gotoBlockEndWithSelection() { QTextCursor cursor = textCursor(); - if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) + if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) { setTextCursor(cursor); + _q_matchParentheses(); + } +} + +static QTextCursor flippedCursor(const QTextCursor &cursor) { + QTextCursor flipped = cursor; + flipped.clearSelection(); + flipped.setPosition(cursor.anchor(), QTextCursor::KeepAnchor); + return flipped; } void BaseTextEditor::selectBlockUp() @@ -640,7 +655,8 @@ void BaseTextEditor::selectBlockUp() return; if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true)) return; - setTextCursor(cursor); + setTextCursor(flippedCursor(cursor)); + _q_matchParentheses(); } void BaseTextEditor::selectBlockDown() @@ -663,7 +679,8 @@ void BaseTextEditor::selectBlockDown() if ( cursor != d->m_selectBlockAnchor) TextBlockUserData::findNextClosingParenthesis(&cursor, true); - setTextCursor(cursor); + setTextCursor(flippedCursor(cursor)); + _q_matchParentheses(); } From 38b04c737be4adfc51a5ba157950da1d5c103214 Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 5 Dec 2008 17:55:09 +0100 Subject: [PATCH 15/41] Bump two plugins from version 0.1 to 0.9.1 --- src/plugins/cpaster/CodePaster.pluginspec | 2 +- src/plugins/git/ScmGit.pluginspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec index 2ddd73902e5..7a1be0b8763 100644 --- a/src/plugins/cpaster/CodePaster.pluginspec +++ b/src/plugins/cpaster/CodePaster.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Technology Preview License Agreement diff --git a/src/plugins/git/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec index 689cc30a579..1f511448a07 100644 --- a/src/plugins/git/ScmGit.pluginspec +++ b/src/plugins/git/ScmGit.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Technology Preview License Agreement From d8b343afa1fc753b5f2f68377b06e7e3bf406baf Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 5 Dec 2008 18:27:45 +0100 Subject: [PATCH 16/41] silence warning --- bin/gdbmacros/gdbmacros.cpp | 5 ++++- src/plugins/cpptools/rpp/pp-fwd.h | 0 src/plugins/debugger/debuggeroutputwindow.cpp | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/plugins/cpptools/rpp/pp-fwd.h diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 0d6575db5b7..2043f65973d 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -1674,7 +1674,10 @@ static void qDumpQObjectSignal(QDumper &d) d.beginHash(); P(d, "name", "[" << i << "] slot"); P(d, "type", ""); - P(d, "value", conn.receiver->metaObject()->method(conn.method).signature()); + if (conn.receiver) + P(d, "value", conn.receiver->metaObject()->method(conn.method).signature()); + else + P(d, "value", ""); P(d, "numchild", "0"); d.endHash(); d.beginHash(); diff --git a/src/plugins/cpptools/rpp/pp-fwd.h b/src/plugins/cpptools/rpp/pp-fwd.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/plugins/debugger/debuggeroutputwindow.cpp b/src/plugins/debugger/debuggeroutputwindow.cpp index 7dc293cf35a..cfcd8df36d8 100644 --- a/src/plugins/debugger/debuggeroutputwindow.cpp +++ b/src/plugins/debugger/debuggeroutputwindow.cpp @@ -285,6 +285,7 @@ void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &outp void DebuggerOutputWindow::showInput(const QString &prefix, const QString &input) { + Q_UNUSED(prefix); m_inputText->append(input); QTextCursor cursor = m_inputText->textCursor(); cursor.movePosition(QTextCursor::End); From 5b3e95fe77e16de6f93ad198a245fa4698c940ad Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 5 Dec 2008 18:29:19 +0100 Subject: [PATCH 17/41] tiny whitespace --- src/app/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 68dfa3e3b23..ad61ab0c750 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -212,9 +212,9 @@ int main(int argc, char **argv) pluginManager.setPluginPaths(pluginPaths); const QStringList arguments = app.arguments(); - QMap foundAppOptions; + QMap foundAppOptions; if (arguments.size() > 1) { - QMap appOptions; + QMap appOptions; appOptions.insert(QLatin1String(HELP_OPTION1), false); appOptions.insert(QLatin1String(HELP_OPTION2), false); appOptions.insert(QLatin1String(HELP_OPTION3), false); From 0d46571eb3b4777abde3921d763551a917955017 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 5 Dec 2008 18:44:09 +0100 Subject: [PATCH 18/41] fix QSet custom dumper for namespaced Qt --- bin/gdbmacros/gdbmacros.cpp | 4 ++-- tests/manual/gdbdebugger/simple/app.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 2043f65973d..05488a85125 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -1869,8 +1869,8 @@ static void qDumpQSet(QDumper &d) d.beginHash(); P(d, "name", "[" << i << "]"); P(d, "type", d.innertype); - P(d, "exp", "(('QHashNode<" << d.innertype - << ",QHashDummyValue>'*)" + P(d, "exp", "(('"NS"QHashNode<" << d.innertype + << ","NS"QHashDummyValue>'*)" << static_cast(node) << ")->key" ); d.endHash(); diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index b00a259457e..4a1ec67e7ab 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -351,6 +351,23 @@ void testPlugin() } } +void testSet() +{ + QSet hgg0; + hgg0.insert(11); + hgg0.insert(22); + + QSet hgg1; + hgg1.insert("22.0"); + + QObject ob; + QSet > hash; + QPointer ptr(&ob); + //hash.insert(ptr); + //hash.insert(ptr); + //hash.insert(ptr); +} + void stringRefTest(const QString &refstring) { Q_UNUSED(refstring); @@ -759,6 +776,7 @@ int main(int argc, char *argv[]) testImage(); testMap(); testString(); + testSet(); testStringList(); testStruct(); //testThreads(); From 881610dfd2ee0f8450b3f1aec78c9a5a6ff76b43 Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 5 Dec 2008 18:51:07 +0100 Subject: [PATCH 19/41] Migrate subversion plugin to extended PathChooser --- src/libs/utils/pathchooser.cpp | 133 +++++++++++++++++++----- src/libs/utils/pathchooser.h | 20 +++- src/plugins/subversion/settingspage.cpp | 17 ++- src/plugins/subversion/settingspage.h | 3 - src/plugins/subversion/settingspage.ui | 20 ++-- 5 files changed, 144 insertions(+), 49 deletions(-) diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 340dbcad36a..68ebe9cbbfd 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -48,40 +48,54 @@ namespace Core { namespace Utils { +#ifdef Q_OS_OSX +/*static*/ const char * const PathChooser::browseButtonLabel = "Choose..."; +#else +/*static*/ const char * const PathChooser::browseButtonLabel = "Browse..."; +#endif + // ------------------ PathValidatingLineEdit class PathValidatingLineEdit : public BaseValidatingLineEdit { public: - explicit PathValidatingLineEdit(QWidget *parent = 0); + explicit PathValidatingLineEdit(PathChooser *chooser, QWidget *parent = 0); protected: virtual bool validate(const QString &value, QString *errorMessage) const; + +private: + PathChooser *m_chooser; }; -PathValidatingLineEdit::PathValidatingLineEdit(QWidget *parent) : - BaseValidatingLineEdit(parent) +PathValidatingLineEdit::PathValidatingLineEdit(PathChooser *chooser, QWidget *parent) : + BaseValidatingLineEdit(parent), + m_chooser(chooser) { + Q_ASSERT(chooser != NULL); } bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessage) const { - return PathChooser::validatePath(value, errorMessage); + return m_chooser->validatePath(value, errorMessage); } // ------------------ PathChooserPrivate struct PathChooserPrivate { - PathChooserPrivate(); + PathChooserPrivate(PathChooser *chooser); PathValidatingLineEdit *m_lineEdit; + PathChooser::Kind m_acceptingKind; + QString m_dialogTitleOverride; }; -PathChooserPrivate::PathChooserPrivate() : - m_lineEdit(new PathValidatingLineEdit) +PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) : + m_lineEdit(new PathValidatingLineEdit(chooser)), + m_acceptingKind(PathChooser::Directory) { } PathChooser::PathChooser(QWidget *parent) : QWidget(parent), - m_d(new PathChooserPrivate) + m_d(new PathChooserPrivate(this)) { QHBoxLayout *hLayout = new QHBoxLayout; hLayout->setContentsMargins(0, 0, 0, 0); @@ -90,11 +104,12 @@ PathChooser::PathChooser(QWidget *parent) : connect(m_d->m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); connect(m_d->m_lineEdit, SIGNAL(validChanged()), this, SIGNAL(validChanged())); - m_d->m_lineEdit->setMinimumWidth(300); + m_d->m_lineEdit->setMinimumWidth(260); hLayout->addWidget(m_d->m_lineEdit); + hLayout->setSizeConstraint(QLayout::SetMinimumSize); QToolButton *browseButton = new QToolButton; - browseButton->setText(tr("...")); + browseButton->setText(tr(browseButtonLabel)); connect(browseButton, SIGNAL(clicked()), this, SLOT(slotBrowse())); hLayout->addWidget(browseButton); @@ -123,8 +138,28 @@ void PathChooser::slotBrowse() QString predefined = path(); if (!predefined.isEmpty() && !QFileInfo(predefined).isDir()) predefined.clear(); - // Prompt for a directory, delete trailing slashes unless it is "/", only - QString newPath = QFileDialog::getExistingDirectory(this, tr("Choose a path"), predefined); + + // Prompt for a file/dir + QString dialogTitle; + QString newPath; + switch (m_d->m_acceptingKind) { + case PathChooser::Directory: + newPath = QFileDialog::getExistingDirectory(this, + makeDialogTitle(tr("Choose a directory")), predefined); + break; + + case PathChooser::File: // fall through + case PathChooser::Command: + newPath = QFileDialog::getOpenFileName(this, + makeDialogTitle(tr("Choose a file")), predefined); + break; + + default: + ; + } + + // TODO make cross-platform + // Delete trailing slashes unless it is "/", only if (!newPath .isEmpty()) { if (newPath .size() > 1 && newPath .endsWith(QDir::separator())) newPath .truncate(newPath .size() - 1); @@ -149,20 +184,52 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage) *errorMessage = tr("The path must not be empty."); return false; } - // Must be a directory? - const QFileInfo fi(path); - if (fi.isDir()) - return true; // Happy! - if (!fi.exists()) { - if (errorMessage) - *errorMessage = tr("The path '%1' does not exist.").arg(path); - return false; + const QFileInfo fi(path); + const bool isDir = fi.isDir(); + + // Check if existing + switch (m_d->m_acceptingKind) { + case PathChooser::Directory: // fall through + case PathChooser::File: + if (!fi.exists()) { + if (errorMessage) + *errorMessage = tr("The path '%1' does not exist.").arg(path); + return false; + } + break; + + case PathChooser::Command: // fall through + default: + ; } - // Must be something weird - if (errorMessage) - *errorMessage = tr("The path '%1' is not a directory.").arg(path); - return false; + + // Check expected kind + switch (m_d->m_acceptingKind) { + case PathChooser::Directory: + if (!isDir) + if (errorMessage) + *errorMessage = tr("The path '%1' is not a directory.").arg(path); + return false; + break; + + case PathChooser::File: + if (isDir) + if (errorMessage) + *errorMessage = tr("The path '%1' is not a file.").arg(path); + return false; + break; + + case PathChooser::Command: + // TODO do proper command validation + // i.e. search $PATH for a matching file + break; + + default: + ; + } + + return true; } QString PathChooser::label() @@ -182,5 +249,23 @@ QString PathChooser::homePath() #endif } +void PathChooser::setExpectedKind(Kind expected) +{ + m_d->m_acceptingKind = expected; +} + +void PathChooser::setPromptDialogTitle(const QString &title) +{ + m_d->m_dialogTitleOverride = title; +} + +QString PathChooser::makeDialogTitle(const QString &title) +{ + if (m_d->m_dialogTitleOverride.isNull()) + return title; + else + return m_d->m_dialogTitleOverride; +} + } // namespace Utils } // namespace Core diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index ab821d5df1e..d4bd098e908 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -54,9 +54,23 @@ class QWORKBENCH_UTILS_EXPORT PathChooser : public QWidget Q_PROPERTY(QString path READ path WRITE setPath DESIGNABLE true) public: + static const char * const browseButtonLabel; + explicit PathChooser(QWidget *parent = 0); virtual ~PathChooser(); + enum Kind { + Directory, + File, + Command, + // ,Any + }; + + // Default is + void setExpectedKind(Kind expected); + + void setPromptDialogTitle(const QString &title); + bool isValid() const; QString errorMessage() const; @@ -65,11 +79,15 @@ public: // Returns the suggested label title when used in a form layout static QString label(); - static bool validatePath(const QString &path, QString *errorMessage = 0); + bool validatePath(const QString &path, QString *errorMessage = 0); // Return the home directory, which needs some fixing under Windows. static QString homePath(); +private: + // Returns overridden title or the one from + QString makeDialogTitle(const QString &title); + signals: void validChanged(); void changed(); diff --git a/src/plugins/subversion/settingspage.cpp b/src/plugins/subversion/settingspage.cpp index ab785db796e..4621928b963 100644 --- a/src/plugins/subversion/settingspage.cpp +++ b/src/plugins/subversion/settingspage.cpp @@ -39,20 +39,24 @@ #include <extensionsystem/pluginmanager.h> #include <QtGui/QFileDialog> +#include <utils/pathchooser.h> using namespace Subversion::Internal; +using namespace Core::Utils; + SettingsPageWidget::SettingsPageWidget(QWidget *parent) : QWidget(parent) { m_ui.setupUi(this); - connect(m_ui.browseButton, SIGNAL(clicked()), this, SLOT(browseForCommand())); + m_ui.pathChooser->setExpectedKind(PathChooser::Command); + m_ui.pathChooser->setPromptDialogTitle(tr("Subversion Command")); } SubversionSettings SettingsPageWidget::settings() const { SubversionSettings rc; - rc.svnCommand = m_ui.svnCmdLineEdit->text(); + rc.svnCommand = m_ui.pathChooser->path(); rc.useAuthentication = m_ui.userGroupBox->isChecked(); rc.user = m_ui.usernameLineEdit->text(); rc.password = m_ui.passwordLineEdit->text(); @@ -63,19 +67,12 @@ SubversionSettings SettingsPageWidget::settings() const void SettingsPageWidget::setSettings(const SubversionSettings &s) { - m_ui.svnCmdLineEdit->setText(s.svnCommand); + m_ui.pathChooser->setPath(s.svnCommand); m_ui.usernameLineEdit->setText(s.user); m_ui.passwordLineEdit->setText(s.password); m_ui.userGroupBox->setChecked(s.useAuthentication); } -void SettingsPageWidget::browseForCommand() -{ - QString cmd = QFileDialog::getOpenFileName(window(), tr("Subversion Command")); - if (!cmd.isEmpty()) - m_ui.svnCmdLineEdit->setText(cmd); -} - SettingsPage::SettingsPage() { } diff --git a/src/plugins/subversion/settingspage.h b/src/plugins/subversion/settingspage.h index f32401b6d93..8ac704f0727 100644 --- a/src/plugins/subversion/settingspage.h +++ b/src/plugins/subversion/settingspage.h @@ -59,9 +59,6 @@ public: SubversionSettings settings() const; void setSettings(const SubversionSettings &); -private slots:; - void browseForCommand(); - private: Ui::SettingsPage m_ui; }; diff --git a/src/plugins/subversion/settingspage.ui b/src/plugins/subversion/settingspage.ui index 14e5ebce87e..21b20187bbd 100644 --- a/src/plugins/subversion/settingspage.ui +++ b/src/plugins/subversion/settingspage.ui @@ -32,14 +32,7 @@ </widget> </item> <item> - <widget class="QLineEdit" name="svnCmdLineEdit"/> - </item> - <item> - <widget class="QToolButton" name="browseButton"> - <property name="text"> - <string>...</string> - </property> - </widget> + <widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/> </item> </layout> </item> @@ -109,9 +102,14 @@ </item> </layout> </widget> - <tabstops> - <tabstop>svnCmdLineEdit</tabstop> - </tabstops> + <customwidgets> + <customwidget> + <class>Core::Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> <resources/> <connections/> </ui> From 9bfb54f59a325bd3fb6fdbaca85a3a342e0b1ef8 Mon Sep 17 00:00:00 2001 From: goro <qtc-committer@nokia.com> Date: Fri, 5 Dec 2008 19:11:06 +0100 Subject: [PATCH 20/41] Migrate Perforce plugin to PathChooser --- src/plugins/perforce/settingspage.cpp | 16 +++++----------- src/plugins/perforce/settingspage.h | 3 --- src/plugins/perforce/settingspage.ui | 18 +++++++++--------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/plugins/perforce/settingspage.cpp b/src/plugins/perforce/settingspage.cpp index 5fd7dda4862..b5cbd7fa000 100644 --- a/src/plugins/perforce/settingspage.cpp +++ b/src/plugins/perforce/settingspage.cpp @@ -39,18 +39,20 @@ #include <QtGui/QFileDialog> using namespace Perforce::Internal; +using namespace Core::Utils; SettingsPageWidget::SettingsPageWidget(QWidget *parent) : QWidget(parent) { m_ui.setupUi(this); - connect(m_ui.browseButton, SIGNAL(clicked()), this, SLOT(browseForCommand())); + m_ui.pathChooser->setPromptDialogTitle(tr("Perforce Command")); + m_ui.pathChooser->setExpectedKind(PathChooser::Command); } PerforceSettings SettingsPageWidget::settings() const { PerforceSettings rc; - rc.p4Command = m_ui.p4CmdLineEdit->text(); + rc.p4Command = m_ui.pathChooser->path(); rc.defaultEnv = m_ui.defaultCheckBox->isChecked(); rc.p4Port = m_ui.portLineEdit->text(); rc.p4Client = m_ui.clientLineEdit->text(); @@ -60,21 +62,13 @@ PerforceSettings SettingsPageWidget::settings() const void SettingsPageWidget::setSettings(const PerforceSettings &s) { - m_ui.p4CmdLineEdit->setText(s.p4Command); + m_ui.pathChooser->setPath(s.p4Command); m_ui.defaultCheckBox->setChecked(s.defaultEnv); m_ui.portLineEdit->setText(s.p4Port); m_ui.clientLineEdit->setText(s.p4Client); m_ui.userLineEdit->setText(s.p4User); } -void SettingsPageWidget::browseForCommand() -{ - const QString cmd = QFileDialog::getOpenFileName(window(), tr("Perforce Command")); - if (!cmd.isEmpty()) - m_ui.p4CmdLineEdit->setText(cmd); -} - - SettingsPage::SettingsPage() { } diff --git a/src/plugins/perforce/settingspage.h b/src/plugins/perforce/settingspage.h index f73a205e112..23e96812573 100644 --- a/src/plugins/perforce/settingspage.h +++ b/src/plugins/perforce/settingspage.h @@ -54,9 +54,6 @@ public: PerforceSettings settings() const; void setSettings(const PerforceSettings &); -private slots:; - void browseForCommand(); - private: Ui::SettingsPage m_ui; }; diff --git a/src/plugins/perforce/settingspage.ui b/src/plugins/perforce/settingspage.ui index 1379b7b6666..b2d6bf10e35 100644 --- a/src/plugins/perforce/settingspage.ui +++ b/src/plugins/perforce/settingspage.ui @@ -36,14 +36,7 @@ </widget> </item> <item> - <widget class="QLineEdit" name="p4CmdLineEdit"/> - </item> - <item> - <widget class="QToolButton" name="browseButton"> - <property name="text"> - <string>...</string> - </property> - </widget> + <widget class="Core::Utils::PathChooser" name="pathChooser" native="true"/> </item> </layout> </item> @@ -120,11 +113,18 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>Core::Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> <tabstops> <tabstop>portLineEdit</tabstop> <tabstop>clientLineEdit</tabstop> <tabstop>userLineEdit</tabstop> - <tabstop>p4CmdLineEdit</tabstop> </tabstops> <resources/> <connections> From 44cc9a2b400a4c695d9f21cce9cebee0d571318a Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 10:25:39 +0100 Subject: [PATCH 21/41] fix expansion state of "dummy" items in locals&watchers after frame changes --- bin/gdbmacros/gdbmacros.cpp | 10 +- src/plugins/debugger/watchhandler.cpp | 128 ++++++++++++++------------ src/plugins/debugger/watchhandler.h | 1 - src/plugins/debugger/watchwindow.cpp | 14 +-- src/plugins/debugger/watchwindow.h | 1 - 5 files changed, 84 insertions(+), 70 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 05488a85125..199b783f45d 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -1864,7 +1864,7 @@ static void qDumpQSet(QDumper &d) n = 100; d << ",children=["; int i = 0; - for (int bucket = 0; bucket != hd->numBuckets; ++bucket) { + for (int bucket = 0; bucket != hd->numBuckets && i <= 10000; ++bucket) { for (node = hd->buckets[bucket]; node->next; node = node->next) { d.beginHash(); P(d, "name", "[" << i << "]"); @@ -1875,6 +1875,14 @@ static void qDumpQSet(QDumper &d) ); d.endHash(); ++i; + if (i > 10000) { + d.beginHash(); + P(d, "name", "Warning:"); + P(d, "value", "<incomplete>"); + P(d, "type", ""); + d.endHash(); + break; + } } } d << "]"; diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 3d99a84ad34..1792e4705d6 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -320,6 +320,51 @@ static WatchData take(const QString &iname, QList<WatchData> *list) } +static QList<WatchData> initialSet() +{ + QList<WatchData> result; + + WatchData root; + root.state = 0; + root.level = 0; + root.row = 0; + root.name = "Root"; + root.parentIndex = -1; + root.childIndex.append(1); + root.childIndex.append(2); + root.childIndex.append(3); + result.append(root); + + WatchData local; + local.iname = "local"; + local.name = "Locals"; + local.state = 0; + local.level = 1; + local.row = 0; + local.parentIndex = 0; + result.append(local); + + WatchData tooltip; + tooltip.iname = "tooltip"; + tooltip.name = "Tooltip"; + tooltip.state = 0; + tooltip.level = 1; + tooltip.row = 1; + tooltip.parentIndex = 0; + result.append(tooltip); + + WatchData watch; + watch.iname = "watch"; + watch.name = "Watchers"; + watch.state = 0; + watch.level = 1; + watch.row = 2; + watch.parentIndex = 0; + result.append(watch); + + return result; +} + /////////////////////////////////////////////////////////////////////// // // WatchHandler @@ -332,7 +377,8 @@ WatchHandler::WatchHandler() m_inFetchMore = false; m_inChange = false; - cleanModel(); + m_completeSet = initialSet(); + m_incompleteSet.clear(); m_displaySet = m_completeSet; } @@ -380,6 +426,7 @@ QVariant WatchHandler::data(const QModelIndex &idx, int role) const int node = idx.internalId(); if (node < 0) return QVariant(); + QWB_ASSERT(node < m_displaySet.size(), return QVariant()); const WatchData &data = m_displaySet.at(node); @@ -558,10 +605,13 @@ void WatchHandler::rebuildModel() MODEL_DEBUG("RECREATE MODEL, CURRENT SET:\n" << toString()); #endif + QHash<QString, int> oldTopINames; QHash<QString, QString> oldValues; for (int i = 0, n = m_oldSet.size(); i != n; ++i) { WatchData &data = m_oldSet[i]; oldValues[data.iname] = data.value; + if (data.level == 2) + ++oldTopINames[data.iname]; } #ifdef DEBUG_PENDING MODEL_DEBUG("OLD VALUES: " << oldValues); @@ -575,6 +625,9 @@ void WatchHandler::rebuildModel() qSort(m_completeSet.begin(), m_completeSet.end(), &iNameSorter); + // This helps to decide whether the view has completely changed or not. + QHash<QString, int> topINames; + QHash<QString, int> iname2idx; for (int i = m_completeSet.size(); --i > 0; ) { @@ -582,7 +635,10 @@ void WatchHandler::rebuildModel() data.parentIndex = 0; data.childIndex.clear(); iname2idx[data.iname] = i; + if (data.level == 2) + ++topINames[data.iname]; } + //qDebug() << "TOPINAMES: " << topINames << "\nOLD: " << oldTopINames; for (int i = 1; i < m_completeSet.size(); ++i) { WatchData &data = m_completeSet[i]; @@ -603,7 +659,13 @@ void WatchHandler::rebuildModel() && data.value != strNotInScope; } - //emit layoutAboutToBeChanged(); + emit layoutAboutToBeChanged(); + + if (oldTopINames != topINames) { + m_displaySet = initialSet(); + m_expandedINames.clear(); + emit reset(); + } m_displaySet = m_completeSet; @@ -668,11 +730,6 @@ void WatchHandler::rebuildModel() emit reset(); //qDebug() << "WATCHHANDLER: RESET EMITTED"; m_inChange = false; - //emit layoutChanged(); - //QSet<QString> einames = m_expandedINames; - //einames.insert("local"); - //einames.insert("watch"); - //emit expandedItems(einames); #if DEBUG_MODEL #if USE_MODEL_TEST @@ -691,8 +748,11 @@ void WatchHandler::cleanup() m_oldSet.clear(); m_expandedINames.clear(); m_displayedINames.clear(); - cleanModel(); + + m_incompleteSet.clear(); + m_completeSet = initialSet(); m_displaySet = m_completeSet; + #if 0 for (EditWindows::ConstIterator it = m_editWindows.begin(); it != m_editWindows.end(); ++it) { @@ -707,7 +767,7 @@ void WatchHandler::cleanup() void WatchHandler::collapseChildren(const QModelIndex &idx) { if (m_inChange || m_completeSet.isEmpty()) { - //qDebug() << "WATCHHANDLER: COLLAPSE IGNORED" << idx; + qDebug() << "WATCHHANDLER: COLLAPSE IGNORED" << idx; return; } QWB_ASSERT(checkIndex(idx.internalId()), return); @@ -879,56 +939,10 @@ void WatchHandler::removeWatchExpression(const QString &iname) emit watchModelUpdateRequested(); } -void WatchHandler::cleanModel() -{ - // This uses data stored in m_oldSet to re-create a new set - // one-by-one - m_completeSet.clear(); - m_incompleteSet.clear(); - - WatchData root; - root.state = 0; - root.level = 0; - root.row = 0; - root.name = "Root"; - root.parentIndex = -1; - root.childIndex.append(1); - root.childIndex.append(2); - root.childIndex.append(3); - m_completeSet.append(root); - - WatchData local; - local.iname = "local"; - local.name = "Locals"; - local.state = 0; - local.level = 1; - local.row = 0; - local.parentIndex = 0; - m_completeSet.append(local); - - WatchData tooltip; - tooltip.iname = "tooltip"; - tooltip.name = "Tooltip"; - tooltip.state = 0; - tooltip.level = 1; - tooltip.row = 1; - tooltip.parentIndex = 0; - m_completeSet.append(tooltip); - - WatchData watch; - watch.iname = "watch"; - watch.name = "Watchers"; - watch.state = 0; - watch.level = 1; - watch.row = 2; - watch.parentIndex = 0; - m_completeSet.append(watch); -} - - void WatchHandler::reinitializeWatchers() { - cleanModel(); + m_completeSet = initialSet(); + m_incompleteSet.clear(); // copy over all watchers and mark all watchers as incomplete for (int i = 0, n = m_oldSet.size(); i < n; ++i) { diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 3841d55d300..989b99b3d22 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -192,7 +192,6 @@ signals: private: WatchData takeData(const QString &iname); QString toString() const; - void cleanModel(); bool m_expandPointers; bool m_inChange; diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 78366198955..d528bf09242 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -57,7 +57,6 @@ enum { INameRole = Qt::UserRole, VisualRole }; WatchWindow::WatchWindow(Type type, QWidget *parent) : QTreeView(parent), m_type(type) { - m_blocked = false; setWindowTitle(tr("Locals and Watchers")); setAlternatingRowColors(true); setIndentation(indentation() * 9/10); @@ -76,12 +75,8 @@ void WatchWindow::expandNode(const QModelIndex &idx) //QModelIndex mi0 = idx.sibling(idx.row(), 0); //QString iname = model()->data(mi0, INameRole).toString(); //QString name = model()->data(mi0, Qt::DisplayRole).toString(); - //qDebug() << "\n\nEXPAND NODE " // << iname << name - // << idx << (m_blocked ? "blocked" : "passed"); //if (isExpanded(idx)) // return; - //if (m_blocked) - // return; emit requestExpandChildren(idx); } @@ -91,8 +86,6 @@ void WatchWindow::collapseNode(const QModelIndex &idx) //QString iname = model()->data(mi0, INameRole).toString(); //QString name = model()->data(mi0, Qt::DisplayRole).toString(); //qDebug() << "COLLAPSE NODE " << idx; - if (m_blocked) - return; emit requestCollapseChildren(idx); } @@ -201,7 +194,6 @@ void WatchWindow::setModel(QAbstractItemModel *model) void WatchWindow::modelAboutToBeReset() { - m_blocked = true; //qDebug() << "Model about to be reset"; m_expandedItems.clear(); m_expandedItems.insert("local"); @@ -225,10 +217,9 @@ void WatchWindow::modelAboutToBeResetHelper(const QModelIndex &idx) void WatchWindow::modelReset() { - //qDebug() << "Model reset"; + collapseAll(); expand(model()->index(0, 0)); modelResetHelper(model()->index(0, 0)); - m_blocked = false; } void WatchWindow::modelResetHelper(const QModelIndex &idx) @@ -242,6 +233,9 @@ void WatchWindow::modelResetHelper(const QModelIndex &idx) QModelIndex idx1 = model()->index(i, 0, idx); modelResetHelper(idx1); } + } else { + // if (!iname.isEmpty()) + // collapse(idx); } } diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index 9781f79fdb7..8b9b5d13ae4 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -85,7 +85,6 @@ private: bool m_alwaysResizeColumnsToContents; Type m_type; - bool m_blocked; QSet<QString> m_expandedItems; }; From d74ddb76b6229746f8c4538b3a35c760d51d2fd3 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 10:44:56 +0100 Subject: [PATCH 22/41] Protected m_dirty and m_projects with a mutex. --- .../cmakeprojectmanager/cmakeproject.cpp | 7 ++- src/plugins/cpptools/cppmodelmanager.cpp | 61 ++++++++++++++++--- src/plugins/cpptools/cppmodelmanager.h | 25 ++++---- .../cpptools/cppmodelmanagerinterface.h | 32 ++++++++-- src/plugins/qt4projectmanager/qt4project.cpp | 26 ++++---- 5 files changed, 111 insertions(+), 40 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 1268c57b967..9c6c3947fa3 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -62,11 +62,12 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) CppTools::CppModelManagerInterface *modelmanager = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>(); if (modelmanager) { - CppTools::CppModelManagerInterface::ProjectInfo *pinfo = modelmanager->projectInfo(this); - pinfo->includePaths = cbpparser.includeFiles(); + CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this); + pinfo.includePaths = cbpparser.includeFiles(); // TODO we only want C++ files, not all other stuff that might be in the project - pinfo->sourceFiles = m_files; + pinfo.sourceFiles = m_files; // TODO defines + modelmanager->updateProjectInfo(pinfo); } } else { // TODO report error diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 042b93cc74d..dbc324013c6 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -66,6 +66,7 @@ #include <Token.h> #include <QPlainTextEdit> +#include <QMutexLocker> #include <QTime> #include <QDebug> @@ -450,12 +451,25 @@ CppModelManager::CppModelManager(QObject *parent) : CppModelManager::~CppModelManager() { } -Document::Ptr CppModelManager::document(const QString &fileName) +Document::Ptr CppModelManager::document(const QString &fileName) const { return m_documents.value(fileName); } -CppModelManager::DocumentTable CppModelManager::documents() +CppModelManager::DocumentTable CppModelManager::documents() const { return m_documents; } +void CppModelManager::ensureUpdated() +{ + QMutexLocker locker(&mutex); + if (! m_dirty) + return; + + m_projectFiles = updateProjectFiles(); + m_includePaths = updateIncludePaths(); + m_frameworkPaths = updateFrameworkPaths(); + m_definedMacros = updateDefinedMacros(); + m_dirty = false; +} + QStringList CppModelManager::updateProjectFiles() const { QStringList files; @@ -527,8 +541,29 @@ QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList() void CppModelManager::updateSourceFiles(const QStringList &sourceFiles) { (void) refreshSourceFiles(sourceFiles); } -CppModelManager::ProjectInfo *CppModelManager::projectInfo(ProjectExplorer::Project *project) -{ return &m_projects[project]; } +QList<CppModelManager::ProjectInfo> CppModelManager::projectInfos() const +{ + QMutexLocker locker(&mutex); + + return m_projects.values(); +} + +CppModelManager::ProjectInfo CppModelManager::projectInfo(ProjectExplorer::Project *project) const +{ + QMutexLocker locker(&mutex); + + return m_projects.value(project, ProjectInfo(project)); +} + +void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) +{ + QMutexLocker locker(&mutex); + + if (! pinfo.isValid()) + return; + + m_projects.insert(pinfo.project, pinfo); +} QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles) { @@ -691,13 +726,18 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc) void CppModelManager::onProjectAdded(ProjectExplorer::Project *) { + QMutexLocker locker(&mutex); m_dirty = true; } void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) { - m_dirty = true; - m_projects.remove(project); + do { + QMutexLocker locker(&mutex); + m_dirty = true; + m_projects.remove(project); + } while (0); + GC(); } @@ -705,8 +745,15 @@ void CppModelManager::onSessionUnloaded() { if (m_core->progressManager()) { m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX); - m_dirty = true; } + + do { + QMutexLocker locker(&mutex); + m_projects.clear(); + m_dirty = true; + } while (0); + + GC(); } void CppModelManager::parse(QFutureInterface<void> &future, diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index a91a414e480..6bc7d0c1c55 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -40,6 +40,7 @@ #include <QMap> #include <QFutureInterface> +#include <QMutex> namespace Core { class ICore; @@ -70,9 +71,13 @@ public: virtual ~CppModelManager(); virtual void updateSourceFiles(const QStringList &sourceFiles); - virtual ProjectInfo *projectInfo(ProjectExplorer::Project *project); - virtual CPlusPlus::Document::Ptr document(const QString &fileName); - virtual DocumentTable documents(); + + virtual QList<ProjectInfo> projectInfos() const; + virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const; + virtual void updateProjectInfo(const ProjectInfo &pinfo); + + virtual CPlusPlus::Document::Ptr document(const QString &fileName) const; + virtual DocumentTable documents() const; virtual void GC(); QFuture<void> refreshSourceFiles(const QStringList &sourceFiles); @@ -127,22 +132,12 @@ private: return m_definedMacros; } + void ensureUpdated(); QStringList updateProjectFiles() const; QStringList updateIncludePaths() const; QStringList updateFrameworkPaths() const; QByteArray updateDefinedMacros() const; - void ensureUpdated() { - if (! m_dirty) - return; - - m_projectFiles = updateProjectFiles(); - m_includePaths = updateIncludePaths(); - m_frameworkPaths = updateFrameworkPaths(); - m_definedMacros = updateDefinedMacros(); - m_dirty = false; - } - static void parse(QFutureInterface<void> &future, CppPreprocessor *preproc, QStringList files); @@ -166,6 +161,8 @@ private: // project integration QMap<ProjectExplorer::Project *, ProjectInfo> m_projects; + mutable QMutex mutex; + enum { MAX_SELECTION_COUNT = 5 }; diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h index 11be08a4b0e..e3ad4fe961b 100644 --- a/src/plugins/cpptools/cppmodelmanagerinterface.h +++ b/src/plugins/cpptools/cppmodelmanagerinterface.h @@ -38,6 +38,7 @@ #include <cplusplus/CppDocument.h> #include <QtCore/QObject> #include <QtCore/QMap> +#include <QtCore/QPointer> namespace ProjectExplorer { class Project; @@ -51,10 +52,29 @@ class CPPTOOLS_EXPORT CppModelManagerInterface Q_OBJECT public: - typedef QMap<QString, CPlusPlus::Document::Ptr> DocumentTable; + typedef QMap<QString, CPlusPlus::Document::Ptr> DocumentTable; // ### remove me - struct ProjectInfo + class ProjectInfo { + public: + ProjectInfo() + { } + + ProjectInfo(QPointer<ProjectExplorer::Project> project) + : project(project) + { } + + operator bool() const + { return ! project.isNull(); } + + bool isValid() const + { return ! project.isNull(); } + + bool isNull() const + { return project.isNull(); } + + public: // attributes + QPointer<ProjectExplorer::Project> project; QString projectPath; QByteArray defines; QStringList sourceFiles; @@ -69,10 +89,12 @@ public: virtual void GC() = 0; virtual void updateSourceFiles(const QStringList &sourceFiles) = 0; - virtual CPlusPlus::Document::Ptr document(const QString &fileName) = 0; - virtual DocumentTable documents() = 0; + virtual CPlusPlus::Document::Ptr document(const QString &fileName) const = 0; + virtual DocumentTable documents() const = 0; - virtual ProjectInfo *projectInfo(ProjectExplorer::Project *project) = 0; + virtual QList<ProjectInfo> projectInfos() const = 0; + virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const = 0; + virtual void updateProjectInfo(const ProjectInfo &pinfo) = 0; }; } // namespace CppTools diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 501068af004..b67535212e7 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -480,23 +480,27 @@ void Qt4Project::updateCodeModel() files += m_projectFiles->files[SourceType]; files += m_projectFiles->generatedFiles[SourceType]; - CppTools::CppModelManagerInterface::ProjectInfo *pinfo = modelmanager->projectInfo(this); + CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this); - if (pinfo->defines == predefinedMacros && - pinfo->includePaths == allIncludePaths && - pinfo->frameworkPaths == allFrameworkPaths && - pinfo->sourceFiles == files) { - // Nothing to update... + if (pinfo.defines == predefinedMacros && + pinfo.includePaths == allIncludePaths && + pinfo.frameworkPaths == allFrameworkPaths && + pinfo.sourceFiles == files) { + modelmanager->updateProjectInfo(pinfo); } else { - pinfo->defines = predefinedMacros; + pinfo.defines = predefinedMacros; // pinfo->defines += definedMacros; // ### FIXME: me - pinfo->includePaths = allIncludePaths; - pinfo->frameworkPaths = allFrameworkPaths; - pinfo->sourceFiles = files; + pinfo.includePaths = allIncludePaths; + pinfo.frameworkPaths = allFrameworkPaths; + pinfo.sourceFiles = files; + + modelmanager->updateProjectInfo(pinfo); modelmanager->GC(); - modelmanager->updateSourceFiles(pinfo->sourceFiles); + modelmanager->updateSourceFiles(pinfo.sourceFiles); } + + // update info } From 045e6dd1b4e97e5e79ec60db85e81616275fb770 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 11:00:46 +0100 Subject: [PATCH 23/41] simplify WatchWindow expansion handling a bit --- src/plugins/debugger/watchhandler.cpp | 7 ++++ src/plugins/debugger/watchhandler.h | 2 +- src/plugins/debugger/watchwindow.cpp | 52 +++------------------------ src/plugins/debugger/watchwindow.h | 4 --- 4 files changed, 13 insertions(+), 52 deletions(-) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 1792e4705d6..1041c2edcc6 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -488,6 +488,13 @@ QVariant WatchHandler::data(const QModelIndex &idx, int role) const case VisualRole: return m_displayedINames.contains(data.iname); + case ExpandedRole: + //qDebug() << " FETCHING: " << data.iname + // << m_expandedINames.contains(data.iname) + // << m_expandedINames; + // Level 0 and 1 are always expanded + return node < 4 || m_expandedINames.contains(data.iname); + default: break; } diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 989b99b3d22..f27e167dc1b 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -135,7 +135,7 @@ public: bool changed; }; -enum { INameRole = Qt::UserRole, VisualRole }; +enum { INameRole = Qt::UserRole, VisualRole, ExpandedRole }; class WatchHandler : public QAbstractItemModel diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index d528bf09242..f49b7073aef 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -46,7 +46,7 @@ using namespace Debugger::Internal; -enum { INameRole = Qt::UserRole, VisualRole }; +enum { INameRole = Qt::UserRole, VisualRole, ExpandedRole }; ///////////////////////////////////////////////////////////////////// // @@ -75,8 +75,6 @@ void WatchWindow::expandNode(const QModelIndex &idx) //QModelIndex mi0 = idx.sibling(idx.row(), 0); //QString iname = model()->data(mi0, INameRole).toString(); //QString name = model()->data(mi0, Qt::DisplayRole).toString(); - //if (isExpanded(idx)) - // return; emit requestExpandChildren(idx); } @@ -174,6 +172,7 @@ void WatchWindow::reset() QTreeView::reset(); setRootIndex(model()->index(row, 0, model()->index(0, 0))); //setRootIndex(model()->index(0, 0)); + resetHelper(model()->index(0, 0)); } void WatchWindow::setModel(QAbstractItemModel *model) @@ -185,57 +184,16 @@ void WatchWindow::setModel(QAbstractItemModel *model) header()->setResizeMode(QHeaderView::ResizeToContents); if (m_type != LocalsType) header()->hide(); - - connect(model, SIGNAL(modelAboutToBeReset()), - this, SLOT(modelAboutToBeReset())); - connect(model, SIGNAL(modelReset()), - this, SLOT(modelReset())); } -void WatchWindow::modelAboutToBeReset() +void WatchWindow::resetHelper(const QModelIndex &idx) { - //qDebug() << "Model about to be reset"; - m_expandedItems.clear(); - m_expandedItems.insert("local"); - m_expandedItems.insert("watch"); - modelAboutToBeResetHelper(model()->index(0, 0)); - //qDebug() << " expanded: " << m_expandedItems; -} - -void WatchWindow::modelAboutToBeResetHelper(const QModelIndex &idx) -{ - QString iname = model()->data(idx, INameRole).toString(); - //qDebug() << "Model about to be reset helper" << iname << idx - // << isExpanded(idx); - if (isExpanded(idx)) - m_expandedItems.insert(iname); - for (int i = 0, n = model()->rowCount(idx); i != n; ++i) { - QModelIndex idx1 = model()->index(i, 0, idx); - modelAboutToBeResetHelper(idx1); - } -} - -void WatchWindow::modelReset() -{ - collapseAll(); - expand(model()->index(0, 0)); - modelResetHelper(model()->index(0, 0)); -} - -void WatchWindow::modelResetHelper(const QModelIndex &idx) -{ - QString name = model()->data(idx, Qt::DisplayRole).toString(); - QString iname = model()->data(idx, INameRole).toString(); - //qDebug() << "Model reset helper" << iname << name; - if (m_expandedItems.contains(iname)) { + if (model()->data(idx, ExpandedRole).toBool()) { expand(idx); for (int i = 0, n = model()->rowCount(idx); i != n; ++i) { QModelIndex idx1 = model()->index(i, 0, idx); - modelResetHelper(idx1); + resetHelper(idx1); } - } else { - // if (!iname.isEmpty()) - // collapse(idx); } } diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index 8b9b5d13ae4..33aafe1d59b 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -72,20 +72,16 @@ private slots: void handleChangedItem(QWidget *); void expandNode(const QModelIndex &index); void collapseNode(const QModelIndex &index); - void modelAboutToBeReset(); - void modelReset(); private: void contextMenuEvent(QContextMenuEvent *ev); void editItem(const QModelIndex &idx); void reset(); /* reimpl */ - void modelAboutToBeResetHelper(const QModelIndex &idx); void modelResetHelper(const QModelIndex &idx); bool m_alwaysResizeColumnsToContents; Type m_type; - QSet<QString> m_expandedItems; }; From 1f8ce02d06b63c58b7e1a91bb13f9e778d60a5b1 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 11:08:48 +0100 Subject: [PATCH 24/41] Some cleanup in CppPreprocessor. --- src/plugins/cpptools/cppmodelmanager.cpp | 565 ++++++++++++----------- 1 file changed, 296 insertions(+), 269 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index dbc324013c6..6be28d36252 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -31,7 +31,6 @@ ** ***************************************************************************/ -#define _SCL_SECURE_NO_WARNINGS 1 #include "pp.h" #include "cppmodelmanager.h" @@ -70,11 +69,10 @@ #include <QTime> #include <QDebug> +using namespace CppTools; +using namespace CppTools::Internal; using namespace CPlusPlus; -namespace CppTools { -namespace Internal { - static const char pp_configuration_file[] = "<configuration>"; static const char pp_configuration[] = @@ -106,278 +104,40 @@ static const char pp_configuration[] = "#define __declspec(a)\n" "#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n"; +namespace CppTools { +namespace Internal { + class CppPreprocessor: public rpp::Client { public: - CppPreprocessor(QPointer<CppModelManager> modelManager) - : m_modelManager(modelManager), - m_documents(modelManager->documents()), - m_proc(this, env) - { } + CppPreprocessor(QPointer<CppModelManager> modelManager); - void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy) - { m_workingCopy = workingCopy; } - - void setIncludePaths(const QStringList &includePaths) - { m_includePaths = includePaths; } - - void setFrameworkPaths(const QStringList &frameworkPaths) - { m_frameworkPaths = frameworkPaths; } - - void addIncludePath(const QString &path) - { m_includePaths.append(path); } - - void setProjectFiles(const QStringList &files) - { m_projectFiles = files; } - - void run(QString &fileName) - { sourceNeeded(fileName, IncludeGlobal); } - - void operator()(QString &fileName) - { run(fileName); } + void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy); + void setIncludePaths(const QStringList &includePaths); + void setFrameworkPaths(const QStringList &frameworkPaths); + void addIncludePath(const QString &path); + void setProjectFiles(const QStringList &files); + void run(QString &fileName); + void operator()(QString &fileName); protected: - bool includeFile(const QString &absoluteFilePath, QByteArray *result) - { - if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) { - return true; - } + CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); - if (m_workingCopy.contains(absoluteFilePath)) { - m_included.insert(absoluteFilePath); - *result = m_workingCopy.value(absoluteFilePath); - return true; - } + bool includeFile(const QString &absoluteFilePath, QByteArray *result); + QByteArray tryIncludeFile(QString &fileName, IncludeType type); - QFileInfo fileInfo(absoluteFilePath); - if (! fileInfo.isFile()) - return false; - - QFile file(absoluteFilePath); - if (file.open(QFile::ReadOnly)) { - m_included.insert(absoluteFilePath); - QTextStream stream(&file); - const QString contents = stream.readAll(); - *result = contents.toUtf8(); - file.close(); - return true; - } - - return false; - } - - QByteArray tryIncludeFile(QString &fileName, IncludeType type) - { - QFileInfo fileInfo(fileName); - if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) { - QByteArray contents; - includeFile(fileName, &contents); - return contents; - } - - if (type == IncludeLocal && m_currentDoc) { - QFileInfo currentFileInfo(m_currentDoc->fileName()); - QString path = currentFileInfo.absolutePath(); - path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } - } - - foreach (const QString &includePath, m_includePaths) { - QString path = includePath; - path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } - } - - // look in the system include paths - foreach (const QString &includePath, m_systemIncludePaths) { - QString path = includePath; - path += QLatin1Char('/'); - path += fileName; - path = QDir::cleanPath(path); - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } - } - - int index = fileName.indexOf(QLatin1Char('/')); - if (index != -1) { - QString frameworkName = fileName.left(index); - QString name = fileName.mid(index + 1); - - foreach (const QString &frameworkPath, m_frameworkPaths) { - QString path = frameworkPath; - path += QLatin1Char('/'); - path += frameworkName; - path += QLatin1String(".framework/Headers/"); - path += name; - QByteArray contents; - if (includeFile(path, &contents)) { - fileName = path; - return contents; - } - } - } - - QString path = fileName; - if (path.at(0) != QLatin1Char('/')) - path.prepend(QLatin1Char('/')); - - foreach (const QString &projectFile, m_projectFiles) { - if (projectFile.endsWith(path)) { - fileName = projectFile; - QByteArray contents; - includeFile(fileName, &contents); - return contents; - } - } - - //qDebug() << "**** file" << fileName << "not found!"; - return QByteArray(); - } - - virtual void macroAdded(const QByteArray ¯oName, const QByteArray ¯oText) - { - if (! m_currentDoc) - return; - - m_currentDoc->appendMacro(macroName, macroText); - } + void mergeEnvironment(CPlusPlus::Document::Ptr doc); + void mergeEnvironment(CPlusPlus::Document::Ptr doc, QSet<QString> *processed); + virtual void macroAdded(const QByteArray ¯oName, + const QByteArray ¯oText); virtual void startExpandingMacro(unsigned offset, - const rpp::Macro &, - const QByteArray &originalText) - { - if (! m_currentDoc) - return; - - //qDebug() << "start expanding:" << macro.name << "text:" << originalText; - m_currentDoc->addMacroUse(offset, originalText.length()); - } - - virtual void stopExpandingMacro(unsigned, const rpp::Macro &) - { - if (! m_currentDoc) - return; - - //qDebug() << "stop expanding:" << macro.name; - } - - void mergeEnvironment(Document::Ptr doc) - { - QSet<QString> processed; - mergeEnvironment(doc, &processed); - } - - void mergeEnvironment(Document::Ptr doc, QSet<QString> *processed) - { - if (! doc) - return; - - const QString fn = doc->fileName(); - - if (processed->contains(fn)) - return; - - processed->insert(fn); - - foreach (QString includedFile, doc->includedFiles()) - mergeEnvironment(m_documents.value(includedFile), processed); - - const QByteArray macros = doc->definedMacros(); - QByteArray localFileName = doc->fileName().toUtf8(); - - QByteArray dummy; - m_proc(localFileName, macros, &dummy); - } - - virtual void startSkippingBlocks(unsigned offset) - { - //qDebug() << "start skipping blocks:" << offset; - if (m_currentDoc) - m_currentDoc->startSkippingBlocks(offset); - } - - virtual void stopSkippingBlocks(unsigned offset) - { - //qDebug() << "stop skipping blocks:" << offset; - if (m_currentDoc) - m_currentDoc->stopSkippingBlocks(offset); - } - - virtual void sourceNeeded(QString &fileName, IncludeType type) - { - if (fileName.isEmpty()) - return; - - QByteArray contents = tryIncludeFile(fileName, type); - - if (m_currentDoc) { - m_currentDoc->addIncludeFile(fileName); - if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) { - QString msg; - msg += fileName; - msg += QLatin1String(": No such file or directory"); - Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning, - m_currentDoc->fileName(), - env.currentLine, /*column = */ 0, - msg); - m_currentDoc->addDiagnosticMessage(d); - //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line; - } - } - - if (! contents.isEmpty()) { - Document::Ptr cachedDoc = m_documents.value(fileName); - if (cachedDoc && m_currentDoc) { - mergeEnvironment(cachedDoc); - } else { - Document::Ptr previousDoc = switchDocument(Document::create(fileName)); - - const QByteArray previousFile = env.current_file; - const unsigned previousLine = env.currentLine; - - env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(), - m_currentDoc->translationUnit()->fileNameLength()); - - QByteArray preprocessedCode; - m_proc(contents, &preprocessedCode); - //qDebug() << preprocessedCode; - - env.current_file = previousFile; - env.currentLine = previousLine; - - m_currentDoc->setSource(preprocessedCode); - m_currentDoc->parse(); - m_currentDoc->check(); - m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream. - - if (m_modelManager) - m_modelManager->emitDocumentUpdated(m_currentDoc); - (void) switchDocument(previousDoc); - } - } - } - - Document::Ptr switchDocument(Document::Ptr doc) - { - Document::Ptr previousDoc = m_currentDoc; - m_currentDoc = doc; - return previousDoc; - } + const rpp::Macro ¯o, + const QByteArray &originalText); + virtual void stopExpandingMacro(unsigned offset, const rpp::Macro ¯o); + virtual void startSkippingBlocks(unsigned offset); + virtual void stopSkippingBlocks(unsigned offset); + virtual void sourceNeeded(QString &fileName, IncludeType type); private: QPointer<CppModelManager> m_modelManager; @@ -390,15 +150,282 @@ private: QStringList m_projectFiles; QStringList m_frameworkPaths; QSet<QString> m_included; - Document::Ptr m_currentDoc; + CPlusPlus::Document::Ptr m_currentDoc; }; } // namespace Internal } // namespace CppTools +CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) + : m_modelManager(modelManager), + m_documents(modelManager->documents()), + m_proc(this, env) +{ } + +void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy) +{ m_workingCopy = workingCopy; } + +void CppPreprocessor::setIncludePaths(const QStringList &includePaths) +{ m_includePaths = includePaths; } + +void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths) +{ m_frameworkPaths = frameworkPaths; } + +void CppPreprocessor::addIncludePath(const QString &path) +{ m_includePaths.append(path); } + +void CppPreprocessor::setProjectFiles(const QStringList &files) +{ m_projectFiles = files; } + +void CppPreprocessor::run(QString &fileName) +{ sourceNeeded(fileName, IncludeGlobal); } + +void CppPreprocessor::operator()(QString &fileName) +{ run(fileName); } + +bool CppPreprocessor::includeFile(const QString &absoluteFilePath, QByteArray *result) +{ + if (absoluteFilePath.isEmpty() || m_included.contains(absoluteFilePath)) { + return true; + } + + if (m_workingCopy.contains(absoluteFilePath)) { + m_included.insert(absoluteFilePath); + *result = m_workingCopy.value(absoluteFilePath); + return true; + } + + QFileInfo fileInfo(absoluteFilePath); + if (! fileInfo.isFile()) + return false; + + QFile file(absoluteFilePath); + if (file.open(QFile::ReadOnly)) { + m_included.insert(absoluteFilePath); + QTextStream stream(&file); + const QString contents = stream.readAll(); + *result = contents.toUtf8(); + file.close(); + return true; + } + + return false; +} + +QByteArray CppPreprocessor::tryIncludeFile(QString &fileName, IncludeType type) +{ + QFileInfo fileInfo(fileName); + if (fileName == QLatin1String(pp_configuration_file) || fileInfo.isAbsolute()) { + QByteArray contents; + includeFile(fileName, &contents); + return contents; + } + + if (type == IncludeLocal && m_currentDoc) { + QFileInfo currentFileInfo(m_currentDoc->fileName()); + QString path = currentFileInfo.absolutePath(); + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; + } + } + + foreach (const QString &includePath, m_includePaths) { + QString path = includePath; + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; + } + } + + // look in the system include paths + foreach (const QString &includePath, m_systemIncludePaths) { + QString path = includePath; + path += QLatin1Char('/'); + path += fileName; + path = QDir::cleanPath(path); + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; + } + } + + int index = fileName.indexOf(QLatin1Char('/')); + if (index != -1) { + QString frameworkName = fileName.left(index); + QString name = fileName.mid(index + 1); + + foreach (const QString &frameworkPath, m_frameworkPaths) { + QString path = frameworkPath; + path += QLatin1Char('/'); + path += frameworkName; + path += QLatin1String(".framework/Headers/"); + path += name; + QByteArray contents; + if (includeFile(path, &contents)) { + fileName = path; + return contents; + } + } + } + + QString path = fileName; + if (path.at(0) != QLatin1Char('/')) + path.prepend(QLatin1Char('/')); + + foreach (const QString &projectFile, m_projectFiles) { + if (projectFile.endsWith(path)) { + fileName = projectFile; + QByteArray contents; + includeFile(fileName, &contents); + return contents; + } + } + + //qDebug() << "**** file" << fileName << "not found!"; + return QByteArray(); +} + +void CppPreprocessor::macroAdded(const QByteArray ¯oName, const QByteArray ¯oText) +{ + if (! m_currentDoc) + return; + + m_currentDoc->appendMacro(macroName, macroText); +} + +void CppPreprocessor::startExpandingMacro(unsigned offset, + const rpp::Macro &, + const QByteArray &originalText) +{ + if (! m_currentDoc) + return; + + //qDebug() << "start expanding:" << macro.name << "text:" << originalText; + m_currentDoc->addMacroUse(offset, originalText.length()); +} + +void CppPreprocessor::stopExpandingMacro(unsigned, const rpp::Macro &) +{ + if (! m_currentDoc) + return; + + //qDebug() << "stop expanding:" << macro.name; +} + +void CppPreprocessor::mergeEnvironment(Document::Ptr doc) +{ + QSet<QString> processed; + mergeEnvironment(doc, &processed); +} + +void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *processed) +{ + if (! doc) + return; + + const QString fn = doc->fileName(); + + if (processed->contains(fn)) + return; + + processed->insert(fn); + + foreach (QString includedFile, doc->includedFiles()) + mergeEnvironment(m_documents.value(includedFile), processed); + + const QByteArray macros = doc->definedMacros(); + QByteArray localFileName = doc->fileName().toUtf8(); + + QByteArray dummy; + m_proc(localFileName, macros, &dummy); +} + +void CppPreprocessor::startSkippingBlocks(unsigned offset) +{ + //qDebug() << "start skipping blocks:" << offset; + if (m_currentDoc) + m_currentDoc->startSkippingBlocks(offset); +} + +void CppPreprocessor::stopSkippingBlocks(unsigned offset) +{ + //qDebug() << "stop skipping blocks:" << offset; + if (m_currentDoc) + m_currentDoc->stopSkippingBlocks(offset); +} + +void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type) +{ + if (fileName.isEmpty()) + return; + + QByteArray contents = tryIncludeFile(fileName, type); + + if (m_currentDoc) { + m_currentDoc->addIncludeFile(fileName); + if (contents.isEmpty() && ! QFileInfo(fileName).isAbsolute()) { + QString msg; + msg += fileName; + msg += QLatin1String(": No such file or directory"); + Document::DiagnosticMessage d(Document::DiagnosticMessage::Warning, + m_currentDoc->fileName(), + env.currentLine, /*column = */ 0, + msg); + m_currentDoc->addDiagnosticMessage(d); + //qWarning() << "file not found:" << fileName << m_currentDoc->fileName() << env.current_line; + } + } + + if (! contents.isEmpty()) { + Document::Ptr cachedDoc = m_documents.value(fileName); + if (cachedDoc && m_currentDoc) { + mergeEnvironment(cachedDoc); + } else { + Document::Ptr previousDoc = switchDocument(Document::create(fileName)); + + const QByteArray previousFile = env.current_file; + const unsigned previousLine = env.currentLine; + + env.current_file = QByteArray(m_currentDoc->translationUnit()->fileName(), + m_currentDoc->translationUnit()->fileNameLength()); + + QByteArray preprocessedCode; + m_proc(contents, &preprocessedCode); + //qDebug() << preprocessedCode; + + env.current_file = previousFile; + env.currentLine = previousLine; + + m_currentDoc->setSource(preprocessedCode); + m_currentDoc->parse(); + m_currentDoc->check(); + m_currentDoc->releaseTranslationUnit(); // release the AST and the token stream. + + if (m_modelManager) + m_modelManager->emitDocumentUpdated(m_currentDoc); + (void) switchDocument(previousDoc); + } + } +} + +Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc) +{ + Document::Ptr previousDoc = m_currentDoc; + m_currentDoc = doc; + return previousDoc; +} + -using namespace CppTools; -using namespace CppTools::Internal; /*! \class CppTools::CppModelManager From e47967312e65e7620774ecc797a070dacc064afb Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 11:58:36 +0100 Subject: [PATCH 25/41] compile fix --- src/plugins/debugger/gdbengine.cpp | 2 ++ src/plugins/debugger/watchwindow.h | 2 +- tests/manual/gdbdebugger/simple/app.cpp | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 1802c018001..9336981b128 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1271,6 +1271,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (isStoppedReason(reason) || reason.isEmpty()) { // Need another round trip if (reason == "breakpoint-hit") { + q->showStatusMessage(tr("Stopped at breakpoint."), -1); GdbMi frame = data.findChild("frame"); //qDebug() << frame.toString(); m_currentFrame = frame.findChild("addr").data() + '%' + @@ -1282,6 +1283,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) QVariant var = QVariant::fromValue<GdbMi>(data); sendCommand("p 0", GdbAsyncOutput2, var); // dummy } else { + q->showStatusMessage(tr("Stopped. %1").arg(reason), -1); handleAsyncOutput2(data); } return; diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index 33aafe1d59b..c292bebb5f6 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -78,7 +78,7 @@ private: void editItem(const QModelIndex &idx); void reset(); /* reimpl */ - void modelResetHelper(const QModelIndex &idx); + void resetHelper(const QModelIndex &idx); bool m_alwaysResizeColumnsToContents; Type m_type; diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 4a1ec67e7ab..958c8985b05 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -785,8 +785,13 @@ int main(int argc, char *argv[]) testVariant3(); testVector(); testVectorOfList(); + + + *(int *)0 = 0; + testObject(argc, argv); + //QColor color(255,128,10); //QFont font; From 358eceacfd07393bd0e70c01200263516559f37f Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 12:01:53 +0100 Subject: [PATCH 26/41] whitespace cosmetics --- src/plugins/coreplugin/viewmanager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/coreplugin/viewmanager.cpp b/src/plugins/coreplugin/viewmanager.cpp index 71ee1132994..b7b59f048ae 100644 --- a/src/plugins/coreplugin/viewmanager.cpp +++ b/src/plugins/coreplugin/viewmanager.cpp @@ -63,7 +63,7 @@ ViewManager::ViewManager(MainWindow *mainWnd) : ViewManagerInterface(mainWnd), m_mainWnd(mainWnd) { - for(int i = 0; i< 3; ++i) { + for (int i = 0; i < 3; ++i) { QWidget *w = new QWidget(); m_mainWnd->statusBar()->insertPermanentWidget(i, w); w->setLayout(new QHBoxLayout); @@ -89,7 +89,7 @@ void ViewManager::init() void ViewManager::objectAdded(QObject *obj) { - IView * view = Aggregation::query<IView>(obj); + IView *view = Aggregation::query<IView>(obj); if (!view) return; @@ -104,8 +104,8 @@ void ViewManager::objectAdded(QObject *obj) void ViewManager::aboutToRemoveObject(QObject *obj) { - IView * view = Aggregation::query<IView>(obj); - if(!view) + IView *view = Aggregation::query<IView>(obj); + if (!view) return; m_mainWnd->removeContextObject(view); } @@ -121,10 +121,10 @@ void ViewManager::saveSettings(QSettings *settings) settings->setValue(QLatin1String("ViewGroup_Default"), m_mainWnd->saveState()); } -IView * ViewManager::view(const QString & id) +IView *ViewManager::view(const QString &id) { QList<IView *> list = m_mainWnd->pluginManager()->getObjects<IView>(); - foreach (IView * view, list) { + foreach (IView *view, list) { if (view->uniqueViewName() == id) return view; } From 520a5c9e65b677086dbf82a801d07fd784777054 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 12:17:39 +0100 Subject: [PATCH 27/41] Put the preprocessor the CPlusPlus namespace --- src/plugins/cpptools/cppmodelmanager.cpp | 14 +++++++------- src/plugins/cpptools/rpp/pp-cctype.h | 4 ++-- src/plugins/cpptools/rpp/pp-client.h | 4 ++-- src/plugins/cpptools/rpp/pp-engine.cpp | 1 - src/plugins/cpptools/rpp/pp-engine.h | 6 +++--- src/plugins/cpptools/rpp/pp-environment.cpp | 2 +- src/plugins/cpptools/rpp/pp-environment.h | 4 ++-- src/plugins/cpptools/rpp/pp-internal.h | 4 ++-- src/plugins/cpptools/rpp/pp-macro-expander.cpp | 2 +- src/plugins/cpptools/rpp/pp-macro-expander.h | 4 ++-- src/plugins/cpptools/rpp/pp-macro.h | 4 ++-- src/plugins/cpptools/rpp/pp-scanner.h | 4 ++-- 12 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6be28d36252..af885de622f 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -107,7 +107,7 @@ static const char pp_configuration[] = namespace CppTools { namespace Internal { -class CppPreprocessor: public rpp::Client +class CppPreprocessor: public CPlusPlus::Client { public: CppPreprocessor(QPointer<CppModelManager> modelManager); @@ -132,9 +132,9 @@ protected: virtual void macroAdded(const QByteArray ¯oName, const QByteArray ¯oText); virtual void startExpandingMacro(unsigned offset, - const rpp::Macro ¯o, + const Macro ¯o, const QByteArray &originalText); - virtual void stopExpandingMacro(unsigned offset, const rpp::Macro ¯o); + virtual void stopExpandingMacro(unsigned offset, const Macro ¯o); virtual void startSkippingBlocks(unsigned offset); virtual void stopSkippingBlocks(unsigned offset); virtual void sourceNeeded(QString &fileName, IncludeType type); @@ -142,8 +142,8 @@ protected: private: QPointer<CppModelManager> m_modelManager; CppModelManager::DocumentTable m_documents; - rpp::Environment env; - rpp::pp m_proc; + Environment env; + pp m_proc; QStringList m_includePaths; QStringList m_systemIncludePaths; QMap<QString, QByteArray> m_workingCopy; @@ -304,7 +304,7 @@ void CppPreprocessor::macroAdded(const QByteArray ¯oName, const QByteArray & } void CppPreprocessor::startExpandingMacro(unsigned offset, - const rpp::Macro &, + const Macro &, const QByteArray &originalText) { if (! m_currentDoc) @@ -314,7 +314,7 @@ void CppPreprocessor::startExpandingMacro(unsigned offset, m_currentDoc->addMacroUse(offset, originalText.length()); } -void CppPreprocessor::stopExpandingMacro(unsigned, const rpp::Macro &) +void CppPreprocessor::stopExpandingMacro(unsigned, const Macro &) { if (! m_currentDoc) return; diff --git a/src/plugins/cpptools/rpp/pp-cctype.h b/src/plugins/cpptools/rpp/pp-cctype.h index 62b44f0bf4c..bec9c25aef1 100644 --- a/src/plugins/cpptools/rpp/pp-cctype.h +++ b/src/plugins/cpptools/rpp/pp-cctype.h @@ -55,7 +55,7 @@ #include <cctype> -namespace rpp { +namespace CPlusPlus { inline bool pp_isalpha (int __ch) { return std::isalpha ((unsigned char) __ch) != 0; } @@ -69,6 +69,6 @@ inline bool pp_isdigit (int __ch) inline bool pp_isspace (int __ch) { return std::isspace ((unsigned char) __ch) != 0; } -} // namespace rpp +} // namespace CPlusPlus #endif // PP_CCTYPE_H diff --git a/src/plugins/cpptools/rpp/pp-client.h b/src/plugins/cpptools/rpp/pp-client.h index 974004a6ce5..35df6497331 100644 --- a/src/plugins/cpptools/rpp/pp-client.h +++ b/src/plugins/cpptools/rpp/pp-client.h @@ -38,7 +38,7 @@ #include <QString> #include <QFile> -namespace rpp { +namespace CPlusPlus { class Macro; @@ -74,6 +74,6 @@ public: virtual void stopSkippingBlocks(unsigned offset) = 0; }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_CLIENT_H diff --git a/src/plugins/cpptools/rpp/pp-engine.cpp b/src/plugins/cpptools/rpp/pp-engine.cpp index 66e8957f355..f2e1d4908eb 100644 --- a/src/plugins/cpptools/rpp/pp-engine.cpp +++ b/src/plugins/cpptools/rpp/pp-engine.cpp @@ -57,7 +57,6 @@ #include <QtDebug> #include <algorithm> -using namespace rpp; using namespace CPlusPlus; namespace { diff --git a/src/plugins/cpptools/rpp/pp-engine.h b/src/plugins/cpptools/rpp/pp-engine.h index 13135f6a310..d0729b3715b 100644 --- a/src/plugins/cpptools/rpp/pp-engine.h +++ b/src/plugins/cpptools/rpp/pp-engine.h @@ -62,7 +62,7 @@ namespace CPlusPlus { class Token; } -namespace rpp { +namespace CPlusPlus { struct Value { @@ -200,7 +200,7 @@ namespace rpp { Value evalExpression(TokenIterator firstToken, TokenIterator lastToken, - const QByteArray &source) const; + const QByteArray &source) const; QVector<CPlusPlus::Token> tokenize(const QByteArray &text) const; @@ -226,6 +226,6 @@ namespace rpp { bool isQtReservedWord(const QByteArray &name) const; }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_ENGINE_H diff --git a/src/plugins/cpptools/rpp/pp-environment.cpp b/src/plugins/cpptools/rpp/pp-environment.cpp index 85e432ae5b5..b06d41757dd 100644 --- a/src/plugins/cpptools/rpp/pp-environment.cpp +++ b/src/plugins/cpptools/rpp/pp-environment.cpp @@ -54,7 +54,7 @@ #include "pp.h" #include <cstring> -using namespace rpp; +using namespace CPlusPlus; Environment::Environment () : currentLine(0), diff --git a/src/plugins/cpptools/rpp/pp-environment.h b/src/plugins/cpptools/rpp/pp-environment.h index 5b97c492d79..e3d130871ba 100644 --- a/src/plugins/cpptools/rpp/pp-environment.h +++ b/src/plugins/cpptools/rpp/pp-environment.h @@ -56,7 +56,7 @@ #include <QVector> #include <QByteArray> -namespace rpp { +namespace CPlusPlus { struct Macro; @@ -104,6 +104,6 @@ private: int _hash_count; }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_ENVIRONMENT_H diff --git a/src/plugins/cpptools/rpp/pp-internal.h b/src/plugins/cpptools/rpp/pp-internal.h index 13bc7c17e84..c11de37453a 100644 --- a/src/plugins/cpptools/rpp/pp-internal.h +++ b/src/plugins/cpptools/rpp/pp-internal.h @@ -55,7 +55,7 @@ #include <QByteArray> -namespace rpp { +namespace CPlusPlus { namespace _PP_internal { inline bool comment_p (const char *__first, const char *__last) @@ -73,6 +73,6 @@ inline bool comment_p (const char *__first, const char *__last) } } // _PP_internal -} // namespace rpp +} // namespace CPlusPlus #endif // PP_INTERNAL_H diff --git a/src/plugins/cpptools/rpp/pp-macro-expander.cpp b/src/plugins/cpptools/rpp/pp-macro-expander.cpp index 6b569eb132f..9ae9702fe18 100644 --- a/src/plugins/cpptools/rpp/pp-macro-expander.cpp +++ b/src/plugins/cpptools/rpp/pp-macro-expander.cpp @@ -35,7 +35,7 @@ #include "pp-macro-expander.h" #include <QDateTime> -using namespace rpp; +using namespace CPlusPlus; MacroExpander::MacroExpander (Environment &env, pp_frame *frame) : env(env), frame(frame), diff --git a/src/plugins/cpptools/rpp/pp-macro-expander.h b/src/plugins/cpptools/rpp/pp-macro-expander.h index dd11540c336..c2f636c1385 100644 --- a/src/plugins/cpptools/rpp/pp-macro-expander.h +++ b/src/plugins/cpptools/rpp/pp-macro-expander.h @@ -53,7 +53,7 @@ #ifndef PP_MACRO_EXPANDER_H #define PP_MACRO_EXPANDER_H -namespace rpp { +namespace CPlusPlus { struct pp_frame { @@ -97,7 +97,7 @@ namespace rpp { int generated_lines; }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_MACRO_EXPANDER_H diff --git a/src/plugins/cpptools/rpp/pp-macro.h b/src/plugins/cpptools/rpp/pp-macro.h index a7bbe35e1d5..b091abd6184 100644 --- a/src/plugins/cpptools/rpp/pp-macro.h +++ b/src/plugins/cpptools/rpp/pp-macro.h @@ -56,7 +56,7 @@ #include <QByteArray> #include <QVector> -namespace rpp { +namespace CPlusPlus { struct Macro { @@ -90,6 +90,6 @@ namespace rpp { { } }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_MACRO_H diff --git a/src/plugins/cpptools/rpp/pp-scanner.h b/src/plugins/cpptools/rpp/pp-scanner.h index 53fea70b52f..85b65403b0b 100644 --- a/src/plugins/cpptools/rpp/pp-scanner.h +++ b/src/plugins/cpptools/rpp/pp-scanner.h @@ -53,7 +53,7 @@ #ifndef PP_SCANNER_H #define PP_SCANNER_H -namespace rpp { +namespace CPlusPlus { struct pp_skip_blanks { @@ -373,7 +373,7 @@ struct pp_skip_argument } }; -} // namespace rpp +} // namespace CPlusPlus #endif // PP_SCANNER_H From f6fbb274ae715c05fcdee61cba5395b4fd4814b9 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 12:24:40 +0100 Subject: [PATCH 28/41] Moved the preprocessor. --- src/libs/cplusplus/cplusplus.pro | 16 ++++++++++++++-- .../rpp => libs/cplusplus}/pp-cctype.h | 0 .../rpp => libs/cplusplus}/pp-client.h | 0 .../rpp => libs/cplusplus}/pp-engine.cpp | 0 .../rpp => libs/cplusplus}/pp-engine.h | 0 .../rpp => libs/cplusplus}/pp-environment.cpp | 0 .../rpp => libs/cplusplus}/pp-environment.h | 0 .../cpptools/rpp => libs/cplusplus}/pp-fwd.h | 0 .../rpp => libs/cplusplus}/pp-internal.h | 0 .../cplusplus}/pp-macro-expander.cpp | 0 .../rpp => libs/cplusplus}/pp-macro-expander.h | 0 .../cpptools/rpp => libs/cplusplus}/pp-macro.h | 0 .../rpp => libs/cplusplus}/pp-scanner.h | 0 .../cpptools/rpp => libs/cplusplus}/pp.h | 0 src/plugins/cpptools/cpptools.pro | 2 +- src/plugins/cpptools/rpp/rpp.pri | 18 ------------------ 16 files changed, 15 insertions(+), 21 deletions(-) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-cctype.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-client.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-engine.cpp (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-engine.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-environment.cpp (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-environment.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-fwd.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-internal.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-macro-expander.cpp (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-macro-expander.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-macro.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp-scanner.h (100%) rename src/{plugins/cpptools/rpp => libs/cplusplus}/pp.h (100%) delete mode 100644 src/plugins/cpptools/rpp/rpp.pri diff --git a/src/libs/cplusplus/cplusplus.pro b/src/libs/cplusplus/cplusplus.pro index 1a2b5326623..49d78fda8b3 100644 --- a/src/libs/cplusplus/cplusplus.pro +++ b/src/libs/cplusplus/cplusplus.pro @@ -21,7 +21,16 @@ HEADERS += \ TypeOfExpression.h \ TypePrettyPrinter.h \ ResolveExpression.h \ - LookupContext.h + LookupContext.h \ + pp-cctype.h \ + pp-engine.h \ + pp-fwd.h \ + pp-macro-expander.h \ + pp-scanner.h \ + pp-client.h \ + pp-environment.h \ + pp-internal.h \ + pp-macro.h SOURCES += \ SimpleLexer.cpp \ @@ -35,6 +44,9 @@ SOURCES += \ TypeOfExpression.cpp \ TypePrettyPrinter.cpp \ ResolveExpression.cpp \ - LookupContext.cpp + LookupContext.cpp \ + pp-engine.cpp \ + pp-environment.cpp \ + pp-macro-expander.cpp RESOURCES += cplusplus.qrc diff --git a/src/plugins/cpptools/rpp/pp-cctype.h b/src/libs/cplusplus/pp-cctype.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-cctype.h rename to src/libs/cplusplus/pp-cctype.h diff --git a/src/plugins/cpptools/rpp/pp-client.h b/src/libs/cplusplus/pp-client.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-client.h rename to src/libs/cplusplus/pp-client.h diff --git a/src/plugins/cpptools/rpp/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp similarity index 100% rename from src/plugins/cpptools/rpp/pp-engine.cpp rename to src/libs/cplusplus/pp-engine.cpp diff --git a/src/plugins/cpptools/rpp/pp-engine.h b/src/libs/cplusplus/pp-engine.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-engine.h rename to src/libs/cplusplus/pp-engine.h diff --git a/src/plugins/cpptools/rpp/pp-environment.cpp b/src/libs/cplusplus/pp-environment.cpp similarity index 100% rename from src/plugins/cpptools/rpp/pp-environment.cpp rename to src/libs/cplusplus/pp-environment.cpp diff --git a/src/plugins/cpptools/rpp/pp-environment.h b/src/libs/cplusplus/pp-environment.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-environment.h rename to src/libs/cplusplus/pp-environment.h diff --git a/src/plugins/cpptools/rpp/pp-fwd.h b/src/libs/cplusplus/pp-fwd.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-fwd.h rename to src/libs/cplusplus/pp-fwd.h diff --git a/src/plugins/cpptools/rpp/pp-internal.h b/src/libs/cplusplus/pp-internal.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-internal.h rename to src/libs/cplusplus/pp-internal.h diff --git a/src/plugins/cpptools/rpp/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp similarity index 100% rename from src/plugins/cpptools/rpp/pp-macro-expander.cpp rename to src/libs/cplusplus/pp-macro-expander.cpp diff --git a/src/plugins/cpptools/rpp/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-macro-expander.h rename to src/libs/cplusplus/pp-macro-expander.h diff --git a/src/plugins/cpptools/rpp/pp-macro.h b/src/libs/cplusplus/pp-macro.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-macro.h rename to src/libs/cplusplus/pp-macro.h diff --git a/src/plugins/cpptools/rpp/pp-scanner.h b/src/libs/cplusplus/pp-scanner.h similarity index 100% rename from src/plugins/cpptools/rpp/pp-scanner.h rename to src/libs/cplusplus/pp-scanner.h diff --git a/src/plugins/cpptools/rpp/pp.h b/src/libs/cplusplus/pp.h similarity index 100% rename from src/plugins/cpptools/rpp/pp.h rename to src/libs/cplusplus/pp.h diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro index 8a096900ebf..92905e42ef9 100644 --- a/src/plugins/cpptools/cpptools.pro +++ b/src/plugins/cpptools/cpptools.pro @@ -10,7 +10,7 @@ unix:QMAKE_CXXFLAGS_DEBUG += -O3 INCLUDEPATH += . DEFINES += CPPTOOLS_LIBRARY CONFIG += help -include(rpp/rpp.pri)|error("Can't find RPP") + HEADERS += cpptools_global.h \ cppquickopenfilter.h \ cppclassesfilter.h \ diff --git a/src/plugins/cpptools/rpp/rpp.pri b/src/plugins/cpptools/rpp/rpp.pri deleted file mode 100644 index a79b0028a05..00000000000 --- a/src/plugins/cpptools/rpp/rpp.pri +++ /dev/null @@ -1,18 +0,0 @@ -DEPENDPATH += $$PWD -INCLUDEPATH += $$PWD - -HEADERS += $$PWD/pp-cctype.h \ - $$PWD/pp-engine.h \ - $$PWD/pp-environment.h \ - $$PWD/pp-internal.h \ - $$PWD/pp-macro-expander.h \ - $$PWD/pp-macro.h \ - $$PWD/pp-scanner.h \ - $$PWD/pp.h \ - $$PWD/pp-client.h - -SOURCES += $$PWD/pp-engine.cpp \ - $$PWD/pp-environment.cpp \ - $$PWD/pp-macro-expander.cpp - - From e503e1e4e9e4b4482373f1f17eec0655b9562b3e Mon Sep 17 00:00:00 2001 From: dt <qtc-commiter@nokia.com> Date: Mon, 8 Dec 2008 12:24:31 +0100 Subject: [PATCH 29/41] Fixes: Parse all the targets. Task: - RevBy: - AutoTest: - Details: (Only outputs them via qDebug().) --- .../cmakeprojectmanager/cmakeproject.cpp | 28 +++++++++++++++++-- .../cmakeprojectmanager/cmakeproject.h | 5 ++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index fe591fa0041..4eb31302e65 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -393,12 +393,36 @@ void CMakeCbpParser::parseBuild() void CMakeCbpParser::parseTarget() { + m_targetOutput.clear(); + m_targetType = false; + while(!atEnd()) { + readNext(); + if (isEndElement()) { + if (m_targetType && !m_targetOutput.isEmpty()) { + qDebug()<<"found target "<<m_targetOutput; + m_targets.insert(m_targetOutput); + } + return; + } else if (name() == "Compiler") { + parseCompiler(); + } else if (name() == "Option") { + parseTargetOption(); + } else if (isStartElement()) { + parseUnknownElement(); + } + } +} + +void CMakeCbpParser::parseTargetOption() +{ + if (attributes().hasAttribute("output")) + m_targetOutput = attributes().value("output").toString(); + else if (attributes().hasAttribute("type") && attributes().value("type") == "1") + m_targetType = true; while(!atEnd()) { readNext(); if (isEndElement()) { return; - } else if (name() == "Compiler") { - parseCompiler(); } else if (isStartElement()) { parseUnknownElement(); } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index c765c0d3838..a0c821ada5e 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -123,13 +123,18 @@ private: void parseProject(); void parseBuild(); void parseTarget(); + void parseTargetOption(); void parseCompiler(); void parseAdd(); void parseUnit(); void parseUnknownElement(); + QSet<QString> m_targets; QList<ProjectExplorer::FileNode *> m_fileList; QStringList m_includeFiles; + + QString m_targetOutput; + bool m_targetType; }; class CMakeFile : public Core::IFile From 83d5461c7f083277ee5948b6b4bbbd93b63415dc Mon Sep 17 00:00:00 2001 From: dt <qtc-commiter@nokia.com> Date: Mon, 8 Dec 2008 12:44:28 +0100 Subject: [PATCH 30/41] Fixes: Find the qplatformdefs.h file Task: - RevBy: - AutoTest: - Details: Add the include path for qplatformdefs.h to the fot. --- .../cmakeprojectmanager/cmakeproject.cpp | 2 +- src/plugins/qt4projectmanager/qt4project.cpp | 3 ++ .../qt4projectmanager/qtversionmanager.cpp | 47 +++++++++++-------- .../qt4projectmanager/qtversionmanager.h | 2 + 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 4eb31302e65..52c28cbc3d5 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -226,7 +226,7 @@ QStringList CMakeProject::files(FilesMode fileMode) const void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer) { // TODO - Q_UNUSED(writer) + Q_UNUSED(writer); } void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader) diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 501068af004..2e06e1ae4e5 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -474,6 +474,9 @@ void Qt4Project::updateCodeModel() } } + // Add mkspec directory + allIncludePaths.append(qtVersion(activeBuildConfiguration())->mkspecPath()); + QStringList files; files += m_projectFiles->files[HeaderType]; files += m_projectFiles->generatedFiles[HeaderType]; diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 0c68fcd98eb..1262f901785 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -728,6 +728,12 @@ QString QtVersion::mkspec() const return m_mkspec; } +QString QtVersion::mkspecPath() const +{ + updateMkSpec(); + return m_mkspecFullPath; +} + QHash<QString,QString> QtVersion::versionInfo() const { updateVersionInfo(); @@ -1023,24 +1029,24 @@ void QtVersion::updateMkSpec() const //qDebug()<<"Finding mkspec for"<<path(); QString mkspec; - QFile f(path() + "/.qmake.cache"); - if (f.exists() && f.open(QIODevice::ReadOnly)) { - while(!f.atEnd()) { - QByteArray line = f.readLine(); - if(line.startsWith("QMAKESPEC")) { - const QList<QByteArray> &temp = line.split('='); - if(temp.size() == 2) { - mkspec = temp.at(1).trimmed(); - if (mkspec.startsWith("$$QT_BUILD_TREE/mkspecs/")) - mkspec = mkspec.mid(QString("$$QT_BUILD_TREE/mkspecs/").length()); - else if (mkspec.startsWith("$$QT_BUILD_TREE\\mkspecs\\")) - mkspec = mkspec.mid(QString("$$QT_BUILD_TREE\\mkspecs\\").length()); - } - break; - } - } - f.close(); - } else { +// QFile f(path() + "/.qmake.cache"); +// if (f.exists() && f.open(QIODevice::ReadOnly)) { +// while(!f.atEnd()) { +// QByteArray line = f.readLine(); +// if(line.startsWith("QMAKESPEC")) { +// const QList<QByteArray> &temp = line.split('='); +// if(temp.size() == 2) { +// mkspec = temp.at(1).trimmed(); +// if (mkspec.startsWith("$$QT_BUILD_TREE/mkspecs/")) +// mkspec = mkspec.mid(QString("$$QT_BUILD_TREE/mkspecs/").length()); +// else if (mkspec.startsWith("$$QT_BUILD_TREE\\mkspecs\\")) +// mkspec = mkspec.mid(QString("$$QT_BUILD_TREE\\mkspecs\\").length()); +// } +// break; +// } +// } +// f.close(); +// } else { // no .qmake.cache so look at the default mkspec QString mkspecPath = versionInfo().value("QMAKE_MKSPECS"); if (mkspecPath.isEmpty()) @@ -1095,9 +1101,10 @@ void QtVersion::updateMkSpec() const mkspec = f2.symLinkTarget(); } #endif - } +// } - int index =mkspec.lastIndexOf('/'); + m_mkspecFullPath = mkspec; + int index = mkspec.lastIndexOf('/'); if(index == -1) index = mkspec.lastIndexOf('\\'); if (index >= 0 && QDir(mkspec.left(index)).canonicalPath() == QDir(m_path + "/mkspecs/").canonicalPath()) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 5810cfa1c2d..a8ca9570895 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -67,6 +67,7 @@ public: QString path() const; QString sourcePath() const; QString mkspec() const; + QString mkspecPath() const; QString makeCommand() const; QString qmakeCommand() const; // Returns the PREFIX, BINPREFIX, DOCPREFIX and similar information @@ -107,6 +108,7 @@ private: QString m_path; QString m_sourcePath; mutable QString m_mkspec; // updated lazily + mutable QString m_mkspecFullPath; QString m_mingwDirectory; QString m_prependPath; QString m_msvcVersion; From 310d50fd0760eed3558d56709b49dca9ffc74530 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 12:59:33 +0100 Subject: [PATCH 31/41] Use Macros. --- src/libs/cplusplus/CppDocument.cpp | 19 +-------- src/libs/cplusplus/CppDocument.h | 15 +++++--- src/libs/cplusplus/pp-cctype.h | 10 +++-- src/libs/cplusplus/pp-client.h | 6 ++- src/libs/cplusplus/pp-engine.cpp | 21 +++------- src/libs/cplusplus/pp-engine.h | 2 +- src/libs/cplusplus/pp-environment.cpp | 4 +- src/libs/cplusplus/pp-environment.h | 8 ++-- src/libs/cplusplus/pp-macro.h | 45 +++++++++++----------- src/plugins/cpptools/cppcodecompletion.cpp | 4 +- src/plugins/cpptools/cppmodelmanager.cpp | 20 +++++----- 11 files changed, 69 insertions(+), 85 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 3a280416d9b..45ad1f569a5 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -138,19 +138,9 @@ void Document::addIncludeFile(const QString &fileName) _includedFiles.append(fileName); } -QByteArray Document::definedMacros() const +void Document::appendMacro(const Macro ¯o) { - return _definedMacros; -} - -void Document::appendMacro(const QByteArray ¯oName, const QByteArray &text) -{ - int index = macroName.indexOf('('); - if (index == -1) - _macroNames.insert(macroName); - else - _macroNames.insert(macroName.left(index)); - _definedMacros += text; + _definedMacros.append(macro); } void Document::addMacroUse(unsigned offset, unsigned length) @@ -251,11 +241,6 @@ void Document::stopSkippingBlocks(unsigned stop) _skippedBlocks.back() = Block(start, stop); } -QSet<QByteArray> Document::macroNames() const -{ - return _macroNames; -} - bool Document::parse(ParseMode mode) { TranslationUnit::ParseMode m = TranslationUnit::ParseTranlationUnit; diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index e952913a07b..d289c579e9c 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -36,6 +36,8 @@ #include <CPlusPlusForwardDeclarations.h> +#include "pp-macro.h" + #include <QByteArray> #include <QList> #include <QSet> @@ -45,6 +47,8 @@ namespace CPlusPlus { +class Macro; + class CPLUSPLUS_EXPORT Document { Document(const Document &other); @@ -63,10 +67,7 @@ public: QStringList includedFiles() const; void addIncludeFile(const QString &fileName); - QByteArray definedMacros() const; - QSet<QByteArray> macroNames() const; - - void appendMacro(const QByteArray ¯oName, const QByteArray &text); + void appendMacro(const Macro ¯o); void addMacroUse(unsigned offset, unsigned length); @@ -81,6 +82,9 @@ public: Scope *globalSymbols() const; // ### deprecate? Namespace *globalNamespace() const; + QList<Macro> definedMacros() const + { return _definedMacros; } + Symbol *findSymbolAt(unsigned line, unsigned column) const; void setSource(const QByteArray &source); @@ -191,8 +195,7 @@ private: TranslationUnit *_translationUnit; Namespace *_globalNamespace; QList<DiagnosticMessage> _diagnosticMessages; - QByteArray _definedMacros; - QSet<QByteArray> _macroNames; + QList<Macro> _definedMacros; QList<Block> _skippedBlocks; QList<Block> _macroUses; }; diff --git a/src/libs/cplusplus/pp-cctype.h b/src/libs/cplusplus/pp-cctype.h index bec9c25aef1..b7558ae5050 100644 --- a/src/libs/cplusplus/pp-cctype.h +++ b/src/libs/cplusplus/pp-cctype.h @@ -53,20 +53,22 @@ #ifndef PP_CCTYPE_H #define PP_CCTYPE_H +#include <CPlusPlusForwardDeclarations.h> + #include <cctype> namespace CPlusPlus { -inline bool pp_isalpha (int __ch) +inline bool CPLUSPLUS_EXPORT pp_isalpha (int __ch) { return std::isalpha ((unsigned char) __ch) != 0; } -inline bool pp_isalnum (int __ch) +inline bool CPLUSPLUS_EXPORT pp_isalnum (int __ch) { return std::isalnum ((unsigned char) __ch) != 0; } -inline bool pp_isdigit (int __ch) +inline bool CPLUSPLUS_EXPORT pp_isdigit (int __ch) { return std::isdigit ((unsigned char) __ch) != 0; } -inline bool pp_isspace (int __ch) +inline bool CPLUSPLUS_EXPORT pp_isspace (int __ch) { return std::isspace ((unsigned char) __ch) != 0; } } // namespace CPlusPlus diff --git a/src/libs/cplusplus/pp-client.h b/src/libs/cplusplus/pp-client.h index 35df6497331..2fc781f22f5 100644 --- a/src/libs/cplusplus/pp-client.h +++ b/src/libs/cplusplus/pp-client.h @@ -34,6 +34,8 @@ #ifndef PP_CLIENT_H #define PP_CLIENT_H +#include <CPlusPlusForwardDeclarations.h> + #include <QByteArray> #include <QString> #include <QFile> @@ -42,7 +44,7 @@ namespace CPlusPlus { class Macro; -class Client +class CPLUSPLUS_EXPORT Client { Client(const Client &other); void operator=(const Client &other); @@ -60,7 +62,7 @@ public: virtual ~Client() { } - virtual void macroAdded(const QByteArray ¯oId, const QByteArray &text) = 0; + virtual void macroAdded(const Macro ¯o) = 0; virtual void sourceNeeded(QString &fileName, IncludeType mode) = 0; // ### FIX the signature. virtual void startExpandingMacro(unsigned offset, diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index f2e1d4908eb..7bdc9b95d69 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -906,16 +906,8 @@ void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) env.bind(macro); - QByteArray macroText; - macroText.reserve(64); - macroText += "#define "; - - macroText += macroId; - macroText += ' '; - macroText += macro.definition; - macroText += '\n'; - - client->macroAdded(macroId, macroText); + if (client) + client->macroAdded(macro); } void pp::processIf(TokenIterator firstToken, TokenIterator lastToken) @@ -1019,13 +1011,10 @@ void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken) if (tk->is(T_IDENTIFIER)) { const QByteArray macroName = tokenText(*tk); - env.remove(macroName); + const Macro *macro = env.remove(macroName); - QByteArray macroText; - macroText += "#undef "; - macroText += macroName; - macroText += '\n'; - client->macroAdded(macroName, macroText); + if (client && macro) + client->macroAdded(*macro); } } diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index d0729b3715b..c909ffab3a7 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -134,7 +134,7 @@ namespace CPlusPlus { #undef PP_DEFINE_BIN_OP }; - class pp + class CPLUSPLUS_EXPORT pp { Client *client; Environment &env; diff --git a/src/libs/cplusplus/pp-environment.cpp b/src/libs/cplusplus/pp-environment.cpp index b06d41757dd..a1ade3b189a 100644 --- a/src/libs/cplusplus/pp-environment.cpp +++ b/src/libs/cplusplus/pp-environment.cpp @@ -115,12 +115,12 @@ Macro *Environment::bind(const Macro &__macro) return m; } -void Environment::remove (const QByteArray &name) +Macro *Environment::remove (const QByteArray &name) { Macro macro; macro.name = name; macro.hidden = true; - bind(macro); + return bind(macro); } bool Environment::isBuiltinMacro(const QByteArray &s) const diff --git a/src/libs/cplusplus/pp-environment.h b/src/libs/cplusplus/pp-environment.h index e3d130871ba..e2a75d29b81 100644 --- a/src/libs/cplusplus/pp-environment.h +++ b/src/libs/cplusplus/pp-environment.h @@ -53,14 +53,16 @@ #ifndef PP_ENVIRONMENT_H #define PP_ENVIRONMENT_H +#include "CPlusPlusForwardDeclarations.h" + #include <QVector> #include <QByteArray> namespace CPlusPlus { -struct Macro; +class Macro; -class Environment +class CPLUSPLUS_EXPORT Environment { public: Environment(); @@ -70,7 +72,7 @@ public: Macro *macroAt(unsigned index) const; Macro *bind(const Macro ¯o); - void remove(const QByteArray &name); + Macro *remove(const QByteArray &name); Macro *resolve(const QByteArray &name) const; bool isBuiltinMacro(const QByteArray &name) const; diff --git a/src/libs/cplusplus/pp-macro.h b/src/libs/cplusplus/pp-macro.h index b091abd6184..494b7a4de7f 100644 --- a/src/libs/cplusplus/pp-macro.h +++ b/src/libs/cplusplus/pp-macro.h @@ -53,42 +53,43 @@ #ifndef PP_MACRO_H #define PP_MACRO_H +#include <CPlusPlusForwardDeclarations.h> + #include <QByteArray> #include <QVector> namespace CPlusPlus { - struct Macro +class CPLUSPLUS_EXPORT Macro +{ +public: + QByteArray name; + QByteArray definition; + QVector<QByteArray> formals; + QByteArray fileName; + int line; + Macro *next; + unsigned hashcode; + + union { - QByteArray name; - QByteArray definition; - QVector<QByteArray> formals; - QByteArray fileName; - int line; - int lines; - Macro *next; - unsigned hashcode; + unsigned state; - union + struct { - unsigned state; - - struct - { - unsigned hidden: 1; - unsigned function_like: 1; - unsigned variadics: 1; - }; + unsigned hidden: 1; + unsigned function_like: 1; + unsigned variadics: 1; }; + }; - inline Macro(): + inline Macro(): line(0), - lines(0), next(0), hashcode(0), state(0) - { } - }; + { } +}; } // namespace CPlusPlus diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 7568d2c8877..47ac5c57678 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -699,7 +699,9 @@ void CppCodeCompletion::addMacros(const LookupContext &context) continue; processed.insert(fn); if (Document::Ptr doc = context.document(fn)) { - macroNames += doc->macroNames(); + foreach (const Macro macro, doc->definedMacros()) { + macroNames.insert(macro.name); + } todo += doc->includedFiles(); } } diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index af885de622f..e8359da2b5b 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -31,7 +31,7 @@ ** ***************************************************************************/ -#include "pp.h" +#include <cplusplus/pp.h> #include "cppmodelmanager.h" #include "cpphoverhandler.h" @@ -129,8 +129,7 @@ protected: void mergeEnvironment(CPlusPlus::Document::Ptr doc); void mergeEnvironment(CPlusPlus::Document::Ptr doc, QSet<QString> *processed); - virtual void macroAdded(const QByteArray ¯oName, - const QByteArray ¯oText); + virtual void macroAdded(const Macro ¯o); virtual void startExpandingMacro(unsigned offset, const Macro ¯o, const QByteArray &originalText); @@ -295,12 +294,12 @@ QByteArray CppPreprocessor::tryIncludeFile(QString &fileName, IncludeType type) return QByteArray(); } -void CppPreprocessor::macroAdded(const QByteArray ¯oName, const QByteArray ¯oText) +void CppPreprocessor::macroAdded(const Macro ¯o) { if (! m_currentDoc) return; - m_currentDoc->appendMacro(macroName, macroText); + m_currentDoc->appendMacro(macro); } void CppPreprocessor::startExpandingMacro(unsigned offset, @@ -340,14 +339,13 @@ void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *process processed->insert(fn); - foreach (QString includedFile, doc->includedFiles()) + foreach (QString includedFile, doc->includedFiles()) { mergeEnvironment(m_documents.value(includedFile), processed); + } - const QByteArray macros = doc->definedMacros(); - QByteArray localFileName = doc->fileName().toUtf8(); - - QByteArray dummy; - m_proc(localFileName, macros, &dummy); + foreach (const Macro macro, doc->definedMacros()) { + env.bind(macro); + } } void CppPreprocessor::startSkippingBlocks(unsigned offset) From c14896b7d29b701cd653625df09cd4be2597d638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com> Date: Fri, 5 Dec 2008 15:58:19 +0100 Subject: [PATCH 32/41] Slight optimization in Session::projectForFile Avoid creating a copy of the list of projects. --- src/plugins/cpptools/searchsymbols.cpp | 2 +- src/plugins/projectexplorer/session.cpp | 36 ++++++++++++------------- src/plugins/projectexplorer/session.h | 3 ++- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/plugins/cpptools/searchsymbols.cpp b/src/plugins/cpptools/searchsymbols.cpp index 670d0d6d471..308449ab581 100644 --- a/src/plugins/cpptools/searchsymbols.cpp +++ b/src/plugins/cpptools/searchsymbols.cpp @@ -194,7 +194,7 @@ QString SearchSymbols::symbolName(const Symbol *symbol) const void SearchSymbols::appendItem(const QString &name, const QString &info, ModelItemInfo::ItemType type, - const CPlusPlus::Symbol *symbol) + const Symbol *symbol) { const QIcon icon = icons.iconForSymbol(symbol); items.append(ModelItemInfo(name, info, type, diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 876b8294a37..71057473046 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -709,7 +709,7 @@ void SessionManager::editDependencies() dlg.exec(); } -QList<Project *> SessionManager::projects() const +const QList<Project *> &SessionManager::projects() const { return m_file->m_projects; } @@ -839,26 +839,26 @@ Project *SessionManager::projectForFile(const QString &fileName) const if (debug) qDebug() << "SessionManager::projectForFile(" << fileName << ")"; - Project *project = 0; + const QList<Project *> &projectList = projects(); - QList<Project *> projectList = projects(); + // Check current project first + Project *currentProject = ProjectExplorerPlugin::instance()->currentProject(); + if (currentProject && projectContainsFile(currentProject, fileName)) + return currentProject; - // Always check current project first - if (Project *currentProject = ProjectExplorerPlugin::instance()->currentProject()) { - projectList.removeOne(currentProject); - projectList.insert(0, currentProject); - } + foreach (Project *p, projectList) + if (p != currentProject && projectContainsFile(p, fileName)) + return p; - foreach (Project *p, projectList) { - if (!m_projectFileCache.contains(p)) { - m_projectFileCache.insert(p, p->files(Project::AllFiles)); - } - if (m_projectFileCache.value(p).contains(fileName)) { - project = p; - break; - } - } - return project; + return 0; +} + +bool SessionManager::projectContainsFile(Project *p, const QString &fileName) const +{ + if (!m_projectFileCache.contains(p)) + m_projectFileCache.insert(p, p->files(Project::AllFiles)); + + return m_projectFileCache.value(p).contains(fileName); } void SessionManager::setEditorCodec(Core::IEditor *editor, const QString &fileName) diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index fcf98a23ded..d07316f07a4 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -137,7 +137,7 @@ public: Core::IFile *file() const; Project *startupProject() const; - QList<Project *> projects() const; + const QList<Project *> &projects() const; bool isDefaultVirgin() const; bool isDefaultSession(const QString &session) const; @@ -182,6 +182,7 @@ private: bool loadImpl(const QString &fileName); bool createImpl(const QString &fileName); QString sessionNameToFileName(const QString &session); + bool projectContainsFile(Project *p, const QString &fileName) const; bool recursiveDependencyCheck(const QString &newDep, const QString &checkDep) const; QStringList dependencies(const QString &proName) const; From d0a2f567c1967a17d6c136d3092b2d1a076604fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com> Date: Fri, 5 Dec 2008 16:06:09 +0100 Subject: [PATCH 33/41] Renamed slot to avoid confusement ProjectExplorer::sessionManager -> ProjectExplorer::showSessionManager --- src/plugins/projectexplorer/projectexplorer.cpp | 6 +++--- src/plugins/projectexplorer/projectexplorer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index b95d5c19463..f67984f0da8 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -605,7 +605,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList & /*arguments*/, QStrin } } - connect(m_sessionManagerAction, SIGNAL(triggered()), this, SLOT(sessionManager())); + connect(m_sessionManagerAction, SIGNAL(triggered()), this, SLOT(showSessionManager())); connect(m_newAction, SIGNAL(triggered()), this, SLOT(newProject())); #if 0 connect(m_loadAction, SIGNAL(triggered()), this, SLOT(loadAction())); @@ -765,10 +765,10 @@ void ProjectExplorerPlugin::newProject() updateActions(); } -void ProjectExplorerPlugin::sessionManager() +void ProjectExplorerPlugin::showSessionManager() { if (debug) - qDebug() << "ProjectExplorerPlugin::newSession"; + qDebug() << "ProjectExplorerPlugin::showSessionManager"; if (m_session->isDefaultVirgin()) { // do not save new virgin default sessions diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 6a7f4beb831..97eb684bb49 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -143,7 +143,7 @@ private slots: void unloadProject(); void clearSession(); void newProject(); - void sessionManager(); + void showSessionManager(); void populateBuildConfigurationMenu(); void buildConfigurationMenuTriggered(QAction *); void populateRunConfigurationMenu(); From bf7486c0118c32fe171cca7e50fd3fb89a5dbe72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com> Date: Mon, 8 Dec 2008 13:01:54 +0100 Subject: [PATCH 34/41] Don't keep around references to old documents The code completion was keeping around references to old documents after the completion finished. This caused documents to stay in memory when unloading projects, up until the next time you used the completion. --- src/libs/cplusplus/TypeOfExpression.cpp | 1 + src/libs/cplusplus/TypeOfExpression.h | 3 +++ src/plugins/cpptools/cppcodecompletion.cpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 7dd669365fc..487c9f8a469 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -48,6 +48,7 @@ TypeOfExpression::TypeOfExpression(): void TypeOfExpression::setDocuments(const QMap<QString, Document::Ptr> &documents) { m_documents = documents; + m_lookupContext = LookupContext(); } QList<TypeOfExpression::Result> TypeOfExpression::operator()(const QString &expression, diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index ecdfac7b290..cd7a23441fd 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -54,6 +54,9 @@ public: /** * Sets the documents used to evaluate expressions. Should be set before * calling this functor. + * + * Also clears the lookup context, so can be used to make sure references + * to the documents previously used are removed. */ void setDocuments(const QMap<QString, Document::Ptr> &documents); diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 47ac5c57678..d24f5a5f81d 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -1027,6 +1027,10 @@ bool CppCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem void CppCodeCompletion::cleanup() { m_completions.clear(); + + // Set empty map in order to avoid referencing old versions of the documents + // until the next completion + typeOfExpression.setDocuments(QMap<QString, Document::Ptr>()); } int CppCodeCompletion::findStartOfName(const TextEditor::ITextEditor *editor) From 8d3a774fc2146bcad47e82e80a7c446b61e1ac69 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 14:26:11 +0100 Subject: [PATCH 35/41] new status widget for debugger output. needs a bit more polishing... --- src/plugins/debugger/debuggermanager.cpp | 31 +++++++------ src/plugins/debugger/debuggermanager.h | 14 ++++-- src/plugins/debugger/gdbengine.cpp | 58 ++++++++++++------------ src/plugins/debugger/mode.cpp | 2 + 4 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index a94b1fb0931..11e7ef6c82d 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -62,6 +62,7 @@ #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QTime> +#include <QtCore/QTimer> #include <QtGui/QAction> #include <QtGui/QComboBox> @@ -145,6 +146,7 @@ void DebuggerManager::init() m_modulesHandler = 0; m_registerHandler = 0; + m_statusLabel = new QLabel; m_breakWindow = new BreakWindow; m_disassemblerWindow = new DisassemblerWindow; m_modulesWindow = new ModulesWindow; @@ -157,6 +159,7 @@ void DebuggerManager::init() //m_tooltipWindow = new WatchWindow(WatchWindow::TooltipType); //m_watchersWindow = new QTreeView; m_tooltipWindow = new QTreeView; + m_statusTimer = new QTimer(this); m_mainWindow = new QMainWindow; m_mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); @@ -408,6 +411,8 @@ void DebuggerManager::init() this, SLOT(saveSessionData())); connect(m_dumpLogAction, SIGNAL(triggered()), this, SLOT(dumpLog())); + connect(m_statusTimer, SIGNAL(timeout()), + this, SLOT(clearStatusMessage())); connect(m_outputWindow, SIGNAL(commandExecutionRequested(QString)), this, SLOT(executeDebuggerCommand(QString))); @@ -553,24 +558,24 @@ QAbstractItemModel *DebuggerManager::threadsModel() return qobject_cast<ThreadsWindow*>(m_threadsWindow)->model(); } +void DebuggerManager::clearStatusMessage() +{ + m_statusLabel->setText(m_lastPermanentStatusMessage); +} + void DebuggerManager::showStatusMessage(const QString &msg, int timeout) { Q_UNUSED(timeout) //qDebug() << "STATUS: " << msg; showDebuggerOutput("status:", msg); - mainWindow()->statusBar()->showMessage(msg, timeout); -#if 0 - QString currentTime = QTime::currentTime().toString("hh:mm:ss.zzz"); - - ICore *core = m_pm->getObject<Core::ICore>(); - //qDebug() << qPrintable(currentTime) << "Setting status: " << msg; - if (msg.isEmpty()) - core->messageManager()->displayStatusBarMessage(msg); - else if (timeout == -1) - core->messageManager()->displayStatusBarMessage(tr("Debugger: ") + msg); - else - core->messageManager()->displayStatusBarMessage(tr("Debugger: ") + msg, timeout); -#endif + m_statusLabel->setText(" " + msg); + if (timeout > 0) { + m_statusTimer->setSingleShot(true); + m_statusTimer->start(timeout); + } else { + m_lastPermanentStatusMessage = msg; + m_statusTimer->stop(); + } } void DebuggerManager::notifyStartupFinished() diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index fd1e7cf5cba..63c225411fc 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -44,9 +44,11 @@ QT_BEGIN_NAMESPACE class QAction; class QAbstractItemModel; class QDockWidget; +class QLabel; class QMainWindow; class QModelIndex; class QSplitter; +class QTimer; class QWidget; QT_END_NAMESPACE @@ -190,7 +192,8 @@ public: private: friend class DebugMode; - virtual QWidget *threadsWindow() = 0; + virtual QWidget *threadsWindow() const = 0; + virtual QLabel *statusLabel() const = 0; virtual QList<QDockWidget*> dockWidgets() const = 0; virtual void createDockWidgets() = 0; }; @@ -213,6 +216,7 @@ public: IDebuggerManagerAccessForEngines *engineInterface(); IDebuggerManagerAccessForDebugMode *debugModeInterface(); QMainWindow *mainWindow() const { return m_mainWindow; } + QLabel *statusLabel() const { return m_statusLabel; } enum StartMode { startInternal, startExternal, attachExternal }; enum DebuggerType { GdbDebugger, ScriptDebugger, WinDebugger }; @@ -272,7 +276,7 @@ public slots: void assignValueInDebugger(const QString &expr, const QString &value); void executeDebuggerCommand(const QString &command); - void showStatusMessage(const QString &msg, int timeout); // -1 forever + void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever private slots: void showDebuggerOutput(const QString &prefix, const QString &msg); @@ -290,6 +294,7 @@ private slots: void reloadRegisters(); void registerDockToggled(bool on); void setStatus(int status); + void clearStatusMessage(); private: // @@ -322,7 +327,7 @@ private: // // Implementation of IDebuggerManagerAccessForDebugMode // - QWidget *threadsWindow() { return m_threadsWindow; } + QWidget *threadsWindow() const { return m_threadsWindow; } QList<QDockWidget*> dockWidgets() const { return m_dockWidgets; } void createDockWidgets(); @@ -382,6 +387,7 @@ private: /// Views QMainWindow *m_mainWindow; + QLabel *m_statusLabel; QDockWidget *m_breakDock; QDockWidget *m_disassemblerDock; QDockWidget *m_modulesDock; @@ -440,6 +446,8 @@ private: int m_status; bool m_busy; + QTimer *m_statusTimer; + QString m_lastPermanentStatusMessage; IDebuggerEngine *engine(); IDebuggerEngine *m_engine; diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 9336981b128..5fce8a96555 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -347,7 +347,7 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error) "This is the default return value of error()."); } - q->showStatusMessage(msg, 5000); + q->showStatusMessage(msg); QMessageBox::critical(q->mainWindow(), tr("Error"), msg); // act as if it was closed by the core q->exitDebugger(); @@ -710,7 +710,7 @@ void GdbEngine::sendCommand(const QString &command, int type, bool temporarilyStopped = false; if (needStop && q->status() == DebuggerInferiorRunning) { - q->showStatusMessage(tr("Temporarily stopped"), -1); + q->showStatusMessage(tr("Temporarily stopped")); interruptInferior(); temporarilyStopped = true; } @@ -1055,7 +1055,7 @@ void GdbEngine::handleExecJumpToLine(const GdbResultRecord &record) // ~"242\t x *= 2;" //109^done" qq->notifyInferiorStopped(); - q->showStatusMessage(tr("Jumped. Stopped."), -1); + q->showStatusMessage(tr("Jumped. Stopped.")); QString output = record.data.findChild("logstreamoutput").data(); if (!output.isEmpty()) return; @@ -1074,7 +1074,7 @@ void GdbEngine::handleExecRunToFunction(const GdbResultRecord &record) // func="foo",args=[{name="str",value="@0x7fff0f450460"}], // file="main.cpp",fullname="/tmp/g/main.cpp",line="37"} qq->notifyInferiorStopped(); - q->showStatusMessage(tr("Run to Function finished. Stopped."), -1); + q->showStatusMessage(tr("Run to Function finished. Stopped.")); GdbMi frame = record.data.findChild("frame"); QString file = frame.findChild("fullname").data(); int line = frame.findChild("line").data().toInt(); @@ -1212,7 +1212,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) } } else { // slow start requested. - q->showStatusMessage("Loading " + data.toString(), -1); + q->showStatusMessage(tr("Loading %1...").arg(QString(data.toString()))); continueInferior(); } return; @@ -1231,7 +1231,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) msg = "Program exited after receiving signal " + data.findChild("signal-name").toString(); } - q->showStatusMessage(msg, -1); + q->showStatusMessage(msg); q->exitDebugger(); return; } @@ -1271,7 +1271,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (isStoppedReason(reason) || reason.isEmpty()) { // Need another round trip if (reason == "breakpoint-hit") { - q->showStatusMessage(tr("Stopped at breakpoint."), -1); + q->showStatusMessage(tr("Stopped at breakpoint")); GdbMi frame = data.findChild("frame"); //qDebug() << frame.toString(); m_currentFrame = frame.findChild("addr").data() + '%' + @@ -1283,7 +1283,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) QVariant var = QVariant::fromValue<GdbMi>(data); sendCommand("p 0", GdbAsyncOutput2, var); // dummy } else { - q->showStatusMessage(tr("Stopped. %1").arg(reason), -1); + q->showStatusMessage(tr("Stopped. Reason: \"%1\"").arg(reason)); handleAsyncOutput2(data); } return; @@ -1305,7 +1305,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) // system="0.00136",start="1218810678.805432",end="1218810678.812011"} q->resetLocation(); qq->notifyInferiorStopped(); - q->showStatusMessage(tr("Run to Function finished. Stopped."), -1); + q->showStatusMessage(tr("Run to Function finished. Stopped.")); GdbMi frame = data.findChild("frame"); QString file = frame.findChild("fullname").data(); int line = frame.findChild("line").data().toInt(); @@ -1378,8 +1378,9 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) if (response.resultClass == GdbResultDone) { m_gdbVersion = 100; QString msg = response.data.findChild("consolestreamoutput").data(); - QRegExp supported("GNU gdb 6.[6789]"); - if (msg.indexOf(supported) == -1) { + QRegExp supported("GNU gdb(.*) (\\d+)\\.(\\d+)\\.(\\d+)"); + if (supported.indexIn(msg) == -1) { + qDebug() << "UNSUPPORTED GDB VERSION " << msg; QStringList list = msg.split("\n"); while (list.size() > 2) list.removeLast(); @@ -1396,11 +1397,11 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) #else //QMessageBox::information(m_mainWindow, tr("Warning"), msg); #endif - } - int pos = msg.indexOf("GNU gdb 6."); - if (pos != -1) { - m_gdbVersion = 600 + (msg.at(pos + 10).unicode() - '0') * 10; - //qDebug() << "GDB VERSION " << m_gdbVersion << msg; + } else { + m_gdbVersion = 10000 * supported.cap(2).toInt() + + 100 * supported.cap(3).toInt() + + 1 * supported.cap(4).toInt(); + //qDebug() << "GDB VERSION " << m_gdbVersion; } } } @@ -1423,14 +1424,14 @@ void GdbEngine::handleExecRun(const GdbResultRecord &response) { if (response.resultClass == GdbResultRunning) { qq->notifyInferiorRunning(); - q->showStatusMessage(tr("Running..."), -1); + q->showStatusMessage(tr("Running...")); //reloadModules(); } else if (response.resultClass == GdbResultError) { QString msg = response.data.findChild("msg").data(); if (msg == "Cannot find bounds of current function") { qq->notifyInferiorStopped(); //q->showStatusMessage(tr("No debug information available. " - // "Leaving function..."), -1); + // "Leaving function...")); //stepOutExec(); } else { QMessageBox::critical(q->mainWindow(), tr("Error"), @@ -1558,7 +1559,7 @@ bool GdbEngine::startDebugger() qDebug() << "ExeFile: " << q->m_executable; #endif - q->showStatusMessage("Starting Debugger", -1); + q->showStatusMessage(tr("Starting Debugger")); emit gdbInputAvailable(QString(), theGdbSettings().m_gdbCmd + ' ' + gdbArgs.join(" ")); m_gdbProc.start(theGdbSettings().m_gdbCmd, gdbArgs); @@ -1567,7 +1568,7 @@ bool GdbEngine::startDebugger() if (m_gdbProc.state() != QProcess::Running) return false; - q->showStatusMessage(tr("Gdb Running"), -1); + q->showStatusMessage(tr("Gdb Running")); sendCommand("show version", GdbShowVersion); if (qq->useFastStart()) { @@ -2337,8 +2338,8 @@ void GdbEngine::handleModulesList(const GdbResultRecord &record) void GdbEngine::handleStackSelectThread(const GdbResultRecord &record, int) { Q_UNUSED(record); - qDebug("FIXME: StackHandler::handleOutput: SelectThread"); - q->showStatusMessage(tr("Retrieving data for stack view..."), -1); + //qDebug("FIXME: StackHandler::handleOutput: SelectThread"); + q->showStatusMessage(tr("Retrieving data for stack view..."), 3000); sendCommand("-stack-list-frames", StackListFrames); } @@ -2432,7 +2433,7 @@ void GdbEngine::selectThread(int index) QList<ThreadData> threads = threadsHandler->threads(); QWB_ASSERT(index < threads.size(), return); int id = threads.at(index).id; - q->showStatusMessage(tr("Retrieving data for stack view..."), -1); + q->showStatusMessage(tr("Retrieving data for stack view..."), 10000); sendCommand(QLatin1String("-thread-select ") + QString::number(id), StackSelectThread); } @@ -2545,7 +2546,7 @@ bool GdbEngine::supportsThreads() const { // 6.3 crashes happily on -thread-list-ids. So don't use it. // The test below is a semi-random pick, 6.8 works fine - return m_gdbVersion > 650; + return m_gdbVersion > 60500; } ////////////////////////////////////////////////////////////////////// @@ -3081,7 +3082,7 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) q->showStatusMessage( tr("Retrieving data for watch view (%1 requests pending)...") - .arg(m_pendingRequests + 1), -1); + .arg(m_pendingRequests + 1), 10000); // create response slot for socket data QVariant var; var.setValue(data); @@ -3299,7 +3300,7 @@ void GdbEngine::updateWatchModel2() PENDING_DEBUG("REBUILDING MODEL") emit gdbInputAvailable(QString(), "[" + currentTime() + "] <Rebuild Watchmodel>"); - q->showStatusMessage(tr("Finished retrieving data."), -1); + q->showStatusMessage(tr("Finished retrieving data."), 400); qq->watchHandler()->rebuildModel(); if (!m_toolTipExpression.isEmpty()) { @@ -3313,9 +3314,6 @@ void GdbEngine::updateWatchModel2() "Cannot evaluate expression: " + m_toolTipExpression); } } - - //qDebug() << "INSERT DATA" << data0.toString(); - //q->showStatusMessage(tr("Stopped."), 5000); } void GdbEngine::handleQueryDataDumper1(const GdbResultRecord &record) @@ -3897,7 +3895,7 @@ void GdbEngine::handleToolTip(const GdbResultRecord &record, if (isCustomValueDumperAvailable(m_toolTip.type)) runCustomDumper(m_toolTip, false); else - q->showStatusMessage(tr("Retrieving data for tooltip..."), -1); + q->showStatusMessage(tr("Retrieving data for tooltip..."), 10000); sendCommand("-data-evaluate-expression " + m_toolTip.exp, WatchToolTip, "evaluate"); //sendToolTipCommand("-var-evaluate-expression tooltip") diff --git a/src/plugins/debugger/mode.cpp b/src/plugins/debugger/mode.cpp index 3eef7dc8329..2229cbfe6f5 100644 --- a/src/plugins/debugger/mode.cpp +++ b/src/plugins/debugger/mode.cpp @@ -169,6 +169,8 @@ QToolBar *DebugMode::createToolBar() managerAccess->threadsWindow(), SIGNAL(threadSelected(int))); debugToolBar->addWidget(threadBox); + debugToolBar->addWidget(managerAccess->statusLabel()); + QWidget *stretch = new QWidget; stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); debugToolBar->addWidget(stretch); From 02488eebe43a840b90b6ee7d950c15c8a79ec853 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@trolltech.com> Date: Mon, 8 Dec 2008 14:48:51 +0100 Subject: [PATCH 36/41] More cleanup in the CppPreprocessor. --- src/plugins/cpptools/cppmodelmanager.cpp | 24 ++++++++++++------------ src/plugins/cpptools/cppmodelmanager.h | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index e8359da2b5b..a165614a594 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -115,7 +115,6 @@ public: void setWorkingCopy(const QMap<QString, QByteArray> &workingCopy); void setIncludePaths(const QStringList &includePaths); void setFrameworkPaths(const QStringList &frameworkPaths); - void addIncludePath(const QString &path); void setProjectFiles(const QStringList &files); void run(QString &fileName); void operator()(QString &fileName); @@ -170,9 +169,6 @@ void CppPreprocessor::setIncludePaths(const QStringList &includePaths) void CppPreprocessor::setFrameworkPaths(const QStringList &frameworkPaths) { m_frameworkPaths = frameworkPaths; } -void CppPreprocessor::addIncludePath(const QString &path) -{ m_includePaths.append(path); } - void CppPreprocessor::setProjectFiles(const QStringList &files) { m_projectFiles = files; } @@ -488,14 +484,14 @@ void CppModelManager::ensureUpdated() if (! m_dirty) return; - m_projectFiles = updateProjectFiles(); - m_includePaths = updateIncludePaths(); - m_frameworkPaths = updateFrameworkPaths(); - m_definedMacros = updateDefinedMacros(); + m_projectFiles = internalProjectFiles(); + m_includePaths = internalIncludePaths(); + m_frameworkPaths = internalFrameworkPaths(); + m_definedMacros = internalDefinedMacros(); m_dirty = false; } -QStringList CppModelManager::updateProjectFiles() const +QStringList CppModelManager::internalProjectFiles() const { QStringList files; QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); @@ -504,10 +500,11 @@ QStringList CppModelManager::updateProjectFiles() const ProjectInfo pinfo = it.value(); files += pinfo.sourceFiles; } + files.removeDuplicates(); return files; } -QStringList CppModelManager::updateIncludePaths() const +QStringList CppModelManager::internalIncludePaths() const { QStringList includePaths; QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); @@ -516,10 +513,11 @@ QStringList CppModelManager::updateIncludePaths() const ProjectInfo pinfo = it.value(); includePaths += pinfo.includePaths; } + includePaths.removeDuplicates(); return includePaths; } -QStringList CppModelManager::updateFrameworkPaths() const +QStringList CppModelManager::internalFrameworkPaths() const { QStringList frameworkPaths; QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); @@ -528,10 +526,11 @@ QStringList CppModelManager::updateFrameworkPaths() const ProjectInfo pinfo = it.value(); frameworkPaths += pinfo.frameworkPaths; } + frameworkPaths.removeDuplicates(); return frameworkPaths; } -QByteArray CppModelManager::updateDefinedMacros() const +QByteArray CppModelManager::internalDefinedMacros() const { QByteArray macros; QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects); @@ -588,6 +587,7 @@ void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) return; m_projects.insert(pinfo.project, pinfo); + m_dirty = true; } QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles) diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 6bc7d0c1c55..3b2f4e19993 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -133,10 +133,10 @@ private: } void ensureUpdated(); - QStringList updateProjectFiles() const; - QStringList updateIncludePaths() const; - QStringList updateFrameworkPaths() const; - QByteArray updateDefinedMacros() const; + QStringList internalProjectFiles() const; + QStringList internalIncludePaths() const; + QStringList internalFrameworkPaths() const; + QByteArray internalDefinedMacros() const; static void parse(QFutureInterface<void> &future, CppPreprocessor *preproc, From 764f9b3ac9ecde434ef37a9704b054a0249d2391 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 15:14:36 +0100 Subject: [PATCH 37/41] Fixes: Documentation fixes RevBy: hjk --- doc/qtcreator.qdoc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4dd7a5fb53c..0db515fe434 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -69,7 +69,7 @@ \image qtcreator-breakdown.png - \seection1 The Mode Selectors + \section1 The Mode Selectors When working in Qt Creator, you can be in one of five modes: \bold Project, \bold Edit, \bold Debug, \bold Help, and \bold Output. @@ -613,7 +613,7 @@ \page creator-debugging.html \nextpage creator-tips.html - \title Debugging With Qt Creator + \title Debugging with Qt Creator \table \row @@ -677,9 +677,9 @@ \list \o At a particular line you want the program to stop -- click on the - left margin or press \key F9 (\key F8 for Mac Os X). - \o At the name of a function that you want the program to stop -- enter - the function's name in \gui{Set Breakpoint at Function...} under the + left margin or press \key F9 (\key F8 for Mac OS X). + \o At a function that you want the program to stop -- enter the + function's name in \gui{Set Breakpoint at Function...} under the \gui Debug menu. \endlist @@ -744,7 +744,7 @@ When the program being debugged is stopped, Qt Creator displays the nested function calls leading to the current position as a \e call stack trace. - This stack trace is built up from \e call stack frames, each representing a + This stack trace is built up from \e{call stack frames}, each representing a particular function. For each function, Qt Creator will try to retrieve the file name and line number of the corresponding source files. This data is shown in the \gui Stack view. @@ -765,11 +765,10 @@ \section2 Threads - The \gui Thread view displays the state of the program being debugged one - thread at a time. If a multi-threaded program is stopped, the \gui Thread - view or the combobox named \gui Thread in the debugger's status bar can - be used to switch from one thread to another. The \gui Stack view will - adjust itself accordingly. + If a multi-threaded program is stopped, the \gui Thread view or the + combobox named \gui Thread in the debugger's status bar can be used to + switch from one thread to another. The \gui Stack view will adjust itself + accordingly. \section2 Locals and Watchers @@ -851,8 +850,8 @@ function, the latter the current state of the CPU registers. Both views are mainly useful in connection with the low-level \gui{Step single instruction} and \gui{Step over single instruction} - commands - + commands. + \section1 A Walkthrough for the Debugger Frontend @@ -947,8 +946,9 @@ \bold{Running Qt Creator from the Command Line} - You can start Qt Creator from a command prompt with an existing session or - \c{.pro} file by giving the name as argument on the command line. + You can start Qt Creator from a command prompt with the name of an existing + session or \c{.pro} file by giving the name as argument on the command + line. \bold{Show and Hide the Sidebar} From b220999bdd55c1fb8a7888b9d319353df6451653 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 17:06:45 +0100 Subject: [PATCH 38/41] Fixes: release build with compiling with CONFIG+=debug_and_release --- src/qworkbench.pri | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/qworkbench.pri b/src/qworkbench.pri index e869ce452a8..1f842960842 100644 --- a/src/qworkbench.pri +++ b/src/qworkbench.pri @@ -1,16 +1,14 @@ IDE_SOURCE_TREE = $$PWD/../ -isEmpty(TEST) { - CONFIG(debug, debug|release) { +isEmpty(TEST):CONFIG(debug, debug|release) { + !debug_and_release|build_pass { TEST = 1 } } -!isEmpty(TEST) { - equals(TEST, 1) { - QT +=testlib - DEFINES+=WITH_TESTS - } +equals(TEST, 1) { + QT +=testlib + DEFINES += WITH_TESTS } isEmpty(IDE_BUILD_TREE) { From be9dfc8c913525e5b636d1693e8a14a45d021f17 Mon Sep 17 00:00:00 2001 From: con <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 17:47:54 +0100 Subject: [PATCH 39/41] Fixes: - Show <No Symbols> or <Select Symbol> in 'empty' method combo box Task: - 234321 RevBy: - Bjoern --- src/libs/cplusplus/OverviewModel.cpp | 46 ++++++++++++++++++++++------ src/plugins/cppeditor/cppeditor.cpp | 23 +++----------- src/plugins/cppeditor/cppeditor.h | 1 - 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp index 38456d8fa7d..20658778905 100644 --- a/src/libs/cplusplus/OverviewModel.cpp +++ b/src/libs/cplusplus/OverviewModel.cpp @@ -74,10 +74,10 @@ Symbol *OverviewModel::globalSymbolAt(unsigned index) const QModelIndex OverviewModel::index(int row, int column, const QModelIndex &parent) const { - if (! hasDocument()) { - return QModelIndex(); - } else if (! parent.isValid()) { - Symbol *symbol = globalSymbolAt(row); + if (!parent.isValid()) { + if (row == 0) // account for no symbol item + return createIndex(row, column); + Symbol *symbol = globalSymbolAt(row-1); // account for no symbol item return createIndex(row, column, symbol); } else { Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer()); @@ -96,12 +96,20 @@ QModelIndex OverviewModel::index(int row, int column, const QModelIndex &parent) QModelIndex OverviewModel::parent(const QModelIndex &child) const { Symbol *symbol = static_cast<Symbol *>(child.internalPointer()); - Q_ASSERT(symbol != 0); + if (!symbol) // account for no symbol item + return QModelIndex(); if (Scope *scope = symbol->scope()) { Symbol *parentSymbol = scope->owner(); - if (parentSymbol && parentSymbol->scope()) - return createIndex(parentSymbol->index(), 0, parentSymbol); + if (parentSymbol && parentSymbol->scope()) { + QModelIndex index; + if (parentSymbol->scope() && parentSymbol->scope()->owner() + && parentSymbol->scope()->owner()->scope()) // the parent doesn't have a parent + index = createIndex(parentSymbol->index(), 0, parentSymbol); + else //+1 to account for no symbol item + index = createIndex(parentSymbol->index() + 1, 0, parentSymbol); + return index; + } } return QModelIndex(); @@ -110,22 +118,27 @@ QModelIndex OverviewModel::parent(const QModelIndex &child) const int OverviewModel::rowCount(const QModelIndex &parent) const { if (hasDocument()) { - if (! parent.isValid()) { - return globalSymbolCount(); + if (!parent.isValid()) { + return globalSymbolCount()+1; // account for no symbol item } else { + if (!parent.parent().isValid() && parent.row() == 0) // account for no symbol item + return 0; Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer()); Q_ASSERT(parentSymbol != 0); if (ScopedSymbol *scopedSymbol = parentSymbol->asScopedSymbol()) { - if (! scopedSymbol->isFunction()) { + if (!scopedSymbol->isFunction()) { Scope *parentScope = scopedSymbol->members(); Q_ASSERT(parentScope != 0); return parentScope->symbolCount(); } } + return 0; } } + if (!parent.isValid()) + return 1; // account for no symbol item return 0; } @@ -136,6 +149,19 @@ int OverviewModel::columnCount(const QModelIndex &) const QVariant OverviewModel::data(const QModelIndex &index, int role) const { + // account for no symbol item + if (!index.parent().isValid() && index.row() == 0) { + switch (role) { + case Qt::DisplayRole: + if (rowCount() > 1) + return tr("<Select Symbol>"); + else + return tr("<No Symbols>"); + default: + return QVariant(); + } //switch + } + switch (role) { case Qt::DisplayRole: { Symbol *symbol = static_cast<Symbol *>(index.internalPointer()); diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 8567f81d751..ff68bd0bac2 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -203,9 +203,7 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable) m_methodCombo->setMaxVisibleItems(20); m_overviewModel = new OverviewModel(this); - m_noSymbolsModel = new QStringListModel(this); - m_noSymbolsModel->setStringList(QStringList() << tr("<no symbols>")); - m_methodCombo->setModel(m_noSymbolsModel); + m_methodCombo->setModel(m_overviewModel); connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int))); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex())); @@ -318,16 +316,9 @@ void CPPEditor::onDocumentUpdated(Document::Ptr doc) return; m_overviewModel->rebuild(doc); - if (m_overviewModel->rowCount() > 0) { - if (m_methodCombo->model() != m_overviewModel) - m_methodCombo->setModel(m_overviewModel); - OverviewTreeView *treeView = static_cast<OverviewTreeView *>(m_methodCombo->view()); - treeView->sync(); - updateMethodBoxIndex(); - } else { - if (m_methodCombo->model() != m_noSymbolsModel) - m_methodCombo->setModel(m_noSymbolsModel); - } + OverviewTreeView *treeView = static_cast<OverviewTreeView *>(m_methodCombo->view()); + treeView->sync(); + updateMethodBoxIndex(); } void CPPEditor::updateFileName() @@ -335,8 +326,6 @@ void CPPEditor::updateFileName() void CPPEditor::jumpToMethod(int) { - if (m_methodCombo->model() != m_overviewModel) - return; QModelIndex index = m_methodCombo->view()->currentIndex(); Symbol *symbol = m_overviewModel->symbolFromIndex(index); if (! symbol) @@ -351,8 +340,6 @@ void CPPEditor::jumpToMethod(int) void CPPEditor::updateMethodBoxIndex() { - if (m_methodCombo->model() != m_overviewModel) - return; int line = 0, column = 0; convertPosition(position(), &line, &column); @@ -362,7 +349,7 @@ void CPPEditor::updateMethodBoxIndex() for (int row = 0; row < rc; ++row) { const QModelIndex index = m_overviewModel->index(row, 0, QModelIndex()); Symbol *symbol = m_overviewModel->symbolFromIndex(index); - if (symbol->line() > unsigned(line)) + if (symbol && symbol->line() > unsigned(line)) break; lastIndex = index; } diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 33745eddef2..05f2c5d9c74 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -139,7 +139,6 @@ private: QList<int> m_contexts; QComboBox *m_methodCombo; CPlusPlus::OverviewModel *m_overviewModel; - QStringListModel *m_noSymbolsModel; }; } // namespace Internal From e07976f6559109cd4b87f95068597aa3e54c1367 Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 18:26:09 +0100 Subject: [PATCH 40/41] ignore async output starting with '=' --- doc/qtcreator.qch | Bin 1649664 -> 1657856 bytes src/plugins/debugger/gdbengine.cpp | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/qtcreator.qch b/doc/qtcreator.qch index 00473f3458d78cb11acb2bb75d02aee69b0869d7..c728e43245e3171093ce06f07e4e393d6fb157d4 100644 GIT binary patch delta 41730 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 @;2;`N@wAAsO>`AGMB6+{@uHo&7({-3hD9K{X*8 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 Z+@&qqf(YA<q6^tx0SyM2`#@?m836C|7bO4y delta 40041 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%0D1Ay| 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 diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 5fce8a96555..aea9635048f 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -442,7 +442,8 @@ void GdbEngine::handleResponse() break; } - if (token == -1 && *from != '&' && *from != '~' && *from != '*') { + if (token == -1 && *from != '&' && *from != '~' && *from != '*' + && *from != '=') { // FIXME: On Linux the application's std::out is merged in here. // High risk of falsely interpreting this as MI output. // We assume that we _always_ use tokens, so not finding a token @@ -470,7 +471,7 @@ void GdbEngine::handleResponse() for (; from != to; ++from) { const char c = *from; if (!isNameChar(c)) - break; + break; asyncClass += *from; } //qDebug() << "ASYNCCLASS" << asyncClass; @@ -1283,7 +1284,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) QVariant var = QVariant::fromValue<GdbMi>(data); sendCommand("p 0", GdbAsyncOutput2, var); // dummy } else { - q->showStatusMessage(tr("Stopped. Reason: \"%1\"").arg(reason)); + q->showStatusMessage(tr("Stopped: \"%1\"").arg(reason)); handleAsyncOutput2(data); } return; From 6761ca0c1038be4982e2d80952a4f444ca7209c6 Mon Sep 17 00:00:00 2001 From: con <qtc-committer@nokia.com> Date: Mon, 8 Dec 2008 18:38:25 +0100 Subject: [PATCH 41/41] Fixes: - Custom Dumpers on Mac RevBy: - hjk --- src/plugins/debugger/gdbengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index aea9635048f..f1042c4faf5 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -3971,7 +3971,7 @@ void GdbEngine::tryLoadCustomDumpers() if (qq->useFastStart()) sendCommand("set stop-on-solib-events 0"); QString flag = QString::number(RTLD_NOW); - sendCommand("call dlopen(\"" + lib + "\", " + flag + ")"); + sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")"); sendCommand("sharedlibrary " + dotEscape(lib)); if (qq->useFastStart()) sendCommand("set stop-on-solib-events 1");