diff --git a/.gitignore b/.gitignore index 8f3ba0e8541d81eea92fe1700e6919b5e5f2cef0..2c79a07b7596f5d67200cd00235864337c217321 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ examples/tools/plugandpaint/plugins include/* include/*/* lib/* +lib64/* plugins/*/* release tmp diff --git a/doc/example/textfinder/textfinder.cpp b/doc/example/textfinder/textfinder.cpp index b399d17d23feee8f8c6ec3fa38ec1d54bc306ef3..c302f91911f79958f78241fd3b1d3d8f4cfee77e 100644 --- a/doc/example/textfinder/textfinder.cpp +++ b/doc/example/textfinder/textfinder.cpp @@ -33,18 +33,21 @@ #include <QtCore/QTextStream> #include <QtGui/QMessageBox> -TextFinder::TextFinder(QWidget *parent, Qt::WFlags flags) - : QWidget(parent, flags) +//! [2] +TextFinder::TextFinder(QWidget *parent) + : QWidget(parent), ui(new Ui::TextFinder) { - ui.setupUi(this); + ui->setupUi(this); loadTextFile(); - isFirstTime = true; } +//! [2] TextFinder::~TextFinder() { + delete ui; } +//! [0] void TextFinder::loadTextFile() { QFile inputFile(":/input.txt"); @@ -54,20 +57,16 @@ void TextFinder::loadTextFile() QString line = in.readAll(); inputFile.close(); - ui.textEdit->setPlainText(line); - QTextCursor cursor = ui.textEdit->textCursor(); + ui->textEdit->setPlainText(line); + QTextCursor cursor = ui->textEdit->textCursor(); cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1); } +//! [0] +//! [1] void TextFinder::on_findButton_clicked() { - QString searchString = ui.lineEdit->text(); - QTextDocument *document = ui.textEdit->document(); - - bool found = false; - - ui.textEdit->find(searchString, QTextDocument::FindWholeWords); - QTextCursor cursor = ui.textEdit->textCursor(); - if (!cursor.isNull()) - found = true; + QString searchString = ui->lineEdit->text(); + ui->textEdit->find(searchString, QTextDocument::FindWholeWords); } +//! [1] diff --git a/doc/example/textfinder/textfinder.h b/doc/example/textfinder/textfinder.h index 19e34224da41d4d48cc64c84a99f725aec65464f..89dad6913664d898a3d5ccd25f54a1d4a65c2d67 100644 --- a/doc/example/textfinder/textfinder.h +++ b/doc/example/textfinder/textfinder.h @@ -34,29 +34,25 @@ #include <QtGui/QWidget> -class QPushButton; -class QTextEdit; -class QLineEdit; +namespace Ui +{ + class TextFinder; +} class TextFinder : public QWidget { Q_OBJECT public: - TextFinder(QWidget *parent = 0, Qt::WFlags flags = 0); + TextFinder(QWidget *parent = 0); ~TextFinder(); private slots: void on_findButton_clicked(); private: - Ui::Form ui; + Ui::TextFinder *ui; void loadTextFile(); - - QPushButton *ui_findButton; - QTextEdit *ui_textEdit; - QLineEdit *ui_lineEdit; - bool isFirstTime; }; #endif // TEXTFINDER_H diff --git a/doc/example/textfinder/textfinder.ui b/doc/example/textfinder/textfinder.ui index 1cb72c57471781a8a7dd6be933d07b31e8acbf84..ba8018742a555bafc6c9ec4f791732f198223838 100644 --- a/doc/example/textfinder/textfinder.ui +++ b/doc/example/textfinder/textfinder.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>Form</class> - <widget class="QWidget" name="Form"> + <class>TextFinder</class> + <widget class="QWidget" name="TextFinder"> <property name="geometry"> <rect> <x>0</x> diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index ce316616f41bb13bb369ebb05b176a38f179fd0a..37bd1846108182aa4ec6a3ebd7695963495f2d8b 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -531,9 +531,11 @@ \image qtcreator-textfinder-ui.png Design the form above using a \l{http://doc.trolltech.com/qlabel.html} - {QLabel}, \l{http://doc.trolltech.com/qlinedit.html}{QLineEdit}, - \l{http://doc.trolltech.com/qpushbutton.html}{QPushButton} and a - \l{http://doc.trolltech.com/qtextedit.html}{QTextEdit}. We recommend that + {QLabel}, \l{http://doc.trolltech.com/qlinedit.html}{QLineEdit} + (named lineEdit), \l{http://doc.trolltech.com/qpushbutton.html}{QPushButton} + (named findButton), and a + \l{http://doc.trolltech.com/qtextedit.html}{QTextEdit} (named textEdit). + We recommend that you use a QGridLayout to lay out the \l{http://doc.trolltech.com/qlabel.html}{QLabel}, \l{http://doc.trolltech.com/qlinedit.html}{QLineEdit} and @@ -559,11 +561,11 @@ void on_findButton_clicked(); private: - Ui::Form ui; + Ui::TextFinder *ui; void loadTextFile(); \endcode - \note The \c{Ui::Form} object is already provided. + \note The \c{Ui::TextFinder} object is already provided. \section2 The Source File @@ -571,57 +573,36 @@ \c{textfinder.cpp}. We begin by filling in the functionality to load a text file. The code snippet below describes this: - \code - void TextFinder::loadTextFile() - { - QFile inputFile(":/input.txt"); - inputFile.open(QIODevice::ReadOnly); - - QTextStream in(&inputFile); - QString line = in.readAll(); - inputFile.close(); - - ui.textEdit->setPlainText(line); - QTextCursor cursor = ui.textEdit->textCursor(); - } - \endcode + \snippet example/textfinder/textfinder.cpp 0 Basically, we load a text file using \l{http://doc.trolltech.com/qfile.html}{QFile}, read it with \l{http://doc.trolltech.com/qtextstream.html}{QTextStream}, and then display it on \c{textEdit} with - \l{http://doc.trolltech.com/qtextedit.html#plainText-prop}{setPlainText()}. + \l{http://doc.trolltech.com/qtextedit.html#plainText-prop}{setPlainText()} + which requires adding the following additional #includes to textfinder.cpp: + \code + #include <QtCore/QFile> + #include <QtCore/QTextStream> + \endcode For the \c{on_findButton_clicked()} slot, we extract the search string and use the \l{http://doc.trolltech.com/qtextedit.html#find}{find()} function to look for the search string within the text file. The code snippet below further describes it: - \code - void TextFinder::on_findButton_clicked() - { - QString searchString = ui.lineEdit->text(); - ui.textEdit->find(searchString, QTextDocument::FindWholeWords); - } - \endcode + \snippet example/textfinder/textfinder.cpp 1 Once we have both these functions complete, we call \c{loadTextFile()} in our constructor. - \code - TextFinder::TextFinder(QWidget *parent, Qt::WFlags flags) - : QWidget(parent, flags) - { - ui.setupUi(this); - loadTextFile(); - } - \endcode + \snippet example/textfinder/textfinder.cpp 2 The \c{on_findButton_clicked()} slot will be called automatically due to this line of code: \code - QMetaObject::connectSlotsByName(Form); + QMetaObject::connectSlotsByName(TextFinder); \endcode in the uic generated \c{ui_textfinder.h} file. @@ -1197,13 +1178,13 @@ \code void TextFinder::on_findButton_clicked() { - QString searchString = ui.lineEdit->text(); + QString searchString = ui->lineEdit->text(); - QTextDocument *document = ui.textEdit->document(); - QTextCursor cursor = ui.textEdit->textCursor(); + QTextDocument *document = ui->textEdit->document(); + QTextCursor cursor = ui->textEdit->textCursor(); cursor = document->find(searchString, cursor, QTextDocument::FindWholeWords); - ui.textEdit->setTextCursor(cursor); + ui->textEdit->setTextCursor(cursor); bool found = cursor.isNull(); @@ -1216,7 +1197,7 @@ if (ret == QMessageBox::Yes) { cursor = document->find(searchString, QTextDocument::FindWholeWords); - ui.textEdit->setTextCursor(cursor); + ui->textEdit->setTextCursor(cursor); } else return; } diff --git a/doc/qtcreator.qdocconf b/doc/qtcreator.qdocconf index 8baed7725cfaa5b6d14a1049d6fd14c940b1dcd0..ea504250cc38bc4484f0e3ba25d3b0d69d89786e 100644 --- a/doc/qtcreator.qdocconf +++ b/doc/qtcreator.qdocconf @@ -8,6 +8,7 @@ sourcedirs = sourcedirs = $SRCDIR imagedirs = $SRCDIR outputdir = $OUTDIR +exampledirs = $SRCDIR extraimages.HTML = qt-logo \ trolltech-logo diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 08c54b19a9d79b667fee0ef694c30b330808c5de..dec887712849d7df2d6c552360db097b23621ea7 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -176,7 +176,7 @@ QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visible scopes.clear(); foreach (Symbol *candidate, candidates) { if (ScopedSymbol *scoped = candidate->asScopedSymbol()) { - scopes.append(scoped->members()); + expand(scoped->members(), visibleScopes, &scopes); } } } @@ -223,9 +223,14 @@ QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visible continue; if (q->nameCount() > 1) { - Name *classOrNamespaceName = - control()->qualifiedNameId(q->names(), - q->nameCount() - 1); + Name *classOrNamespaceName = 0; + + if (q->nameCount() == 1) + classOrNamespaceName = q->nameAt(0); + else + classOrNamespaceName = control()->qualifiedNameId(q->names(), + q->nameCount() - 1); + const QList<Symbol *> resolvedClassOrNamespace = resolveClassOrNamespace(classOrNamespaceName, visibleScopes); diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 626c888d9ebf7762625a5b5b6483065385e9b315..cc1cd5fff95b56600c91dc8f141ce3f3d81b677c 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1388,6 +1388,10 @@ bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS") return true; + else if (size == 8 && macroId.at(0) == 'Q' && macroId == "Q_SIGNAL") + return true; + else if (size == 6 && macroId.at(0) == 'Q' && macroId == "Q_SLOT") + return true; else if (size == 6 && macroId.at(0) == 'S' && macroId == "SIGNAL") return true; else if (size == 4 && macroId.at(0) == 'S' && macroId == "SLOT") diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index 370b256c166dda98b3d031e92f74b4c4655aa736..53c69c91af7206d52c76179b50664a18ef4e4d08 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -41,8 +41,10 @@ #ifdef Q_OS_WIN #include <windows.h> +QT_BEGIN_NAMESPACE class QWinEventNotifier; class QTemporaryFile; +QT_END_NAMESPACE #endif namespace Core { diff --git a/src/libs/utils/submiteditorwidget.cpp b/src/libs/utils/submiteditorwidget.cpp index 0a283c62a09601499db777837d372d8694c626a9..984bf9ea222618e48d1d414f2ca9fb4a261e28e0 100644 --- a/src/libs/utils/submiteditorwidget.cpp +++ b/src/libs/utils/submiteditorwidget.cpp @@ -156,9 +156,6 @@ SubmitEditorWidget::SubmitEditorWidget(QWidget *parent) : connect(m_d->m_ui.fileView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(diffActivated(QModelIndex))); - // Text - m_d->m_ui.description->setFont(QFont(QLatin1String("Courier"))); - setFocusPolicy(Qt::StrongFocus); setFocusProxy(m_d->m_ui.description); } diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 9990547838a4a1b283096830b03f36e685e79d92..fea6fd3ed8d305b8eea34b69bc4524d9a1976f7f 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -47,6 +47,7 @@ #include <cplusplus/Overview.h> #include <cplusplus/OverviewModel.h> #include <cplusplus/SimpleLexer.h> +#include <cplusplus/TokenUnderCursor.h> #include <cplusplus/TypeOfExpression.h> #include <cpptools/cppmodelmanagerinterface.h> @@ -182,13 +183,13 @@ CPPEditorEditable::CPPEditorEditable(CPPEditor *editor) CPPEditor::CPPEditor(QWidget *parent) : TextEditor::BaseTextEditor(parent) + , m_showingLink(false) { setParenthesesMatchingEnabled(true); setMarksVisible(true); setCodeFoldingSupported(true); setCodeFoldingVisible(true); baseTextDocument()->setSyntaxHighlighter(new CppHighlighter); -// new QShortcut(QKeySequence("Ctrl+Alt+M"), this, SLOT(foo()), 0, Qt::WidgetShortcut); #ifdef WITH_TOKEN_MOVE_POSITION new QShortcut(QKeySequence::MoveToPreviousWord, this, SLOT(moveToPreviousToken()), @@ -235,7 +236,7 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable) policy.setHorizontalPolicy(QSizePolicy::Expanding); m_methodCombo->setSizePolicy(policy); - QTreeView *methodView = new OverviewTreeView(); + QTreeView *methodView = new OverviewTreeView; methodView->header()->hide(); methodView->setItemsExpandable(false); m_methodCombo->setView(methodView); @@ -586,7 +587,8 @@ void CPPEditor::switchDeclarationDefinition() } } -CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor) +CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor, + bool lookupDefinition) { Link link; @@ -627,13 +629,15 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor) tc.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); const int nameStart = tc.position(); const int nameLength = tc.anchor() - tc.position(); + tc.setPosition(endOfName); - // Drop out if we're at a number - if (characterAt(nameStart).isNumber()) + // Drop out if we're at a number, string or comment + static TokenUnderCursor tokenUnderCursor; + const SimpleToken tk = tokenUnderCursor(tc); + if (tk.isLiteral() || tk.isComment()) return link; // Evaluate the type of the expression under the cursor - tc.setPosition(endOfName); ExpressionUnderCursor expressionUnderCursor; const QString expression = expressionUnderCursor(tc); TypeOfExpression typeOfExpression; @@ -642,10 +646,22 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor) typeOfExpression(expression, doc, lastSymbol); if (!resolvedSymbols.isEmpty()) { - Symbol *symbol = resolvedSymbols.first().second; - if (symbol) { + TypeOfExpression::Result result = resolvedSymbols.first(); + + if (result.first->isForwardClassDeclarationType()) { + while (! resolvedSymbols.isEmpty()) { + TypeOfExpression::Result r = resolvedSymbols.takeFirst(); + + if (! r.first->isForwardClassDeclarationType()) { + result = r; + break; + } + } + } + + if (Symbol *symbol = result.second) { Symbol *def = 0; - if (!lastSymbol->isFunction()) + if (lookupDefinition && !lastSymbol->isFunction()) def = findDefinition(symbol); link = linkToSymbol(def ? def : symbol); @@ -804,8 +820,7 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e) void CPPEditor::mouseMoveEvent(QMouseEvent *e) { - bool hasDestination = false; - Qt::CursorShape cursorShape; + bool linkFound = false; if (e->modifiers() & Qt::ControlModifier) { // Link emulation behaviour for 'go to definition' @@ -819,33 +834,18 @@ void CPPEditor::mouseMoveEvent(QMouseEvent *e) onText = cursorRect(nextPos).right() >= e->x(); } - const Link link = findLinkAt(cursor); + const Link link = findLinkAt(cursor, false); if (onText && !link.fileName.isEmpty()) { - QTextEdit::ExtraSelection sel; - sel.cursor = cursor; - if (link.pos >= 0) { - sel.cursor.setPosition(link.pos); - sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor); - } else { - sel.cursor.select(QTextCursor::WordUnderCursor); - } - sel.format.setFontUnderline(true); - sel.format.setForeground(Qt::blue); - setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel); - hasDestination = true; - cursorShape = Qt::PointingHandCursor; + showLink(link); + linkFound = true; } } - if (!hasDestination) { - setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); - cursorShape = Qt::IBeamCursor; - } + if (!linkFound) + clearLink(); TextEditor::BaseTextEditor::mouseMoveEvent(e); - - viewport()->setCursor(cursorShape); } void CPPEditor::mouseReleaseEvent(QMouseEvent *e) @@ -855,8 +855,7 @@ void CPPEditor::mouseReleaseEvent(QMouseEvent *e) const QTextCursor cursor = cursorForPosition(e->pos()); if (openCppEditorAt(findLinkAt(cursor))) { - setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); - viewport()->setCursor(Qt::IBeamCursor); + clearLink(); e->accept(); return; } @@ -865,13 +864,42 @@ void CPPEditor::mouseReleaseEvent(QMouseEvent *e) TextEditor::BaseTextEditor::mouseReleaseEvent(e); } +void CPPEditor::leaveEvent(QEvent *e) +{ + clearLink(); + TextEditor::BaseTextEditor::leaveEvent(e); +} + void CPPEditor::keyReleaseEvent(QKeyEvent *e) { // Clear link emulation when Ctrl is released - if (e->key() == Qt::Key_Control) { - setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); - viewport()->setCursor(Qt::IBeamCursor); - } + if (e->key() == Qt::Key_Control) + clearLink(); + + TextEditor::BaseTextEditor::keyReleaseEvent(e); +} + +void CPPEditor::showLink(const Link &link) +{ + QTextEdit::ExtraSelection sel; + sel.cursor = textCursor(); + sel.cursor.setPosition(link.pos); + sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor); + sel.format = m_linkFormat; + sel.format.setFontUnderline(true); + setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel); + viewport()->setCursor(Qt::PointingHandCursor); + m_showingLink = true; +} + +void CPPEditor::clearLink() +{ + if (!m_showingLink) + return; + + setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>()); + viewport()->setCursor(Qt::IBeamCursor); + m_showingLink = false; } QList<int> CPPEditorEditable::context() const @@ -916,6 +944,8 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs) const QVector<QTextCharFormat> formats = fs.toTextCharFormats(categories); highlighter->setFormats(formats.constBegin(), formats.constEnd()); highlighter->rehighlight(); + + m_linkFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_LINK)); } diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 35a46cb0c7249fbc8918e724fcb34f5979304d7c..bd30f3031f9dd72a1fd172e7ff0202d44e43894a 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -99,6 +99,7 @@ protected: void contextMenuEvent(QContextMenuEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); + void leaveEvent(QEvent *); void keyReleaseEvent(QKeyEvent *); TextEditor::BaseTextEditorEditable *createEditableInterface(); @@ -148,9 +149,14 @@ private: int column; // Target column }; - Link findLinkAt(const QTextCursor &); + void showLink(const Link &); + void clearLink(); + bool m_showingLink; + + Link findLinkAt(const QTextCursor &, bool lookupDefinition = true); static Link linkToSymbol(CPlusPlus::Symbol *symbol); bool openCppEditorAt(const Link &); + QTextCharFormat m_linkFormat; CppTools::CppModelManagerInterface *m_modelManager; diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 92fe3c7cb1595b3f93decd8386021f70b74dbb0f..308d565a3e9d89c421e2f4fde8cbfd9879f40055 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -101,6 +101,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(act1); menu.addAction(act2); menu.addAction(act4); + menu.addSeparator(); menu.addAction(theDebuggerAction(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/cdb/cdb.pri b/src/plugins/debugger/cdb/cdb.pri index 527cd0be298b8ba69a5f06abd83437218a5934f4..27186577c3041746f0c48c5952df1c72d3daba6b 100644 --- a/src/plugins/debugger/cdb/cdb.pri +++ b/src/plugins/debugger/cdb/cdb.pri @@ -1,5 +1,8 @@ +# Detect presence of "Debugging Tools For Windows" +# in case VS compilers are used. + win32 { -# ---- Detect Debugging Tools For Windows +contains(QMAKE_CXX, cl) { CDB_PATH="$$(ProgramFiles)/Debugging Tools For Windows/sdk" @@ -26,6 +29,7 @@ SOURCES += \ $$PWD/cdbdebugeventcallback.cpp \ $$PWD/cdbdebugoutput.cpp } else { - error("Debugging Tools for Windows could not be found in $$CDB_PATH") + message("Debugging Tools for Windows could not be found in $$CDB_PATH") +} } } diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index efaa12d2b98a8e6b6c8d0a32966d6bced247bf11..af9da55976e7e768c3bcbc0b37e94f4ecce12f66 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -360,6 +360,16 @@ bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString * return true; } +void CdbDebugEngine::processTerminated(unsigned long exitCode) +{ + if (debugCDB) + qDebug() << Q_FUNC_INFO << exitCode; + + m_d->setDebuggeeHandles(0, 0); + m_d->m_debuggerManagerAccess->notifyInferiorExited(); + m_d->m_debuggerManager->exitDebugger(); +} + void CdbDebugEngine::exitDebugger() { if (debugCDB) @@ -380,7 +390,9 @@ void CdbDebugEngine::exitDebugger() break; case StartExternal: case StartInternal: + // Terminate and waitr for stop events. hr = m_d->m_pDebugClient->TerminateCurrentProcess(); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); if (debugCDB) qDebug() << Q_FUNC_INFO << "terminated" << msgDebugEngineComResult(hr); @@ -469,7 +481,7 @@ bool CdbDebugEnginePrivate::updateLocals(int frameIndex, value = QLatin1String("<unknown>"); } WatchData wd; - wd.iname = QLatin1String("local"); + wd.iname = QLatin1String("local.") + name; wd.name = name; wd.value = value; wd.type = type; @@ -592,6 +604,7 @@ void CdbDebugEngine::continueInferior() m_d->m_debuggerManager->resetLocation(); ULONG executionStatus; + m_d->m_debuggerManagerAccess->notifyInferiorRunningRequested(); HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus); if (SUCCEEDED(hr) && executionStatus != DEBUG_STATUS_GO) { hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO); @@ -654,8 +667,10 @@ void CdbDebugEngine::activateFrame(int frameIndex) if (debugCDB) qDebug() << Q_FUNC_INFO << frameIndex; - if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped) + if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped) { + qWarning("WARNING %s: invoked while debuggee is running\n", Q_FUNC_INFO); return; + } QString errorMessage; bool success = false; @@ -793,7 +808,7 @@ void CdbDebugEngine::timerEvent(QTimerEvent* te) const HRESULT hr = m_d->m_pDebugControl->WaitForEvent(0, 1); if (debugCDB) if (debugCDB > 1 || hr != S_FALSE) - qDebug() << Q_FUNC_INFO << "WaitForEvent" << msgDebugEngineComResult(hr); + qDebug() << Q_FUNC_INFO << "WaitForEvent" << m_d->m_debuggerManager->status() << msgDebugEngineComResult(hr); switch (hr) { case S_OK: @@ -974,9 +989,10 @@ void CdbDebugEnginePrivate::updateStackTrace() } } -void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString) +void CdbDebugEnginePrivate::handleDebugOutput(const char *szOutputString) { - qDebug() << Q_FUNC_INFO << szOutputString; + if (debugCDB && strstr(szOutputString, "ModLoad:") == 0) + qDebug() << Q_FUNC_INFO << szOutputString; m_debuggerManagerAccess->showApplicationOutput(QString::fromLocal8Bit(szOutputString)); } diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h index 59ebeed571efb3145d10240490d6226d9021a626..0662a8350a091494acc71715e16fea72f65f0d4d 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.h +++ b/src/plugins/debugger/cdb/cdbdebugengine.h @@ -104,6 +104,7 @@ private: bool startDebuggerWithExecutable(DebuggerStartMode sm, QString *errorMessage); void startWatchTimer(); void killWatchTimer(); + void processTerminated(unsigned long exitCode); CdbDebugEnginePrivate *m_d; diff --git a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp index c0f6cd80a40984e224ee5761cc0bb62497de8b39..ee8120f3e53c6ed767ddb1a4b03eceaa489da2fc 100644 --- a/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp +++ b/src/plugins/debugger/cdb/cdbdebugeventcallback.cpp @@ -192,9 +192,7 @@ STDMETHODIMP CdbDebugEventCallback::ExitProcess( { if (debugCDB) qDebug() << Q_FUNC_INFO << ExitCode; - - m_pEngine->m_d->setDebuggeeHandles(0, 0); - m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited(); + m_pEngine->processTerminated(ExitCode); return S_OK; } diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index c86d3793014db99b92085c0ee58455d4ad4cc925..f6388fa835947b36a5fa3d9c348bad86bb1eb47c 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -26,6 +26,7 @@ HEADERS += \ debuggerrunner.h \ disassemblerhandler.h \ disassemblerwindow.h \ + watchutils.h \ gdbengine.h \ gdbmi.h \ idebuggerengine.h \ @@ -56,6 +57,7 @@ SOURCES += \ debuggerrunner.cpp \ disassemblerhandler.cpp \ disassemblerwindow.cpp \ + watchutils.cpp \ gdbengine.cpp \ gdbmi.cpp \ moduleshandler.cpp \ diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index f7edac224f73d604c659ee75c8a5d3a7942cadf4..0a281d4fbcf70efdfc42e2f881c2930e133cb60e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -34,7 +34,9 @@ #include <QtCore/QDebug> #include <QtCore/QSettings> + #include <QtGui/QAction> +#include <QtGui/QActionGroup> #include <QtGui/QAbstractButton> #include <QtGui/QRadioButton> #include <QtGui/QCheckBox> @@ -253,8 +255,15 @@ void DebuggerAction::pathChooserEditingFinished() void DebuggerAction::actionTriggered(bool) { - if (this->isCheckable()) - setValue(this->isChecked()); + //qDebug() << "TRIGGERING" << this << actionGroup(); + if (isCheckable()) + setValue(isChecked()); + if (actionGroup() && actionGroup()->isExclusive()) { + // FIXME: should be taken care of more directly + foreach (QAction *act, actionGroup()->actions()) + if (DebuggerAction *dact = qobject_cast<DebuggerAction *>(act)) + dact->setValue(bool(act == this)); + } } void DebuggerAction::trigger(const QVariant &data) @@ -331,6 +340,9 @@ DebuggerSettings *theDebuggerSettings() DebuggerAction *item = 0; + // + // View + // item = new DebuggerAction(instance); instance->insertItem(AdjustColumnWidths, item); item->setText(QObject::tr("Adjust column widths to contents")); @@ -340,6 +352,9 @@ DebuggerSettings *theDebuggerSettings() item->setText(QObject::tr("Always adjust column widths to contents")); item->setCheckable(true); + // + // Locals & Watchers + // item = new DebuggerAction(instance); instance->insertItem(WatchExpression, item); item->setTextPattern(QObject::tr("Watch expression \"%1\"")); @@ -356,6 +371,14 @@ DebuggerSettings *theDebuggerSettings() item = new DebuggerAction(instance); instance->insertItem(AssignValue, item); + item = new DebuggerAction(instance); + instance->insertItem(ExpandItem, item); + item->setText(QObject::tr("Expand item")); + + item = new DebuggerAction(instance); + instance->insertItem(CollapseItem, item); + item->setText(QObject::tr("Collapse item")); + // // Dumpers // @@ -369,21 +392,69 @@ DebuggerSettings *theDebuggerSettings() item->setCheckable(true); item = new DebuggerAction(instance); - instance->insertItem(RecheckDumpers, item); item->setText(QObject::tr("Recheck custom dumper availability")); + instance->insertItem(RecheckDumpers, item); // // Breakpoints // item = new DebuggerAction(instance); - instance->insertItem(SynchronizeBreakpoints, item); item->setText(QObject::tr("Syncronize breakpoints")); + instance->insertItem(SynchronizeBreakpoints, item); // + // Registers + // + + QActionGroup *registerFormatGroup = new QActionGroup(instance); + registerFormatGroup->setExclusive(true); + item = new DebuggerAction(instance); - instance->insertItem(AutoQuit, item); - item->setText(QObject::tr("Automatically quit debugger")); + item->setText(QObject::tr("Hexadecimal")); + item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatHexadecimal"); + item->setChecked(true); + instance->insertItem(FormatHexadecimal, item); + registerFormatGroup->addAction(item); + + item = new DebuggerAction(instance); + item->setText(QObject::tr("Decimal")); + item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatDecimal"); + instance->insertItem(FormatDecimal, item); + registerFormatGroup->addAction(item); + + item = new DebuggerAction(instance); + item->setText(QObject::tr("Octal")); item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatOctal"); + instance->insertItem(FormatOctal, item); + registerFormatGroup->addAction(item); + + item = new DebuggerAction(instance); + item->setText(QObject::tr("Binary")); + item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatBinary"); + instance->insertItem(FormatBinary, item); + registerFormatGroup->addAction(item); + + item = new DebuggerAction(instance); + item->setText(QObject::tr("Raw")); + item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatRaw"); + instance->insertItem(FormatRaw, item); + registerFormatGroup->addAction(item); + + item = new DebuggerAction(instance); + item->setText(QObject::tr("Natural")); + item->setCheckable(true); + item->setSettingsKey("DebugMode", "FormatNatural"); + instance->insertItem(FormatNatural, item); + registerFormatGroup->addAction(item); + + // + // Misc + // item = new DebuggerAction(instance); instance->insertItem(SkipKnownFrames, item); @@ -417,12 +488,10 @@ DebuggerSettings *theDebuggerSettings() item->setSettingsKey("DebugMode", "ScriptFile"); item = new DebuggerAction(instance); - instance->insertItem(GdbAutoQuit, item); item->setSettingsKey("DebugMode", "AutoQuit"); - - item = new DebuggerAction(instance); - instance->insertItem(GdbAutoRun, item); - item->setSettingsKey("DebugMode", "AutoRun"); + item->setText(QObject::tr("Automatically quit debugger")); + item->setCheckable(true); + instance->insertItem(AutoQuit, item); item = new DebuggerAction(instance); instance->insertItem(UseToolTips, item); @@ -450,7 +519,7 @@ DebuggerSettings *theDebuggerSettings() item->setSettingsKey("DebugMode", "PrebuiltDumpersLocation"); item = new DebuggerAction(instance); - instance->insertItem(Terminal, item); + instance->insertItem(TerminalApplication, item); item->setDefaultValue("xterm"); item->setSettingsKey("DebugMode", "Terminal"); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 47ccfa9638620e4f8557a1825ea8ab10e27b587b..75029ab9526e1d492432e4ea0aa09914ed1a2893 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -134,16 +134,14 @@ enum DebuggerActionCode SettingsDialog, AdjustColumnWidths, AlwaysAdjustColumnWidths, - + AutoQuit, + TerminalApplication, LockView, // Gdb GdbLocation, GdbEnvironment, GdbScriptFile, - GdbAutoRun, - GdbAutoQuit, - Terminal, // Watchers & Locals WatchExpression, @@ -152,6 +150,8 @@ enum DebuggerActionCode WatchModelUpdate, UseToolTips, AssignValue, + ExpandItem, + CollapseItem, RecheckDumpers, UsePrebuiltDumpers, @@ -173,7 +173,13 @@ enum DebuggerActionCode NoPluginBreakpoints, SelectedPluginBreakpointsPattern, - AutoQuit, + // Registers + FormatHexadecimal, + FormatDecimal, + FormatOctal, + FormatBinary, + FormatRaw, + FormatNatural, }; // singleton access diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index c1369aa3298d93eb87150a2ae646aa0105601281..a17d1bb060c5cf008d737465ab11f0bd6e871a3a 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -51,8 +51,6 @@ const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug"; const char * const C_GDBDEBUGGER = "Gdb Debugger"; const char * const GDBRUNNING = "Gdb.Running"; -const char * const PROPERTY_REGISTER_FORMAT = "Debugger.Property.RegisterFormat"; - namespace Internal { enum { debug = 0 }; } diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 5b7bb4be8ed236a70bcd5f1b980b9e37d6fb30eb..561397ed36e47c34abc150a9f196f6f745d79710 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -88,6 +88,25 @@ using namespace Debugger::Constants; static const QString tooltipIName = "tooltip"; +static const char *stateName(int s) +{ + switch (s) { + case DebuggerProcessNotReady: + return "DebuggerProcessNotReady"; + case DebuggerProcessStartingUp: + return "DebuggerProcessStartingUp"; + case DebuggerInferiorRunningRequested: + return "DebuggerInferiorRunningRequested"; + case DebuggerInferiorRunning: + return "DebuggerInferiorRunning"; + case DebuggerInferiorStopRequested: + return "DebuggerInferiorStopRequested"; + case DebuggerInferiorStopped: + return "DebuggerInferiorStopped"; + } + return "<unknown>"; +} + /////////////////////////////////////////////////////////////////////// // // BreakByFunctionDialog @@ -251,18 +270,10 @@ void DebuggerManager::init() // Locals QTreeView *localsView = qobject_cast<QTreeView *>(m_localsWindow); localsView->setModel(m_watchHandler->model()); - connect(localsView, SIGNAL(requestExpandChildren(QModelIndex)), - this, SLOT(expandChildren(QModelIndex))); - connect(localsView, SIGNAL(requestCollapseChildren(QModelIndex)), - this, SLOT(collapseChildren(QModelIndex))); // Watchers QTreeView *watchersView = qobject_cast<QTreeView *>(m_watchersWindow); watchersView->setModel(m_watchHandler->model()); - connect(watchersView, SIGNAL(requestExpandChildren(QModelIndex)), - this, SLOT(expandChildren(QModelIndex))); - connect(watchersView, SIGNAL(requestCollapseChildren(QModelIndex)), - this, SLOT(collapseChildren(QModelIndex))); connect(m_watchHandler, SIGNAL(sessionValueRequested(QString,QVariant*)), this, SIGNAL(sessionValueRequested(QString,QVariant*))); connect(m_watchHandler, SIGNAL(setSessionValueRequested(QString,QVariant)), @@ -718,18 +729,6 @@ void DebuggerManager::updateWatchModel() m_engine->updateWatchModel(); } -void DebuggerManager::expandChildren(const QModelIndex &idx) -{ - QTC_ASSERT(m_watchHandler, return); - m_watchHandler->expandChildren(idx); -} - -void DebuggerManager::collapseChildren(const QModelIndex &idx) -{ - QTC_ASSERT(m_watchHandler, return); - m_watchHandler->collapseChildren(idx); -} - QVariant DebuggerManager::sessionValue(const QString &name) { // this is answered by the plugin @@ -1153,13 +1152,16 @@ static bool isAllowedTransition(int from, int to) void DebuggerManager::setStatus(int status) { if (Debugger::Constants::Internal::debug) - qDebug() << Q_FUNC_INFO << "STATUS CHANGE: from" << m_status << "to" << status; + qDebug() << Q_FUNC_INFO << "STATUS CHANGE: from" << stateName(m_status) << "to" << stateName(status); if (status == m_status) return; - if (!isAllowedTransition(m_status, status)) - qDebug() << "UNEXPECTED TRANSITION: " << m_status << status; + if (!isAllowedTransition(m_status, status)) { + const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3"). + arg(QLatin1String(Q_FUNC_INFO), QLatin1String(stateName(m_status)), QLatin1String(stateName(status))); + qWarning("%s", qPrintable(msg)); + } m_status = status; diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 77e629e38e501eedc93fe38613cdc65e6fba08eb..414ef429631d8c588283e6be5574d86a3c4b36e1 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -231,8 +231,6 @@ public slots: void addToWatchWindow(); void updateWatchModel(); - void expandChildren(const QModelIndex &idx); - void collapseChildren(const QModelIndex &idx); void sessionLoaded(); void aboutToSaveSession(); diff --git a/src/plugins/debugger/debuggeroutputwindow.cpp b/src/plugins/debugger/debuggeroutputwindow.cpp index 74d8e8bb5e63ee1810101ac71d3d20913f83b088..37799215354f53f9d7645c8ebbab88b1bfc1f68b 100644 --- a/src/plugins/debugger/debuggeroutputwindow.cpp +++ b/src/plugins/debugger/debuggeroutputwindow.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "debuggeroutputwindow.h" +#include "debuggeractions.h" #include <QtCore/QDebug> @@ -51,7 +52,7 @@ using namespace Find; #endif // GDBDEBUGGERLEAN -using Debugger::Internal::DebuggerOutputWindow; +using namespace Debugger::Internal; ///////////////////////////////////////////////////////////////////// // @@ -83,6 +84,8 @@ public: menu->addAction(m_clearContentsAction); //menu->addAction(m_saveContentsAction); addContextActions(menu); + menu->addSeparator(); + menu->addAction(theDebuggerAction(SettingsDialog)); menu->exec(ev->globalPos()); delete menu; } diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 2a66c1422e73e3b9fdb5adcc3e9c7f2ac9f06a65..cc3c0f01d7f80b86e1917edf5bf60e7a54d25a3c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -278,7 +278,7 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) ->connectWidget(m_ui.scriptFileChooser); theDebuggerAction(GdbEnvironment) ->connectWidget(m_ui.environmentEdit); - theDebuggerAction(Terminal) + theDebuggerAction(TerminalApplication) ->connectWidget(m_ui.terminalChooser); theDebuggerAction(AllPluginBreakpoints) @@ -319,7 +319,7 @@ void GdbOptionPage::apply() theDebuggerAction(GdbLocation)->apply(s); theDebuggerAction(GdbScriptFile)->apply(s); theDebuggerAction(GdbEnvironment)->apply(s); - theDebuggerAction(Terminal)->apply(s); + theDebuggerAction(TerminalApplication)->apply(s); theDebuggerAction(AllPluginBreakpoints)->apply(s); theDebuggerAction(SelectedPluginBreakpoints)->apply(s); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 535276b326cfde9604675929fc1b7a9989807092..b85b74e6c52fcc593ad64cfb8a896c889e7a614e 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -29,6 +29,7 @@ #include "gdbengine.h" +#include "watchutils.h" #include "debuggeractions.h" #include "debuggerconstants.h" #include "debuggermanager.h" @@ -152,88 +153,12 @@ enum GdbCommandType WatchDumpCustomEditValue, }; -QString dotEscape(QString str) -{ - str.replace(' ', '.'); - str.replace('\\', '.'); - str.replace('/', '.'); - return str; -} - -QString currentTime() -{ - return QTime::currentTime().toString("hh:mm:ss.zzz"); -} - static int ¤tToken() { static int token = 0; return token; } -static bool isSkippableFunction(const QString &funcName, const QString &fileName) -{ - if (fileName.endsWith("kernel/qobject.cpp")) - return true; - if (fileName.endsWith("kernel/moc_qobject.cpp")) - return true; - if (fileName.endsWith("kernel/qmetaobject.cpp")) - return true; - if (fileName.endsWith(".moc")) - return true; - - if (funcName.endsWith("::qt_metacall")) - return true; - - return false; -} - -static bool isLeavableFunction(const QString &funcName, const QString &fileName) -{ - if (funcName.endsWith("QObjectPrivate::setCurrentSender")) - return true; - if (fileName.endsWith("kernel/qmetaobject.cpp") - && funcName.endsWith("QMetaObject::methodOffset")) - return true; - if (fileName.endsWith("kernel/qobject.h")) - return true; - if (fileName.endsWith("kernel/qobject.cpp") - && funcName.endsWith("QObjectConnectionListVector::at")) - return true; - if (fileName.endsWith("kernel/qobject.cpp") - && funcName.endsWith("~QObject")) - return true; - if (fileName.endsWith("thread/qmutex.cpp")) - return true; - if (fileName.endsWith("thread/qthread.cpp")) - return true; - if (fileName.endsWith("thread/qthread_unix.cpp")) - return true; - if (fileName.endsWith("thread/qmutex.h")) - return true; - if (fileName.contains("thread/qbasicatomic")) - return true; - if (fileName.contains("thread/qorderedmutexlocker_p")) - return true; - if (fileName.contains("arch/qatomic")) - return true; - if (fileName.endsWith("tools/qvector.h")) - return true; - if (fileName.endsWith("tools/qlist.h")) - return true; - if (fileName.endsWith("tools/qhash.h")) - return true; - if (fileName.endsWith("tools/qmap.h")) - return true; - if (fileName.endsWith("tools/qstring.h")) - return true; - if (fileName.endsWith("global/qglobal.h")) - return true; - - return false; -} - - /////////////////////////////////////////////////////////////////////// // // GdbEngine @@ -291,6 +216,19 @@ void GdbEngine::initializeConnections() this, SLOT(setDebugDumpers(bool))); connect(theDebuggerAction(RecheckDumpers), SIGNAL(triggered()), this, SLOT(recheckCustomDumperAvailability())); + + connect(theDebuggerAction(FormatHexadecimal), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); + connect(theDebuggerAction(FormatDecimal), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); + connect(theDebuggerAction(FormatOctal), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); + connect(theDebuggerAction(FormatBinary), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); + connect(theDebuggerAction(FormatRaw), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); + connect(theDebuggerAction(FormatNatural), SIGNAL(triggered()), + this, SLOT(reloadRegisters())); } void GdbEngine::initializeVariables() @@ -351,12 +289,6 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error) q->exitDebugger(); } -static inline bool isNameChar(char c) -{ - // could be 'stopped' or 'shlibs-added' - return (c >= 'a' && c <= 'z') || c == '-'; -} - #if 0 static void dump(const char *first, const char *middle, const QString & to) { @@ -497,7 +429,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) // On Windows, the contents seem to depend on the debugger // version and/or OS version used. if (data.startsWith("warning:")) - qq->showApplicationOutput(data); + qq->showApplicationOutput(data.mid(9)); // cut "warning: " break; } @@ -1562,7 +1494,6 @@ int GdbEngine::currentFrame() const return qq->stackHandler()->currentIndex(); } - bool GdbEngine::startDebugger() { debugMessage(theDebuggerSettings()->dump()); @@ -2656,7 +2587,19 @@ void GdbEngine::handleStackListThreads(const GdbResultRecord &record, int id) void GdbEngine::reloadRegisters() { - QString format = qq->registerHandler()->model()->property(PROPERTY_REGISTER_FORMAT).toString(); + QString format; + if (theDebuggerAction(FormatHexadecimal)->isChecked()) + format = "x"; + else if (theDebuggerAction(FormatDecimal)->isChecked()) + format = "d"; + else if (theDebuggerAction(FormatOctal)->isChecked()) + format = "o"; + else if (theDebuggerAction(FormatBinary)->isChecked()) + format = "t"; + else if (theDebuggerAction(FormatRaw)->isChecked()) + format = "r"; + else + format = "N"; sendCommand("-data-list-register-values " + format, RegisterListValues); } @@ -2718,43 +2661,6 @@ static QString m_toolTipExpression; static QPoint m_toolTipPos; static QMap<QString, WatchData> m_toolTipCache; -static bool hasLetterOrNumber(const QString &exp) -{ - for (int i = exp.size(); --i >= 0; ) - if (exp[i].isLetterOrNumber() || exp[i] == '_') - return true; - return false; -} - -static bool hasSideEffects(const QString &exp) -{ - // FIXME: complete? - return exp.contains("-=") - || exp.contains("+=") - || exp.contains("/=") - || exp.contains("*=") - || exp.contains("&=") - || exp.contains("|=") - || exp.contains("^=") - || exp.contains("--") - || exp.contains("++"); -} - -static bool isKeyWord(const QString &exp) -{ - // FIXME: incomplete - return exp == QLatin1String("class") - || exp == QLatin1String("const") - || exp == QLatin1String("do") - || exp == QLatin1String("if") - || exp == QLatin1String("return") - || exp == QLatin1String("struct") - || exp == QLatin1String("template") - || exp == QLatin1String("void") - || exp == QLatin1String("volatile") - || exp == QLatin1String("while"); -} - void GdbEngine::setToolTipExpression(const QPoint &pos, const QString &exp0) { //qDebug() << "SET TOOLTIP EXP" << pos << exp0; @@ -2861,85 +2767,6 @@ void GdbEngine::setToolTipExpression(const QPoint &pos, const QString &exp0) static const QString strNotInScope = QLatin1String("<not in scope>"); -static bool isPointerType(const QString &type) -{ - return type.endsWith("*") || type.endsWith("* const"); -} - -static bool isAccessSpecifier(const QString &str) -{ - static const QStringList items = - QStringList() << "private" << "protected" << "public"; - return items.contains(str); -} - -static bool startsWithDigit(const QString &str) -{ - return !str.isEmpty() && str[0] >= '0' && str[0] <= '9'; -} - -QString stripPointerType(QString type) -{ - if (type.endsWith("*")) - type.chop(1); - if (type.endsWith("* const")) - type.chop(7); - if (type.endsWith(' ')) - type.chop(1); - return type; -} - -static QString gdbQuoteTypes(const QString &type) -{ - // gdb does not understand sizeof(Core::IFile*). - // "sizeof('Core::IFile*')" is also not acceptable, - // it needs to be "sizeof('Core::IFile'*)" - // - // We never will have a perfect solution here (even if we had a full blown - // C++ parser as we do not have information on what is a type and what is - // a variable name. So "a<b>::c" could either be two comparisons of values - // 'a', 'b' and '::c', or a nested type 'c' in a template 'a<b>'. We - // assume here it is the latter. - //return type; - - // (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable - // (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable - if (isPointerType(type)) - return gdbQuoteTypes(stripPointerType(type)) + "*"; - - QString accu; - QString result; - int templateLevel = 0; - for (int i = 0; i != type.size(); ++i) { - QChar c = type.at(i); - if (c.isLetterOrNumber() || c == '_' || c == ':' || c == ' ') { - accu += c; - } else if (c == '<') { - ++templateLevel; - accu += c; - } else if (c == '<') { - --templateLevel; - accu += c; - } else if (templateLevel > 0) { - accu += c; - } else { - if (accu.contains(':') || accu.contains('<')) - result += '\'' + accu + '\''; - else - result += accu; - accu.clear(); - result += c; - } - } - if (accu.contains(':') || accu.contains('<')) - result += '\'' + accu + '\''; - else - result += accu; - //qDebug() << "GDB_QUOTING" << type << " TO " << result; - - return result; -} - static void setWatchDataValue(WatchData &data, const GdbMi &mi, int encoding = 0) { @@ -3023,68 +2850,6 @@ static void setWatchDataSAddress(WatchData &data, const GdbMi &mi) data.saddr = mi.data(); } -static bool extractTemplate(const QString &type, QString *tmplate, QString *inner) -{ - // Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in - // 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates - // whether parsing was successful - int level = 0; - bool skipSpace = false; - for (int i = 0; i != type.size(); ++i) { - QChar c = type[i]; - if (c == ' ' && skipSpace) { - skipSpace = false; - } else if (c == '<') { - *(level == 0 ? tmplate : inner) += c; - ++level; - } else if (c == '>') { - --level; - *(level == 0 ? tmplate : inner) += c; - } else if (c == ',') { - *inner += (level == 1) ? '@' : ','; - skipSpace = true; - } else { - *(level == 0 ? tmplate : inner) += c; - } - } - *tmplate = tmplate->trimmed(); - *tmplate = tmplate->remove("<>"); - *inner = inner->trimmed(); - //qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type; - return !inner->isEmpty(); -} - -static QString extractTypeFromPTypeOutput(const QString &str) -{ - int pos0 = str.indexOf('='); - int pos1 = str.indexOf('{'); - int pos2 = str.lastIndexOf('}'); - QString res = str; - if (pos0 != -1 && pos1 != -1 && pos2 != -1) - res = str.mid(pos0 + 2, pos1 - 1 - pos0) - + " ... " + str.right(str.size() - pos2); - return res.simplified(); -} - -static bool isIntOrFloatType(const QString &type) -{ - static const QStringList types = QStringList() - << "char" << "int" << "short" << "float" << "double" << "long" - << "bool" << "signed char" << "unsigned" << "unsigned char" - << "unsigned int" << "unsigned long" << "long long" - << "unsigned long long"; - return types.contains(type); -} - -static QString sizeofTypeExpression(const QString &type) -{ - if (type.endsWith('*')) - return "sizeof(void*)"; - if (type.endsWith('>')) - return "sizeof(" + type + ")"; - return "sizeof(" + gdbQuoteTypes(type) + ")"; -} - void GdbEngine::setUseDumpers(bool on) { qDebug() << "SWITCHING ON/OFF DUMPER DEBUGGING:" << on; @@ -4304,4 +4069,3 @@ IDebuggerEngine *createGdbEngine(DebuggerManager *parent) { return new GdbEngine(parent); } - diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 20c9c222877b92dfbdb544ba90f5dfd8990a03f3..d35f0f0827174a8b059940436ebd175f9daa0dbf 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -265,7 +265,7 @@ private: // // Register specific stuff // - void reloadRegisters(); + Q_SLOT void reloadRegisters(); void handleRegisterListNames(const GdbResultRecord &record); void handleRegisterListValues(const GdbResultRecord &record); diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp index 70bae1b2b3808946359eaaf0bf6059368bf7c5fe..12dd1d213162b36a8d5ecd0d32866ca594fe7912 100644 --- a/src/plugins/debugger/registerhandler.cpp +++ b/src/plugins/debugger/registerhandler.cpp @@ -51,9 +51,7 @@ using namespace Debugger::Constants; RegisterHandler::RegisterHandler(QObject *parent) : QAbstractTableModel(parent) -{ - setProperty(PROPERTY_REGISTER_FORMAT, "x"); -} +{} int RegisterHandler::rowCount(const QModelIndex &parent) const { diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index e83a3abb052fe7086d2b556d7f999d9d80128b9d..03239d8875ab176e9e968505a81fcf8676fa8390 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -29,17 +29,19 @@ #include "registerwindow.h" +#include "debuggeractions.h" #include "debuggerconstants.h" -#include <QAction> -#include <QDebug> -#include <QDir> -#include <QFileInfo> -#include <QFileInfoList> -#include <QHeaderView> -#include <QMenu> -#include <QResizeEvent> -#include <QToolButton> +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QFileInfoList> + +#include <QtGui/QAction> +#include <QtGui/QHeaderView> +#include <QtGui/QMenu> +#include <QtGui/QResizeEvent> +#include <QtGui/QToolButton> using namespace Debugger::Internal; @@ -72,14 +74,12 @@ void RegisterWindow::resizeEvent(QResizeEvent *ev) void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) { - enum { Hex, Bin, Dec, Raw, Oct, Nat, - Adjust, AlwaysAdjust, Reload, AlwaysReload, Count }; + enum { Adjust, AlwaysAdjust, Reload, AlwaysReload, Count }; QMenu menu; QAction *actions[Count]; - //QTreeWidgetItem *item = itemAt(ev->pos()); - QString format = model()->property(PROPERTY_REGISTER_FORMAT).toString(); - qDebug() << "FORMAT: " << format; + //QString format = model()->property(PROPERTY_REGISTER_FORMAT).toString(); + //qDebug() << "FORMAT: " << format; actions[Adjust] = menu.addAction("Adjust column widths to contents"); @@ -94,30 +94,15 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) actions[AlwaysReload]->setChecked(m_alwaysReloadContents); menu.addSeparator(); + menu.addAction(theDebuggerAction(FormatHexadecimal)); + menu.addAction(theDebuggerAction(FormatDecimal)); + menu.addAction(theDebuggerAction(FormatOctal)); + menu.addAction(theDebuggerAction(FormatBinary)); + menu.addAction(theDebuggerAction(FormatRaw)); + menu.addAction(theDebuggerAction(FormatNatural)); - actions[Hex] = menu.addAction("Hexadecimal"); - actions[Hex]->setCheckable(true); - actions[Hex]->setChecked(format == "h"); - - actions[Bin] = menu.addAction("Binary"); - actions[Bin]->setCheckable(true); - actions[Bin]->setChecked(format == "t"); - - actions[Dec] = menu.addAction("Decimal"); - actions[Dec]->setCheckable(true); - actions[Dec]->setChecked(format == "d"); - - actions[Raw] = menu.addAction("Raw"); - actions[Raw]->setCheckable(true); - actions[Raw]->setChecked(format == "r"); - - actions[Nat] = menu.addAction("Natural"); - actions[Nat]->setCheckable(true); - actions[Nat]->setChecked(format == "N"); - - actions[Oct] = menu.addAction("Octal"); - actions[Oct]->setCheckable(true); - actions[Oct]->setChecked(format == "o"); + menu.addSeparator(); + menu.addAction(theDebuggerAction(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); @@ -129,17 +114,6 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) reloadContents(); else if (act == actions[AlwaysReload]) setAlwaysReloadContents(!m_alwaysReloadContents); - else if (act == actions[Hex]) - model()->setProperty(PROPERTY_REGISTER_FORMAT, "h"); - else if (act == actions[Oct]) - model()->setProperty(PROPERTY_REGISTER_FORMAT, "o"); - else if (act == actions[Bin]) - model()->setProperty(PROPERTY_REGISTER_FORMAT, "t"); - else if (act == actions[Dec]) - model()->setProperty(PROPERTY_REGISTER_FORMAT, "d"); - else if (act == actions[Nat]) - model()->setProperty(PROPERTY_REGISTER_FORMAT, "N"); - } void RegisterWindow::resizeColumnsToContents() diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp index 1f90bc0d8186b41a78a8b7f9b4e0e381c76bb4d2..7b927cd4de829c887ddd6f8887c3391bb9f61c72 100644 --- a/src/plugins/debugger/sourcefileswindow.cpp +++ b/src/plugins/debugger/sourcefileswindow.cpp @@ -28,18 +28,19 @@ **************************************************************************/ #include "sourcefileswindow.h" +#include "debuggeractions.h" -#include <QDebug> -#include <QAction> -#include <QComboBox> -#include <QFileInfo> -#include <QDebug> -#include <QHeaderView> -#include <QMenu> -#include <QResizeEvent> -#include <QTreeView> -#include <QSortFilterProxyModel> -#include <QVBoxLayout> +#include <QtCore/QDebug> +#include <QtCore/QFileInfo> + +#include <QtGui/QAction> +#include <QtGui/QComboBox> +#include <QtGui/QHeaderView> +#include <QtGui/QMenu> +#include <QtGui/QResizeEvent> +#include <QtGui/QSortFilterProxyModel> +#include <QtGui/QTreeView> +#include <QtGui/QVBoxLayout> using Debugger::Internal::SourceFilesWindow; using Debugger::Internal::SourceFilesModel; @@ -205,6 +206,8 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addAction(act1); menu.addAction(act2); + menu.addSeparator(); + menu.addAction(theDebuggerAction(SettingsDialog)); QAction *act = menu.exec(ev->globalPos()); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index cfe0eb5338ceb24ee530b0d54f175a4ca8a2f918..e8bb8d5fe5e7957346a49b7fef903a44da951da3 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -370,9 +370,12 @@ WatchHandler::WatchHandler() connect(theDebuggerAction(WatchExpression), SIGNAL(triggered()), this, SLOT(watchExpression())); - connect(theDebuggerAction(RemoveWatchExpression), SIGNAL(triggered()), this, SLOT(removeWatchExpression())); + connect(theDebuggerAction(ExpandItem), + SIGNAL(triggered()), this, SLOT(expandChildren())); + connect(theDebuggerAction(CollapseItem), + SIGNAL(triggered()), this, SLOT(collapseChildren())); } static QString niceType(QString type) @@ -748,7 +751,8 @@ void WatchHandler::rebuildModel() m_inChange = true; //qDebug() << "WATCHHANDLER: RESET ABOUT TO EMIT"; - emit reset(); + //emit reset(); + emit layoutChanged(); //qDebug() << "WATCHHANDLER: RESET EMITTED"; m_inChange = false; @@ -785,15 +789,19 @@ void WatchHandler::cleanup() emit reset(); } -void WatchHandler::collapseChildren(const QModelIndex &idx) +void WatchHandler::collapseChildren() +{ + if (QAction *act = qobject_cast<QAction *>(sender())) + collapseChildren(act->data().toString()); +} + +void WatchHandler::collapseChildren(const QString &iname) { if (m_inChange || m_completeSet.isEmpty()) { - qDebug() << "WATCHHANDLER: COLLAPSE IGNORED" << idx; + qDebug() << "WATCHHANDLER: COLLAPSE IGNORED" << iname; return; } - QTC_ASSERT(checkIndex(idx.internalId()), return); - QString iname0 = m_displaySet.at(idx.internalId()).iname; - MODEL_DEBUG("COLLAPSE NODE" << iname0); + MODEL_DEBUG("COLLAPSE NODE" << iname); #if 0 QString iname1 = iname0 + '.'; for (int i = m_completeSet.size(); --i >= 0; ) { @@ -806,19 +814,32 @@ void WatchHandler::collapseChildren(const QModelIndex &idx) } } #endif - m_expandedINames.remove(iname0); + m_expandedINames.remove(iname); //MODEL_DEBUG(toString()); //rebuildModel(); } -void WatchHandler::expandChildren(const QModelIndex &idx) +void WatchHandler::expandChildren() +{ + if (QAction *act = qobject_cast<QAction *>(sender())) + expandChildren(act->data().toString()); +} + +void WatchHandler::expandChildren(const QString &iname) { if (m_inChange || m_completeSet.isEmpty()) { - //qDebug() << "WATCHHANDLER: EXPAND IGNORED" << idx; + //qDebug() << "WATCHHANDLER: EXPAND IGNORED" << iname; return; } - int index = idx.internalId(); - if (index == 0) + int index = -1; + for (int i = 0; i != m_displaySet.size(); ++i) { + if (m_displaySet.at(i).iname == iname) { + index = i; + break; + } + } + + if (index == -1) return; QTC_ASSERT(index >= 0, qDebug() << toString() << index; return); QTC_ASSERT(index < m_completeSet.size(), qDebug() << toString() << index; return); @@ -832,8 +853,7 @@ void WatchHandler::expandChildren(const QModelIndex &idx) // "expand()" signals folr the root item from time to time. // Try to handle that gracfully. //MODEL_DEBUG(toString()); - qDebug() << "FIXME: expandChildren, no data " << display.iname << "found" - << idx; + qDebug() << "FIXME: expandChildren, no data " << display.iname << "found"; //rebuildModel(); return; } diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index a41920381568e8c08c0fc5836566b4a6b7b8abd8..6701eecda34baf9de1a95553eef7deb9b7b2d721 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -165,8 +165,10 @@ public: Q_SLOT void removeWatchExpression(const QString &exp); void reinitializeWatchers(); - void collapseChildren(const QModelIndex &idx); - void expandChildren(const QModelIndex &idx); + Q_SLOT void collapseChildren(); + Q_SLOT void expandChildren(); + Q_SLOT void collapseChildren(const QString &iname); + Q_SLOT void expandChildren(const QString &iname); void rebuildModel(); // unconditionally version of above void showEditValue(const WatchData &data); diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c679857ab88879ee43f102092b2019d1dcfde6e1 --- /dev/null +++ b/src/plugins/debugger/watchutils.cpp @@ -0,0 +1,303 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#include "watchutils.h" + +#include <QtCore/QDebug> +#include <QtCore/QTime> +#include <QtCore/QStringList> + +namespace Debugger { +namespace Internal { + +QString dotEscape(QString str) +{ + const QChar dot = QLatin1Char(','); + str.replace(QLatin1Char(' '), dot); + str.replace(QLatin1Char('\\'), dot); + str.replace(QLatin1Char('/'), dot); + return str; +} + +QString currentTime() +{ + return QTime::currentTime().toString(QLatin1String("hh:mm:ss.zzz")); +} + +bool isSkippableFunction(const QString &funcName, const QString &fileName) +{ + if (fileName.endsWith(QLatin1String("kernel/qobject.cpp"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/moc_qobject.cpp"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/qmetaobject.cpp"))) + return true; + if (fileName.endsWith(QLatin1String(".moc"))) + return true; + + if (funcName.endsWith("::qt_metacall")) + return true; + + return false; +} + +bool isLeavableFunction(const QString &funcName, const QString &fileName) +{ + if (funcName.endsWith(QLatin1String("QObjectPrivate::setCurrentSender"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/qmetaobject.cpp")) + && funcName.endsWith(QLatin1String("QMetaObject::methodOffset"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/qobject.h"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/qobject.cpp")) + && funcName.endsWith(QLatin1String("QObjectConnectionListVector::at"))) + return true; + if (fileName.endsWith(QLatin1String("kernel/qobject.cpp")) + && funcName.endsWith(QLatin1String("~QObject"))) + return true; + if (fileName.endsWith(QLatin1String("thread/qmutex.cpp"))) + return true; + if (fileName.endsWith(QLatin1String("thread/qthread.cpp"))) + return true; + if (fileName.endsWith(QLatin1String("thread/qthread_unix.cpp"))) + return true; + if (fileName.endsWith(QLatin1String("thread/qmutex.h"))) + return true; + if (fileName.contains(QLatin1String("thread/qbasicatomic"))) + return true; + if (fileName.contains(QLatin1String("thread/qorderedmutexlocker_p"))) + return true; + if (fileName.contains(QLatin1String("arch/qatomic"))) + return true; + if (fileName.endsWith(QLatin1String("tools/qvector.h"))) + return true; + if (fileName.endsWith(QLatin1String("tools/qlist.h"))) + return true; + if (fileName.endsWith(QLatin1String("tools/qhash.h"))) + return true; + if (fileName.endsWith(QLatin1String("tools/qmap.h"))) + return true; + if (fileName.endsWith(QLatin1String("tools/qstring.h"))) + return true; + if (fileName.endsWith(QLatin1String("global/qglobal.h"))) + return true; + + return false; +} + +bool hasLetterOrNumber(const QString &exp) +{ + const QChar underscore = QLatin1Char('_'); + for (int i = exp.size(); --i >= 0; ) + if (exp.at(i).isLetterOrNumber() || exp.at(i) == underscore) + return true; + return false; +} + +bool hasSideEffects(const QString &exp) +{ + // FIXME: complete? + return exp.contains(QLatin1String("-=")) + || exp.contains(QLatin1String("+=")) + || exp.contains(QLatin1String("/=")) + || exp.contains(QLatin1String("*=")) + || exp.contains(QLatin1String("&=")) + || exp.contains(QLatin1String("|=")) + || exp.contains(QLatin1String("^=")) + || exp.contains(QLatin1String("--")) + || exp.contains(QLatin1String("++")); +} + +bool isKeyWord(const QString &exp) +{ + // FIXME: incomplete + return exp == QLatin1String("class") + || exp == QLatin1String("const") + || exp == QLatin1String("do") + || exp == QLatin1String("if") + || exp == QLatin1String("return") + || exp == QLatin1String("struct") + || exp == QLatin1String("template") + || exp == QLatin1String("void") + || exp == QLatin1String("volatile") + || exp == QLatin1String("while"); +} + +bool isPointerType(const QString &type) +{ + return type.endsWith(QLatin1Char('*')) || type.endsWith(QLatin1String("* const")); +} + +bool isAccessSpecifier(const QString &str) +{ + static const QStringList items = + QStringList() << QLatin1String("private") << QLatin1String("protected") << QLatin1String("public"); + return items.contains(str); +} + +bool startsWithDigit(const QString &str) +{ + return !str.isEmpty() && str.at(0).isDigit(); +} + +QString stripPointerType(QString type) +{ + if (type.endsWith(QLatin1Char('*'))) + type.chop(1); + if (type.endsWith(QLatin1String("* const"))) + type.chop(7); + if (type.endsWith(QLatin1Char(' '))) + type.chop(1); + return type; +} + +QString gdbQuoteTypes(const QString &type) +{ + // gdb does not understand sizeof(Core::IFile*). + // "sizeof('Core::IFile*')" is also not acceptable, + // it needs to be "sizeof('Core::IFile'*)" + // + // We never will have a perfect solution here (even if we had a full blown + // C++ parser as we do not have information on what is a type and what is + // a variable name. So "a<b>::c" could either be two comparisons of values + // 'a', 'b' and '::c', or a nested type 'c' in a template 'a<b>'. We + // assume here it is the latter. + //return type; + + // (*('myns::QPointer<myns::QObject>*'*)0x684060)" is not acceptable + // (*('myns::QPointer<myns::QObject>'**)0x684060)" is acceptable + if (isPointerType(type)) + return gdbQuoteTypes(stripPointerType(type)) + QLatin1Char('*'); + + QString accu; + QString result; + int templateLevel = 0; + + const QChar colon = QLatin1Char(':'); + const QChar singleQuote = QLatin1Char('\''); + const QChar lessThan = QLatin1Char('<'); + const QChar greaterThan = QLatin1Char('>'); + for (int i = 0; i != type.size(); ++i) { + const QChar c = type.at(i); + if (c.isLetterOrNumber() || c == QLatin1Char('_') || c == colon || c == QLatin1Char(' ')) { + accu += c; + } else if (c == lessThan) { + ++templateLevel; + accu += c; + } else if (c == greaterThan) { + --templateLevel; + accu += c; + } else if (templateLevel > 0) { + accu += c; + } else { + if (accu.contains(colon) || accu.contains(lessThan)) + result += singleQuote + accu + singleQuote; + else + result += accu; + accu.clear(); + result += c; + } + } + if (accu.contains(colon) || accu.contains(lessThan)) + result += singleQuote + accu + singleQuote; + else + result += accu; + //qDebug() << "GDB_QUOTING" << type << " TO " << result; + + return result; +} + +bool extractTemplate(const QString &type, QString *tmplate, QString *inner) +{ + // Input "Template<Inner1,Inner2,...>::Foo" will return "Template::Foo" in + // 'tmplate' and "Inner1@Inner2@..." etc in 'inner'. Result indicates + // whether parsing was successful + int level = 0; + bool skipSpace = false; + + for (int i = 0; i != type.size(); ++i) { + const QChar c = type.at(i); + if (c == QLatin1Char(' ') && skipSpace) { + skipSpace = false; + } else if (c == QLatin1Char('<')) { + *(level == 0 ? tmplate : inner) += c; + ++level; + } else if (c == QLatin1Char('>')) { + --level; + *(level == 0 ? tmplate : inner) += c; + } else if (c == QLatin1Char(',')) { + *inner += (level == 1) ? QLatin1Char('@') : QLatin1Char(','); + skipSpace = true; + } else { + *(level == 0 ? tmplate : inner) += c; + } + } + *tmplate = tmplate->trimmed(); + *tmplate = tmplate->remove(QLatin1String("<>")); + *inner = inner->trimmed(); + //qDebug() << "EXTRACT TEMPLATE: " << *tmplate << *inner << " FROM " << type; + return !inner->isEmpty(); +} + +QString extractTypeFromPTypeOutput(const QString &str) +{ + int pos0 = str.indexOf(QLatin1Char('=')); + int pos1 = str.indexOf(QLatin1Char('{')); + int pos2 = str.lastIndexOf(QLatin1Char('}')); + QString res = str; + if (pos0 != -1 && pos1 != -1 && pos2 != -1) + res = str.mid(pos0 + 2, pos1 - 1 - pos0) + + QLatin1String(" ... ") + str.right(str.size() - pos2); + return res.simplified(); +} + +bool isIntOrFloatType(const QString &type) +{ + static const QStringList types = QStringList() + << QLatin1String("char") << QLatin1String("int") << QLatin1String("short") + << QLatin1String("float") << QLatin1String("double") << QLatin1String("long") + << QLatin1String("bool") << QLatin1String("signed char") << QLatin1String("unsigned") + << QLatin1String("unsigned char") + << QLatin1String("unsigned int") << QLatin1String("unsigned long") + << QLatin1String("long long") << QLatin1String("unsigned long long"); + return types.contains(type); +} + +QString sizeofTypeExpression(const QString &type) +{ + if (type.endsWith(QLatin1Char('*'))) + return QLatin1String("sizeof(void*)"); + if (type.endsWith(QLatin1Char('>'))) + return QLatin1String("sizeof(") + type + QLatin1Char(')'); + return QLatin1String("sizeof(") + gdbQuoteTypes(type) + QLatin1Char(')'); +} + +} +} diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h new file mode 100644 index 0000000000000000000000000000000000000000..6c7dbb9143acc75536c66589d7a7f07391c0fb00 --- /dev/null +++ b/src/plugins/debugger/watchutils.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +**************************************************************************/ + +#ifndef WATCHUTILS_H +#define WATCHUTILS_H + +#include <QtCore/QString> + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE + +namespace Debugger { +namespace Internal { + +QString dotEscape(QString str); +QString currentTime(); +bool isSkippableFunction(const QString &funcName, const QString &fileName); +bool isLeavableFunction(const QString &funcName, const QString &fileName); + +inline bool isNameChar(char c) +{ + // could be 'stopped' or 'shlibs-added' + return (c >= 'a' && c <= 'z') || c == '-'; +} + +bool hasLetterOrNumber(const QString &exp); +bool hasSideEffects(const QString &exp); +bool isKeyWord(const QString &exp); +bool isPointerType(const QString &type); +bool isAccessSpecifier(const QString &str); +bool startsWithDigit(const QString &str); +QString stripPointerType(QString type); +QString gdbQuoteTypes(const QString &type); +bool extractTemplate(const QString &type, QString *tmplate, QString *inner); +QString extractTypeFromPTypeOutput(const QString &str); +bool isIntOrFloatType(const QString &type); +QString sizeofTypeExpression(const QString &type); + + +} // namespace Internal +} // namespace Debugger + +#endif // WATCHUTILS_H diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index de30e8f38065c5ca265f9acb38850821f1923bd6..e10d39319b68f80f7b2619ea542e19d8df444f99 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -125,19 +125,16 @@ WatchWindow::WatchWindow(Type type, QWidget *parent) 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(); - emit requestExpandChildren(idx); + QModelIndex mi0 = idx.sibling(idx.row(), 0); + QVariant iname = model()->data(mi0, INameRole); + theDebuggerAction(ExpandItem)->trigger(iname); } void WatchWindow::collapseNode(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() << "COLLAPSE NODE " << idx; - emit requestCollapseChildren(idx); + QModelIndex mi0 = idx.sibling(idx.row(), 0); + QVariant iname = model()->data(mi0, INameRole); + theDebuggerAction(CollapseItem)->trigger(iname); } void WatchWindow::keyPressEvent(QKeyEvent *ev) @@ -218,16 +215,13 @@ void WatchWindow::editItem(const QModelIndex &idx) void WatchWindow::reset() { + QTreeView::reset(); int row = 0; if (m_type == TooltipType) row = 1; else if (m_type == WatchersType) row = 2; - //qDebug() << "WATCHWINDOW::RESET" << row; - 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) @@ -239,16 +233,27 @@ void WatchWindow::setModel(QAbstractItemModel *model) header()->setResizeMode(QHeaderView::ResizeToContents); if (m_type != LocalsType) header()->hide(); + + connect(model, SIGNAL(layoutChanged()), this, SLOT(resetHelper())); +} + +void WatchWindow::resetHelper() +{ + resetHelper(model()->index(0, 0)); } void WatchWindow::resetHelper(const QModelIndex &idx) { if (model()->data(idx, ExpandedRole).toBool()) { + //qDebug() << "EXPANDING " << model()->data(idx, INameRole); expand(idx); for (int i = 0, n = model()->rowCount(idx); i != n; ++i) { QModelIndex idx1 = model()->index(i, 0, idx); resetHelper(idx1); } + } else { + //qDebug() << "COLLAPSING " << model()->data(idx, INameRole); + collapse(idx); } } diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index bf6995edb4adae1bee3eb4310b771bac9e595cc2..715507f8b16df9cef441cebd960581a11e02d9e4 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -57,15 +57,11 @@ public slots: void setAlwaysResizeColumnsToContents(bool on = true); void setModel(QAbstractItemModel *model); -signals: - void requestExpandChildren(const QModelIndex &idx); - void requestCollapseChildren(const QModelIndex &idx); - -private slots: - void expandNode(const QModelIndex &index); - void collapseNode(const QModelIndex &index); - private: + Q_SLOT void expandNode(const QModelIndex &index); + Q_SLOT void collapseNode(const QModelIndex &index); + Q_SLOT void resetHelper(); + void keyPressEvent(QKeyEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void editItem(const QModelIndex &idx); diff --git a/src/plugins/designer/formeditorplugin.cpp b/src/plugins/designer/formeditorplugin.cpp index 3052c1735855fcd76bc38302eab57c74d2b56546..41970ae5ae5ed88c8e8ce518d35e4ce6d8fde793 100644 --- a/src/plugins/designer/formeditorplugin.cpp +++ b/src/plugins/designer/formeditorplugin.cpp @@ -100,12 +100,7 @@ bool FormEditorPlugin::initialize(const QStringList &arguments, QString *error) m_factory = new FormEditorFactory; addObject(m_factory); - // Make sure settings pages and action shortcuts are registered - // TODO we don't want to do a full initialization here, - // we actually want to call ensureInitStage(FormEditorW::RegisterPlugins) - // But due to a bug in kde 4.2.0 this crashes then when opening the file dialog - // This should be removed after 4.2.1 is out - FormEditorW::ensureInitStage(FormEditorW::FullyInitialized); + FormEditorW::ensureInitStage(FormEditorW::RegisterPlugins); error->clear(); return true; diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 985d4db096d9972d238a455fc3bbf25a382843ec..b42c4d011e1357b8edbe72196fbc53885d41356a 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1512,6 +1512,9 @@ EventResult FakeVimHandler::Private::handleInsertMode(int key, int, if (leftText.simplified().isEmpty()) indentRegion(text.at(0)); } + + if (text.at(0) == '.' || text.at(0) == '>') + emit q->completionRequested(); } else { return EventUnhandled; } diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index d7d978c9d8a90b5c7824f5ecaf79b222bb3d7660..7b5b183cf341af61ddecee3fb43caeb5d98bdfc8 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -77,6 +77,7 @@ signals: const QString &fileName, const QString &contents); void moveToMatchingParenthesis(bool *moved, bool *forward, QTextCursor *cursor); void indentRegion(int *amount, int beginLine, int endLine, QChar typedChar); + void completionRequested(); private: bool eventFilter(QObject *ob, QEvent *ev); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index ee632a1acba1ca83cc1f80359d9256cf1a984aad..8ece7de87249704273db4969c320fb9dc9780d1f 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -116,6 +116,7 @@ private slots: void installHandlerOnCurrentEditor(); void installHandler(Core::IEditor *editor); void removeHandler(); + void triggerCompletions(); void showCommandBuffer(const QString &contents); void showExtraInformation(const QString &msg); @@ -208,6 +209,8 @@ void FakeVimPluginPrivate::installHandler(Core::IEditor *editor) this, SLOT(moveToMatchingParenthesis(bool*,bool*,QTextCursor*))); connect(handler, SIGNAL(indentRegion(int*,int,int,QChar)), this, SLOT(indentRegion(int*,int,int,QChar))); + connect(handler, SIGNAL(completionRequested()), + this, SLOT(triggerCompletions())); handler->setupWidget(); handler->setExtraData(editor); @@ -235,6 +238,15 @@ void FakeVimPluginPrivate::installHandlerOnCurrentEditor() installHandler(EditorManager::instance()->currentEditor()); } +void FakeVimPluginPrivate::triggerCompletions() +{ + FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender()); + if (!handler) + return; + if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(handler->widget())) + bt->triggerCompletions(); +} + void FakeVimPluginPrivate::writeFile(bool *handled, const QString &fileName, const QString &contents) { diff --git a/src/plugins/git/gitsubmiteditor.cpp b/src/plugins/git/gitsubmiteditor.cpp index 1f082e5188db6fe4feb8d2f9c6baa0a9646f1774..4de97513fd37ba7a62a28db7cb782d3be4c97cc5 100644 --- a/src/plugins/git/gitsubmiteditor.cpp +++ b/src/plugins/git/gitsubmiteditor.cpp @@ -35,6 +35,7 @@ #include <vcsbase/submitfilemodel.h> #include <QtCore/QDebug> +#include <QtCore/QStringList> namespace Git { namespace Internal { @@ -121,6 +122,25 @@ void GitSubmitEditor::slotDiffSelected(const QStringList &files) emit diff(unstagedFiles, stagedFiles); } +QString GitSubmitEditor::fileContents() const +{ + // We need to manually purge out comment lines starting with + // hash '#' since git does not do that when using -F. + const QChar newLine = QLatin1Char('\n'); + const QChar hash = QLatin1Char('#'); + QString message = VCSBase::VCSBaseSubmitEditor::fileContents(); + for (int pos = 0; pos < message.size(); ) { + const int newLinePos = message.indexOf(newLine, pos); + const int startOfNextLine = newLinePos == -1 ? message.size() : newLinePos + 1; + if (message.at(pos) == hash) { + message.remove(pos, startOfNextLine - pos); + } else { + pos = startOfNextLine; + } + } + return message; +} + GitSubmitEditorPanelData GitSubmitEditor::panelData() const { return const_cast<GitSubmitEditor*>(this)->submitEditorWidget()->panelData(); diff --git a/src/plugins/git/gitsubmiteditor.h b/src/plugins/git/gitsubmiteditor.h index a2c97e05e2a715f26fd69d3931ec18132e3899b2..88f4dba8e131a4b8e449a4784d1d8a40c56cde47 100644 --- a/src/plugins/git/gitsubmiteditor.h +++ b/src/plugins/git/gitsubmiteditor.h @@ -54,6 +54,8 @@ public: void setCommitData(const CommitData &); GitSubmitEditorPanelData panelData() const; + virtual QString fileContents() const; + signals: void diff(const QStringList &unstagedFiles, const QStringList &stagedFiles); diff --git a/src/plugins/git/gitsubmiteditorwidget.cpp b/src/plugins/git/gitsubmiteditorwidget.cpp index a8749431771de27fdb82bca817a004734bfdf276..4fcbc20722072c18d0b3a68811c5e116fad7ac4b 100644 --- a/src/plugins/git/gitsubmiteditorwidget.cpp +++ b/src/plugins/git/gitsubmiteditorwidget.cpp @@ -30,15 +30,92 @@ #include "gitsubmiteditorwidget.h" #include "commitdata.h" +#include <texteditor/texteditorsettings.h> +#include <texteditor/fontsettings.h> +#include <texteditor/texteditorconstants.h> + +#include <QtGui/QSyntaxHighlighter> +#include <QtGui/QTextEdit> + +#include <QtCore/QDebug> +#include <QtCore/QRegExp> + namespace Git { namespace Internal { +// Retrieve the comment char format from the text editor. +static QTextCharFormat commentFormat() +{ + const TextEditor::FontSettings settings = TextEditor::TextEditorSettings::instance()->fontSettings(); + return settings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_COMMENT)); +} + +// Highlighter for git submit messages. Make the first line bold, indicates +// comments as such (retrieving the format from the text editor) and marks up +// keywords (words in front of a colon as in 'Task: <bla>'). + +class GitSubmitHighlighter : QSyntaxHighlighter { +public: + explicit GitSubmitHighlighter(QTextEdit *parent); + virtual void highlightBlock(const QString &text); + +private: + enum State { Header, Comment, Other }; + const QTextCharFormat m_commentFormat; + const QRegExp m_keywordPattern; + const QChar m_hashChar; +}; + +GitSubmitHighlighter::GitSubmitHighlighter(QTextEdit * parent) : + QSyntaxHighlighter(parent), + m_commentFormat(commentFormat()), + m_keywordPattern(QLatin1String("^\\w+:")), + m_hashChar(QLatin1Char('#')) +{ + Q_ASSERT(m_keywordPattern.isValid()); +} + +void GitSubmitHighlighter::highlightBlock(const QString &text) +{ + // figure out current state + State state = Other; + const QTextBlock block = currentBlock(); + if (block.position() == 0) { + state = Header; + } else { + if (text.startsWith(m_hashChar)) + state = Comment; + } + // Apply format. + switch (state) { + case Header: { + QTextCharFormat charFormat = format(0); + charFormat.setFontWeight(QFont::Bold); + setFormat(0, text.size(), charFormat); + } + break; + case Comment: + setFormat(0, text.size(), m_commentFormat); + break; + case Other: + // Format key words ("Task:") italic + if (m_keywordPattern.indexIn(text, 0, QRegExp::CaretAtZero) == 0) { + QTextCharFormat charFormat = format(0); + charFormat.setFontItalic(true); + setFormat(0, m_keywordPattern.matchedLength(), charFormat); + } + break; + } +} + +// ------------------ GitSubmitEditorWidget::GitSubmitEditorWidget(QWidget *parent) : Core::Utils::SubmitEditorWidget(parent), m_gitSubmitPanel(new QWidget) { m_gitSubmitPanelUi.setupUi(m_gitSubmitPanel); insertTopWidget(m_gitSubmitPanel); + new GitSubmitHighlighter(descriptionEdit()); } void GitSubmitEditorWidget::setPanelInfo(const GitSubmitEditorPanelInfo &info) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 6574d416310a5e2691c92f9c4be52a7be3ba3928..322039c0cbd036c34e365cf16730f82dcfa47eaa 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1255,6 +1255,7 @@ BaseTextEditorPrivate::BaseTextEditorPrivate() m_document(new BaseTextDocument()), m_parenthesesMatchingEnabled(false), m_extraArea(0), + m_mouseOnCollapsedMarker(false), m_marksVisible(false), m_codeFoldingVisible(false), m_codeFoldingSupported(false), @@ -2421,22 +2422,30 @@ void BaseTextEditorPrivate::clearVisibleCollapsedBlock() void BaseTextEditor::mouseMoveEvent(QMouseEvent *e) { d->m_lastEventWasBlockSelectionEvent = (e->modifiers() & Qt::AltModifier); - if (e->buttons() == 0) { - QTextBlock collapsedBlock = collapsedBlockAt(e->pos()); - int blockNumber = collapsedBlock.next().blockNumber(); + if (e->buttons() == Qt::NoButton) { + const QTextBlock collapsedBlock = collapsedBlockAt(e->pos()); + const int blockNumber = collapsedBlock.next().blockNumber(); if (blockNumber < 0) { d->clearVisibleCollapsedBlock(); } else if (blockNumber != d->visibleCollapsedBlockNumber) { d->suggestedVisibleCollapsedBlockNumber = blockNumber; d->collapsedBlockTimer.start(40, this); } - viewport()->setCursor(collapsedBlock.isValid() ? Qt::PointingHandCursor : Qt::IBeamCursor); + + // Update the mouse cursor + if (collapsedBlock.isValid() && !d->m_mouseOnCollapsedMarker) { + d->m_mouseOnCollapsedMarker = true; + viewport()->setCursor(Qt::PointingHandCursor); + } else if (!collapsedBlock.isValid() && d->m_mouseOnCollapsedMarker) { + d->m_mouseOnCollapsedMarker = false; + viewport()->setCursor(Qt::IBeamCursor); + } } else { QPlainTextEdit::mouseMoveEvent(e); } if (d->m_lastEventWasBlockSelectionEvent && d->m_inBlockSelectionMode) { if (textCursor().atBlockEnd()) { - d->m_blockSelectionExtraX = qMax(0, e->pos().x() - cursorRect().center().x()) / fontMetrics().width(QLatin1Char('x')); + d->m_blockSelectionExtraX = qMax(0, e->pos().x() - cursorRect().center().x()) / fontMetrics().averageCharWidth(); } else { d->m_blockSelectionExtraX = 0; } diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index 8c106181349edbde83d0f8c4a82f6dc9aba51633..c3cae63467fa8afb8058f6b5c6544742748eda5c 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -27,7 +27,6 @@ ** **************************************************************************/ - #ifndef BASETEXTEDITOR_H #define BASETEXTEDITOR_H @@ -42,7 +41,6 @@ QT_BEGIN_NAMESPACE class QLabel; -class QTextCharFormat; class QToolBar; QT_END_NAMESPACE diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h index 638f2faba225d217c36cb8a45841b3475e712cc3..d33fa9d7d4c2fdef660fb8967638787d50f2ec17 100644 --- a/src/plugins/texteditor/basetexteditor_p.h +++ b/src/plugins/texteditor/basetexteditor_p.h @@ -175,6 +175,7 @@ public: int visibleCollapsedBlockNumber; int suggestedVisibleCollapsedBlockNumber; void clearVisibleCollapsedBlock(); + bool m_mouseOnCollapsedMarker; QBasicTimer autoScrollTimer; void updateMarksLineNumber(); diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 654bba0d4bcbc96d1ad060285ae80c5ab1d67122..e598a8911484cba9c91c427d7a5c0d35779cd0a6 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -65,6 +65,7 @@ const char * const C_TEXTEDITOR_MIMETYPE_XML = "application/xml"; // Text color and style categories const char * const C_TEXT = "Text"; +const char * const C_LINK = "Link"; const char * const C_SELECTION = "Selection"; const char * const C_LINE_NUMBER = "LineNumber"; const char * const C_SEARCH_RESULT = "SearchResult"; diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index cc55dec6b24c6726a8c1abd655bd36a98d6a394d..31204648a1d2a778f8f94d897348c2caf8c28507 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -65,6 +65,7 @@ TextEditorSettings::TextEditorSettings(QObject *parent) // Special categories const QPalette p = QApplication::palette(); + formatDescriptions.push_back(FormatDescription(QLatin1String(C_LINK), tr("Link"), Qt::blue)); formatDescriptions.push_back(FormatDescription(QLatin1String(C_SELECTION), tr("Selection"), p.color(QPalette::HighlightedText))); formatDescriptions.push_back(FormatDescription(QLatin1String(C_LINE_NUMBER), tr("Line Number"))); formatDescriptions.push_back(FormatDescription(QLatin1String(C_SEARCH_RESULT), tr("Search Result"))); diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp index 62ea9417b825aa869e5ca4afe2a16bbccfd5c68b..2bbcc02c9c0301667771f75465676755b0b18d4d 100644 --- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp +++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp @@ -41,6 +41,8 @@ #include <utils/submiteditorwidget.h> #include <utils/submitfieldwidget.h> #include <find/basetextfind.h> +#include <texteditor/fontsettings.h> +#include <texteditor/texteditorsettings.h> #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> @@ -107,6 +109,13 @@ VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *pa Core::Utils::SubmitEditorWidget *editorWidget) : m_d(new VCSBaseSubmitEditorPrivate(parameters, editorWidget, this)) { + // message font according to settings + const TextEditor::FontSettings fs = TextEditor::TextEditorSettings::instance()->fontSettings(); + QFont font = editorWidget->descriptionEdit()->font(); + font.setFamily(fs.family()); + font.setPointSize((fs.fontSize() * 4) / 5); + editorWidget->descriptionEdit()->setFont(font); + m_d->m_file->setModified(false); // We are always clean to prevent the editor manager from asking to save. connect(m_d->m_file, SIGNAL(saveMe(QString)), this, SLOT(save(QString))); diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 3f3f802506f462246e200d112f832a4ab47a2b27..44d5cd695a499a8d58d5cfd7e1684a3383dbe9e4 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -396,6 +396,7 @@ protected: class CPLUSPLUS_EXPORT SimpleDeclarationAST: public DeclarationAST { public: + unsigned qt_invokable_token; SpecifierAST *decl_specifier_seq; DeclaratorListAST *declarators; unsigned semicolon_token; @@ -1071,6 +1072,7 @@ protected: class CPLUSPLUS_EXPORT FunctionDefinitionAST: public DeclarationAST { public: + unsigned qt_invokable_token; SpecifierAST *decl_specifier_seq; DeclaratorAST *declarator; CtorInitializerAST *ctor_initializer; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 06b85f8c5b19216afc40684be6c25fe448cb2432..c6de2cf4aa0d412e408dcbe08b7c3e6dc8190180 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -154,6 +154,9 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) } } + const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT; + const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL; + List<Declaration *> **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { Name *name = 0; @@ -172,6 +175,10 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) fun->setScope(_scope); fun->setName(name); fun->setMethodKey(semantic()->currentMethodKey()); + if (isQ_SIGNAL) + fun->setMethodKey(Function::SignalMethod); + else if (isQ_SLOT) + fun->setMethodKey(Function::SlotMethod); fun->setVisibility(semantic()->currentVisibility()); } else if (semantic()->currentMethodKey() != Function::NormalMethod) { translationUnit()->warning(ast->firstToken(), @@ -259,6 +266,14 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) fun->setVisibility(semantic()->currentVisibility()); fun->setMethodKey(semantic()->currentMethodKey()); + const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT; + const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL; + + if (isQ_SIGNAL) + fun->setMethodKey(Function::SignalMethod); + else if (isQ_SLOT) + fun->setMethodKey(Function::SlotMethod); + checkFunctionArguments(fun); ast->symbol = fun; diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 28cd42227b8f1d5866907b57cbeeb92ff452eb84..57d3b56961b4c6459f14af3808ac074ba4dad767 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -532,6 +532,19 @@ static inline int classify6(const char *s, bool q) { } } } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'S') { + if (s[3] == 'L') { + if (s[4] == 'O') { + if (s[5] == 'T') { + return T_Q_SLOT; + } + } + } + } + } + } return T_IDENTIFIER; } @@ -850,6 +863,23 @@ static inline int classify8(const char *s, bool) { } } } + else if (s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'S') { + if (s[3] == 'I') { + if (s[4] == 'G') { + if (s[5] == 'N') { + if (s[6] == 'A') { + if (s[7] == 'L') { + return T_Q_SIGNAL; + } + } + } + } + } + } + } + } return T_IDENTIFIER; } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 423a05e05be8352e4ebccc5b24166fbbefc9bfbb..5bae822f350a216577aa935b95706c121ab452d9 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -2381,10 +2381,12 @@ bool Parser::parseBuiltinTypeSpecifier(SpecifierAST *&node) bool Parser::parseSimpleDeclaration(DeclarationAST *&node, bool acceptStructDeclarator) { + unsigned qt_invokable_token = 0; + if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT)) + qt_invokable_token = consumeToken(); + // parse a simple declaration, a function definition, // or a contructor declaration. - cursor(); - bool has_type_specifier = false; bool has_complex_type_specifier = false; unsigned startOfNamedTypeSpecifier = 0; @@ -2498,6 +2500,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, } } SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST; + ast->qt_invokable_token = qt_invokable_token; ast->decl_specifier_seq = decl_specifier_seq; ast->declarators = declarator_list; match(T_SEMICOLON, &ast->semicolon_token); @@ -2510,6 +2513,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, if (LA() == T_LBRACE) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; + ast->qt_invokable_token = qt_invokable_token; ast->decl_specifier_seq = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; @@ -2518,6 +2522,7 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, return true; // recognized a function definition. } else if (LA() == T_TRY) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; + ast->qt_invokable_token = qt_invokable_token; ast->decl_specifier_seq = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index 70d4af8e9a415903dfea398a5ae1582dafcf8e65..0fdb0cee2b625ae2b9e1c8ed8e691ca5f051cc16 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -90,7 +90,7 @@ static const char *token_names[] = { ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), - ("SIGNAL"), ("SLOT"), ("Q_SIGNALS"), ("Q_SLOTS") + ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots") }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 260eaac43d61988294fb48852cc12a98353131bd..69ba4c37826023181a5d32a4128b88edf89132aa 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -232,6 +232,8 @@ enum Kind { // Qt keywords T_SIGNAL = T_FIRST_QT_KEYWORD, T_SLOT, + T_Q_SIGNAL, + T_Q_SLOT, T_SIGNALS, T_SLOTS,