| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Contact: Nokia Corporation (info@qt.nokia.com) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** GNU Lesser General Public License Usage | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** 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.
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** rights. These rights are described in the Nokia Qt LGPL Exception | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Other Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Alternatively, this file may be used in accordance with the terms and | 
					
						
							|  |  |  | ** conditions contained in a signed written agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							| 
									
										
										
										
											2011-05-06 15:05:37 +02:00
										 |  |  | ** Nokia at info@qt.nokia.com. | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "debuggertooltipmanager.h"
 | 
					
						
							|  |  |  | #include "watchutils.h"
 | 
					
						
							|  |  |  | #include "debuggerengine.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | #include "debuggeractions.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | #include "watchhandler.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | #include "watchutils.h"
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | #include "stackhandler.h"
 | 
					
						
							|  |  |  | #include "debuggercore.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <coreplugin/icore.h>
 | 
					
						
							|  |  |  | #include <coreplugin/modemanager.h>
 | 
					
						
							|  |  |  | #include <coreplugin/imode.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | #include <coreplugin/coreconstants.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | #include <coreplugin/editormanager/editormanager.h>
 | 
					
						
							|  |  |  | #include <texteditor/itexteditor.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | #include <texteditor/basetexteditor.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | #include <texteditor/tooltip/tooltip.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | #include <texteditor/tooltip/tipcontents.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <utils/qtcassert.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QtGui/QToolButton>
 | 
					
						
							|  |  |  | #include <QtGui/QToolBar>
 | 
					
						
							|  |  |  | #include <QtGui/QVBoxLayout>
 | 
					
						
							|  |  |  | #include <QtGui/QStyle>
 | 
					
						
							|  |  |  | #include <QtGui/QIcon>
 | 
					
						
							|  |  |  | #include <QtGui/QApplication>
 | 
					
						
							|  |  |  | #include <QtGui/QMainWindow>
 | 
					
						
							|  |  |  | #include <QtGui/QMoveEvent>
 | 
					
						
							|  |  |  | #include <QtGui/QDesktopWidget>
 | 
					
						
							|  |  |  | #include <QtGui/QScrollBar>
 | 
					
						
							|  |  |  | #include <QtGui/QSortFilterProxyModel>
 | 
					
						
							|  |  |  | #include <QtGui/QStandardItemModel>
 | 
					
						
							|  |  |  | #include <QtGui/QStandardItem>
 | 
					
						
							|  |  |  | #include <QtGui/QPlainTextEdit>
 | 
					
						
							|  |  |  | #include <QtGui/QTextCursor>
 | 
					
						
							|  |  |  | #include <QtGui/QTextDocument>
 | 
					
						
							|  |  |  | #include <QtGui/QLabel>
 | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  | #include <QtGui/QClipboard>
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtCore/QVariant>
 | 
					
						
							|  |  |  | #include <QtCore/QStack>
 | 
					
						
							|  |  |  | #include <QtCore/QDebug>
 | 
					
						
							|  |  |  | #include <QtCore/QTimer>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | using namespace Core; | 
					
						
							|  |  |  | using namespace TextEditor; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | enum { debugToolTips = 0 }; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | enum { debugToolTipPositioning = 0 }; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Expire tooltips after n days on (no longer load them) in order
 | 
					
						
							|  |  |  | // to avoid them piling up.
 | 
					
						
							|  |  |  | enum { toolTipsExpiryDays = 6 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char sessionSettingsKeyC[] = "DebuggerToolTips"; | 
					
						
							|  |  |  | static const char sessionDocumentC[] = "DebuggerToolTips"; | 
					
						
							|  |  |  | static const char sessionVersionAttributeC[] = "version"; | 
					
						
							|  |  |  | static const char toolTipElementC[] = "DebuggerToolTip"; | 
					
						
							|  |  |  | static const char toolTipClassAttributeC[] = "class"; | 
					
						
							|  |  |  | static const char fileNameAttributeC[] = "name"; | 
					
						
							|  |  |  | static const char functionAttributeC[] = "function"; | 
					
						
							|  |  |  | static const char textPositionAttributeC[] = "position"; | 
					
						
							|  |  |  | static const char textLineAttributeC[] = "line"; | 
					
						
							|  |  |  | static const char textColumnAttributeC[] = "column"; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | static const char offsetXAttributeC[] = "offset_x"; | 
					
						
							|  |  |  | static const char offsetYAttributeC[] = "offset_y"; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | static const char engineTypeAttributeC[] = "engine"; | 
					
						
							|  |  |  | static const char dateAttributeC[] = "date"; | 
					
						
							|  |  |  | static const char treeElementC[] = "tree"; | 
					
						
							|  |  |  | static const char treeModelAttributeC[] = "model"; // Locals/Watches
 | 
					
						
							|  |  |  | static const char treeExpressionAttributeC[] = "expression"; // Locals/Watches
 | 
					
						
							|  |  |  | static const char modelElementC[] = "model"; | 
					
						
							|  |  |  | static const char modelColumnCountAttributeC[] = "columncount"; | 
					
						
							|  |  |  | static const char modelRowElementC[] = "row"; | 
					
						
							|  |  |  | static const char modelItemElementC[] = "item"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Forward a stream reader across end elements looking for the
 | 
					
						
							|  |  |  | // next start element of a desired type.
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | static bool readStartElement(QXmlStreamReader &r, const char *name) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (debugToolTips > 1) | 
					
						
							|  |  |  |         qDebug("readStartElement: looking for '%s', currently at: %s/%s", | 
					
						
							|  |  |  |                name, qPrintable(r.tokenString()), qPrintable(r.name().toString())); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     while (r.tokenType() != QXmlStreamReader::StartElement | 
					
						
							|  |  |  |             || r.name() != QLatin1String(name)) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         switch (r.readNext()) { | 
					
						
							|  |  |  |         case QXmlStreamReader::EndDocument: | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         case QXmlStreamReader::NoToken: | 
					
						
							|  |  |  |         case QXmlStreamReader::Invalid: | 
					
						
							|  |  |  |             qWarning("'%s'/'%s' encountered while looking for start element '%s'.", | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |                     qPrintable(r.tokenString()), | 
					
						
							|  |  |  |                     qPrintable(r.name().toString()), name); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-23 10:16:11 +01:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | static void debugMode(const QAbstractItemModel *model) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QDebug nospace = qDebug().nospace(); | 
					
						
							|  |  |  |     nospace << model << '\n'; | 
					
						
							|  |  |  |     for (int r = 0; r < model->rowCount(); r++) | 
					
						
							|  |  |  |         nospace << '#' << r << ' ' << model->data(model->index(r, 0)).toString() << '\n'; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-02-23 10:16:11 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | namespace Debugger { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A convenience struct to pass around all tooltip-relevant editor members
 | 
					
						
							|  |  |  | // (TextEditor, Widget, File, etc), constructing from a Core::IEditor.
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | class DebuggerToolTipEditor | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     explicit DebuggerToolTipEditor(IEditor *ie = 0); | 
					
						
							|  |  |  |     bool isValid() const { return textEditor && baseTextEditor && file; } | 
					
						
							|  |  |  |     operator bool() const { return isValid(); } | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     QString fileName() const { return file ? file->fileName() : QString(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static DebuggerToolTipEditor currentToolTipEditor(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     ITextEditor *textEditor; | 
					
						
							|  |  |  |     BaseTextEditorWidget *baseTextEditor; | 
					
						
							|  |  |  |     IFile *file; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | DebuggerToolTipEditor::DebuggerToolTipEditor(IEditor *ie) : | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     textEditor(0), baseTextEditor(0), file(0) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     if (ie && ie->file() && isEditorDebuggable(ie)) { | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         if (ITextEditor *te = qobject_cast<ITextEditor *>(ie)) { | 
					
						
							|  |  |  |             if (BaseTextEditorWidget *pe = qobject_cast<BaseTextEditorWidget *>(ie->widget())) { | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |                 textEditor = te; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                 baseTextEditor = pe; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |                 file = ie->file(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | DebuggerToolTipEditor DebuggerToolTipEditor::currentToolTipEditor() | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     if (IEditor *ie = EditorManager::instance()->currentEditor()) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         return DebuggerToolTipEditor(ie); | 
					
						
							|  |  |  |     return DebuggerToolTipEditor(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Helper for building a QStandardItemModel of a tree form (see TreeModelVisitor).
 | 
					
						
							|  |  |  |  * The recursion/building is based on the scheme: \code | 
					
						
							|  |  |  | <row><item1><item2> | 
					
						
							|  |  |  |     <row><item11><item12></row> | 
					
						
							|  |  |  | </row> | 
					
						
							|  |  |  | \endcode */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | class StandardItemTreeModelBuilder | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | public: | 
					
						
							|  |  |  |     typedef QList<QStandardItem *> StandardItemRow; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     explicit StandardItemTreeModelBuilder(QStandardItemModel *m, Qt::ItemFlags f = Qt::ItemIsSelectable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     void addItem(const QString &); | 
					
						
							|  |  |  |     void startRow(); | 
					
						
							|  |  |  |     void endRow(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     void pushRow(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QStandardItemModel *m_model; | 
					
						
							|  |  |  |     const Qt::ItemFlags m_flags; | 
					
						
							|  |  |  |     StandardItemRow m_row; | 
					
						
							|  |  |  |     QStack<QStandardItem *> m_rowParents; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StandardItemTreeModelBuilder::StandardItemTreeModelBuilder(QStandardItemModel *m, Qt::ItemFlags f) : | 
					
						
							|  |  |  |     m_model(m), m_flags(f) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_model->removeRows(0, m_model->rowCount()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandardItemTreeModelBuilder::addItem(const QString &s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QStandardItem *item = new QStandardItem(s); | 
					
						
							|  |  |  |     item->setFlags(m_flags); | 
					
						
							|  |  |  |     m_row.push_back(item); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandardItemTreeModelBuilder::pushRow() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_rowParents.isEmpty()) { | 
					
						
							|  |  |  |         m_model->appendRow(m_row); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_rowParents.top()->appendRow(m_row); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_rowParents.push(m_row.front()); | 
					
						
							|  |  |  |     m_row.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandardItemTreeModelBuilder::startRow() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Push parent in case rows are nested. This is a Noop for the very first row.
 | 
					
						
							|  |  |  |     if (!m_row.isEmpty()) | 
					
						
							|  |  |  |         pushRow(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandardItemTreeModelBuilder::endRow() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_row.isEmpty()) // Push row if no child rows have been encountered
 | 
					
						
							|  |  |  |         pushRow(); | 
					
						
							|  |  |  |     m_rowParents.pop(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Helper visitor base class for recursing over a tree model
 | 
					
						
							|  |  |  |  * (see StandardItemTreeModelBuilder for the scheme). */ | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | class TreeModelVisitor | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     virtual void run() { run(QModelIndex()); } | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     TreeModelVisitor(const QAbstractItemModel *model) : m_model(model) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void rowStarted() {} | 
					
						
							|  |  |  |     virtual void handleItem(const QModelIndex &m) = 0; | 
					
						
							|  |  |  |     virtual void rowEnded() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QAbstractItemModel *model() const { return m_model; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     void run(const QModelIndex &parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QAbstractItemModel *m_model; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TreeModelVisitor::run(const QModelIndex &parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const int columnCount = m_model->columnCount(parent); | 
					
						
							|  |  |  |     const int rowCount = m_model->rowCount(parent); | 
					
						
							|  |  |  |     for (int r = 0; r < rowCount; r++) { | 
					
						
							|  |  |  |         rowStarted(); | 
					
						
							|  |  |  |         QModelIndex left; | 
					
						
							|  |  |  |         for (int c = 0; c < columnCount; c++) { | 
					
						
							|  |  |  |             const QModelIndex index = m_model->index(r, c, parent); | 
					
						
							|  |  |  |             handleItem(index); | 
					
						
							|  |  |  |             if (!c) | 
					
						
							|  |  |  |                 left = index; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (left.isValid()) | 
					
						
							|  |  |  |             run(left); | 
					
						
							|  |  |  |         rowEnded(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Visitor writing out a tree model in XML format.
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | class XmlWriterTreeModelVisitor : public TreeModelVisitor | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     XmlWriterTreeModelVisitor(const QAbstractItemModel *model, QXmlStreamWriter &w); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void run(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual void rowStarted() { m_writer.writeStartElement(QLatin1String(modelRowElementC)); } | 
					
						
							|  |  |  |     virtual void handleItem(const QModelIndex &m); | 
					
						
							|  |  |  |     virtual void rowEnded() { m_writer.writeEndElement(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     const QString m_modelItemElement; | 
					
						
							|  |  |  |     QXmlStreamWriter &m_writer; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | XmlWriterTreeModelVisitor::XmlWriterTreeModelVisitor(const QAbstractItemModel *model, QXmlStreamWriter &w) : | 
					
						
							|  |  |  |     TreeModelVisitor(model), m_modelItemElement(QLatin1String(modelItemElementC)), m_writer(w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void XmlWriterTreeModelVisitor::run() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_writer.writeStartElement(QLatin1String(modelElementC)); | 
					
						
							|  |  |  |     const int columnCount = model()->columnCount(); | 
					
						
							|  |  |  |     m_writer.writeAttribute(QLatin1String(modelColumnCountAttributeC), QString::number(columnCount)); | 
					
						
							|  |  |  |    TreeModelVisitor::run(); | 
					
						
							|  |  |  |     m_writer.writeEndElement(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void XmlWriterTreeModelVisitor::handleItem(const QModelIndex &m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QString value = m.data(Qt::DisplayRole).toString(); | 
					
						
							|  |  |  |     if (value.isEmpty()) { | 
					
						
							|  |  |  |         m_writer.writeEmptyElement(m_modelItemElement); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         m_writer.writeTextElement(m_modelItemElement, value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  | // TreeModelVisitor for debugging/copying models
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | class DumpTreeModelVisitor : public TreeModelVisitor | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     enum Mode | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         DebugMode,      // For debugging, "|'data'|"
 | 
					
						
							|  |  |  |         ClipboardMode   // Tab-delimited "\tdata" for clipboard (see stack window)
 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     explicit DumpTreeModelVisitor(const QAbstractItemModel *model, Mode m, QTextStream &s); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual void rowStarted(); | 
					
						
							|  |  |  |     virtual void handleItem(const QModelIndex &m); | 
					
						
							|  |  |  |     virtual void rowEnded(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     const Mode m_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     QTextStream &m_stream; | 
					
						
							|  |  |  |     int m_level; | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     unsigned m_itemsInRow; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  | DumpTreeModelVisitor::DumpTreeModelVisitor(const QAbstractItemModel *model, Mode m, QTextStream &s) : | 
					
						
							|  |  |  |     TreeModelVisitor(model), m_mode(m), m_stream(s), m_level(0), m_itemsInRow(0) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     if (m_mode == DebugMode) | 
					
						
							|  |  |  |         m_stream << model->metaObject()->className() << '/' << model->objectName(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DumpTreeModelVisitor::rowStarted() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_level++; | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     if (m_itemsInRow) { // Nested row.
 | 
					
						
							|  |  |  |         m_stream << '\n'; | 
					
						
							|  |  |  |         m_itemsInRow = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     switch (m_mode) { | 
					
						
							|  |  |  |     case DebugMode: | 
					
						
							|  |  |  |         m_stream << QString(2 * m_level, QLatin1Char(' ')); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case ClipboardMode: | 
					
						
							|  |  |  |         m_stream << QString(m_level, QLatin1Char('\t')); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DumpTreeModelVisitor::handleItem(const QModelIndex &m) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     const QString data = m.data().toString(); | 
					
						
							|  |  |  |     switch (m_mode) { | 
					
						
							|  |  |  |     case DebugMode: | 
					
						
							|  |  |  |         if (m.column()) | 
					
						
							|  |  |  |             m_stream << '|'; | 
					
						
							|  |  |  |         m_stream << '\'' << data << '\''; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case ClipboardMode: | 
					
						
							|  |  |  |         if (m.column()) | 
					
						
							|  |  |  |             m_stream << '\t'; | 
					
						
							|  |  |  |         m_stream << data; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_itemsInRow++; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DumpTreeModelVisitor::rowEnded() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     if (m_itemsInRow) { | 
					
						
							|  |  |  |         m_stream << '\n'; | 
					
						
							|  |  |  |         m_itemsInRow = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     m_level--; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace Debugger
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  | static QDebug operator<<(QDebug d, const QAbstractItemModel &model) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QString s; | 
					
						
							|  |  |  |     QTextStream str(&s); | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  |     Debugger::Internal::DumpTreeModelVisitor v(&model, Debugger::Internal::DumpTreeModelVisitor::DebugMode, str); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     v.run(); | 
					
						
							|  |  |  |     qDebug().nospace() << s; | 
					
						
							|  |  |  |     return d; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Debugger { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Visitor building a QStandardItem from a tree model (copy).
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | class TreeModelCopyVisitor : public TreeModelVisitor | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     TreeModelCopyVisitor(const QAbstractItemModel *source, QStandardItemModel *target) : | 
					
						
							|  |  |  |         TreeModelVisitor(source), m_builder(target) | 
					
						
							|  |  |  |     {} | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual void rowStarted() { m_builder.startRow(); } | 
					
						
							|  |  |  |     virtual void handleItem(const QModelIndex &m) { m_builder.addItem(m.data().toString()); } | 
					
						
							|  |  |  |     virtual void rowEnded() { m_builder.endRow(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     StandardItemTreeModelBuilder m_builder; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::PinnableToolTipWidget | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     A pinnable tooltip that goes from State 'Unpinned' (button showing | 
					
						
							|  |  |  |     'Pin') to 'Pinned' (button showing 'Close'). | 
					
						
							|  |  |  |     It consists of a title toolbar and a vertical main layout. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PinnableToolTipWidget::PinnableToolTipWidget(QWidget *parent) : | 
					
						
							|  |  |  |     QWidget(parent), | 
					
						
							|  |  |  |     m_pinState(Unpinned), | 
					
						
							|  |  |  |     m_mainVBoxLayout(new QVBoxLayout), | 
					
						
							|  |  |  |     m_toolBar(new QToolBar), | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     m_toolButton(new QToolButton) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     m_mainVBoxLayout->setSizeConstraint(QLayout::SetFixedSize); | 
					
						
							|  |  |  |     m_mainVBoxLayout->setContentsMargins(0, 0, 0, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QIcon pinIcon(QLatin1String(":/debugger/images/pin.xpm")); | 
					
						
							|  |  |  |     const QList<QSize> pinIconSizes = pinIcon.availableSizes(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_toolButton->setIcon(pinIcon); | 
					
						
							|  |  |  |     connect(m_toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_toolBar->setProperty("_q_custom_style_disabled", QVariant(true)); | 
					
						
							|  |  |  |     if (!pinIconSizes.isEmpty()) | 
					
						
							|  |  |  |         m_toolBar->setIconSize(pinIconSizes.front()); | 
					
						
							|  |  |  |     m_toolBar->addWidget(m_toolButton); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_mainVBoxLayout->addWidget(m_toolBar); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLayout(m_mainVBoxLayout); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PinnableToolTipWidget::addWidget(QWidget *w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     w->setFocusPolicy(Qt::NoFocus); | 
					
						
							|  |  |  |     m_mainVBoxLayout->addWidget(w); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PinnableToolTipWidget::addToolBarWidget(QWidget *w) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_toolBar->addWidget(w); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PinnableToolTipWidget::pin() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_pinState == Unpinned) { | 
					
						
							|  |  |  |         m_pinState = Pinned; | 
					
						
							|  |  |  |         m_toolButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         doPin(); | 
					
						
							|  |  |  |         emit pinned(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | void PinnableToolTipWidget::doPin() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | void PinnableToolTipWidget::toolButtonClicked() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (m_pinState) { | 
					
						
							|  |  |  |     case Unpinned: | 
					
						
							|  |  |  |         pin(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Pinned: | 
					
						
							|  |  |  |         close(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | /* A Label that emits a signal when the user drags for moving the parent
 | 
					
						
							|  |  |  |  * widget around. */ | 
					
						
							|  |  |  | class DraggableLabel : public QLabel | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Q_OBJECT | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     explicit DraggableLabel(QWidget *parent = 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     bool isActive() const { return m_active; } | 
					
						
							|  |  |  |     void setActive(bool v) { m_active = v; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | signals: | 
					
						
							|  |  |  |     void dragged(const QPoint &d); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual void mousePressEvent(QMouseEvent * event); | 
					
						
							|  |  |  |     virtual void mouseReleaseEvent(QMouseEvent * event); | 
					
						
							|  |  |  |     virtual void mouseMoveEvent(QMouseEvent * event); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QPoint m_moveStartPos; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     bool m_active; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DraggableLabel::DraggableLabel(QWidget *parent) : | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     QLabel(parent), m_moveStartPos(-1, -1), m_active(false) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DraggableLabel::mousePressEvent(QMouseEvent * event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (m_active && event->button() ==  Qt::LeftButton) { | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         m_moveStartPos = event->globalPos(); | 
					
						
							|  |  |  |         event->accept(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QLabel::mousePressEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DraggableLabel::mouseReleaseEvent(QMouseEvent * event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (m_active && event->button() ==  Qt::LeftButton) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         m_moveStartPos = QPoint(-1, -1); | 
					
						
							|  |  |  |     QLabel::mouseReleaseEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DraggableLabel::mouseMoveEvent(QMouseEvent * event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (m_active && (event->buttons() & Qt::LeftButton)) { | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         if (m_moveStartPos != QPoint(-1, -1)) { | 
					
						
							|  |  |  |             const QPoint newPos = event->globalPos(); | 
					
						
							|  |  |  |             emit dragged(event->globalPos() - m_moveStartPos); | 
					
						
							|  |  |  |             m_moveStartPos = newPos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         event->accept(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     QLabel::mouseMoveEvent(event); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::DebuggerToolTipContext | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     File name and position where the tooltip is anchored. Redundant position/line column | 
					
						
							|  |  |  |     information is used to detect if the underlying file has been changed | 
					
						
							|  |  |  |     on restoring. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipContext::DebuggerToolTipContext() : position(0), line(0), column(0) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | DebuggerToolTipContext DebuggerToolTipContext::fromEditor(IEditor *ie, int pos) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     DebuggerToolTipContext rc; | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     if (const IFile *file = ie->file()) { | 
					
						
							|  |  |  |         if (const ITextEditor *te = qobject_cast<const ITextEditor *>(ie)) { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             rc.fileName = file->fileName(); | 
					
						
							|  |  |  |             rc.position = pos; | 
					
						
							|  |  |  |             te->convertPosition(pos, &rc.line, &rc.column); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDebug operator<<(QDebug d, const DebuggerToolTipContext &c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDebug nsp = d.nospace(); | 
					
						
							|  |  |  |     nsp << c.fileName << '@' << c.line << ',' << c.column << " (" << c.position << ')'; | 
					
						
							|  |  |  |     if (!c.function.isEmpty()) | 
					
						
							|  |  |  |         nsp << ' ' << c.function << "()"; | 
					
						
							|  |  |  |     return d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::AbstractDebuggerToolTipWidget | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Base class for a tool tip widget associated with file name | 
					
						
							|  |  |  |     and position with functionality to | 
					
						
							|  |  |  |     \list | 
					
						
							|  |  |  |     \o Save and restore values (session data) in XML form | 
					
						
							|  |  |  |     \o Acquire and release the engine: When the debugger stops at a file, all | 
					
						
							|  |  |  |        matching tooltips acquire the engine, that is, display the engine data. | 
					
						
							|  |  |  |        When continuing or switching away from the frame, the tooltips release the | 
					
						
							|  |  |  |        engine, that is, store the data internally and keep displaying them | 
					
						
							|  |  |  |        marked as 'previous'. | 
					
						
							|  |  |  |     \endlist | 
					
						
							|  |  |  |     When restoring the data from a session, all tooltips start in 'released' mode. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Stored tooltips expire after toolTipsExpiryDays while loading to prevent | 
					
						
							|  |  |  |     them accumulating. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In addition, if the stored line number diverges too much from the current line | 
					
						
							|  |  |  |     number in positionShow(), the tooltip is also closed/discarded. | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The widget is that is first shown by the TextEditor's tooltip | 
					
						
							|  |  |  |     class and typically closed by it unless the user pins it. | 
					
						
							|  |  |  |     In that case, it is removed from the tip's layout, added to the DebuggerToolTipManager's | 
					
						
							|  |  |  |     list of pinned tooltips and re-shown as a global tooltip widget. | 
					
						
							|  |  |  |     As the debugger stop and continues, it shows the debugger values or a copy | 
					
						
							|  |  |  |     of them. On closing or session changes, the contents it saved. | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | static QString msgReleasedText() { return AbstractDebuggerToolTipWidget::tr("Previous"); } | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | AbstractDebuggerToolTipWidget::AbstractDebuggerToolTipWidget(QWidget *parent) : | 
					
						
							|  |  |  |     PinnableToolTipWidget(parent), | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |     m_titleLabel(new DraggableLabel), m_engineAcquired(false), | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     m_creationDate(QDate::currentDate()) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     QToolButton *copyButton = new QToolButton; | 
					
						
							|  |  |  |     copyButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_COPY))); | 
					
						
							|  |  |  |     connect(copyButton, SIGNAL(clicked()), this, SLOT(copy())); | 
					
						
							|  |  |  |     addToolBarWidget(copyButton); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     m_titleLabel->setText(msgReleasedText()); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |     m_titleLabel->setMinimumWidth(40); // Ensure a draggable area even if text is empty.
 | 
					
						
							|  |  |  |     connect(m_titleLabel, SIGNAL(dragged(QPoint)), this, SLOT(slotDragged(QPoint))); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     addToolBarWidget(m_titleLabel); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AbstractDebuggerToolTipWidget::matches(const QString &fileName, | 
					
						
							|  |  |  |                                             const QString &engineType, | 
					
						
							|  |  |  |                                             const QString &function) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (fileName.isEmpty() || m_context.fileName != fileName) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     // Optional.
 | 
					
						
							|  |  |  |     if (!engineType.isEmpty() && engineType != m_engineType) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     if (function.isEmpty() || m_context.function.isEmpty()) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     return function == m_context.function; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AbstractDebuggerToolTipWidget::acquireEngine(Debugger::DebuggerEngine *engine) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(engine, return); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << this << " acquiring" << engine << m_engineAcquired; | 
					
						
							|  |  |  |     if (m_engineAcquired) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     doAcquireEngine(engine); | 
					
						
							|  |  |  |     m_engineType = engine->objectName(); | 
					
						
							|  |  |  |     m_engineAcquired = true; | 
					
						
							|  |  |  |     m_titleLabel->setText(QString()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AbstractDebuggerToolTipWidget::releaseEngine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Release engine of same type
 | 
					
						
							|  |  |  |     if (!m_engineAcquired) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "releaseEngine" << this; | 
					
						
							|  |  |  |     doReleaseEngine(); | 
					
						
							|  |  |  |     m_titleLabel->setText(msgReleasedText()); | 
					
						
							|  |  |  |     m_engineAcquired = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  | void AbstractDebuggerToolTipWidget::copy() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QString clipboardText = clipboardContents(); | 
					
						
							|  |  |  |     QClipboard *clipboard = QApplication::clipboard(); | 
					
						
							|  |  |  | #ifdef Q_WS_X11
 | 
					
						
							|  |  |  |     clipboard->setText(clipboardText, QClipboard::Selection); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     clipboard->setText(clipboardText, QClipboard::Clipboard); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | void AbstractDebuggerToolTipWidget::slotDragged(const QPoint &p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     move(pos() + p); | 
					
						
							|  |  |  |     m_offset += p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | bool AbstractDebuggerToolTipWidget::positionShow(const DebuggerToolTipEditor &te) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // Figure out new position of tooltip using the text edit.
 | 
					
						
							|  |  |  |     // If the line changed too much, close this tip.
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(te, return false); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     QTextCursor cursor(te.baseTextEditor->document()); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     cursor.setPosition(m_context.position); | 
					
						
							|  |  |  |     const int line = cursor.blockNumber(); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     const int column = cursor.columnNumber(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     if (qAbs(m_context.line - line) > 2) { | 
					
						
							|  |  |  |         if (debugToolTips) | 
					
						
							|  |  |  |             qDebug() << "Closing " << this << " in positionShow() lines " | 
					
						
							|  |  |  |                      << line << m_context.line; | 
					
						
							|  |  |  |         close(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (debugToolTipPositioning) | 
					
						
							|  |  |  |         qDebug() << "positionShow" << this << line << column; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QPoint screenPos = te.baseTextEditor->toolTipPosition(cursor) + m_offset; | 
					
						
							|  |  |  |     const QRect toolTipArea = QRect(screenPos, QSize(sizeHint())); | 
					
						
							|  |  |  |     const QRect plainTextArea = QRect(te.baseTextEditor->mapToGlobal(QPoint(0, 0)), te.baseTextEditor->size()); | 
					
						
							|  |  |  |     const bool visible = plainTextArea.contains(toolTipArea); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     if (debugToolTips) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         qDebug() << "DebuggerToolTipWidget::positionShow() " << this << m_context | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                  << " line: " << line << " plainTextPos " << toolTipArea | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |                  << " offset: " << m_offset | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |                  << " Area: " << plainTextArea << " Screen pos: " | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                  << screenPos << te.baseTextEditor << " visible=" << visible; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     if (!visible) { | 
					
						
							|  |  |  |         hide(); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     move(screenPos); | 
					
						
							|  |  |  |     show(); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | void AbstractDebuggerToolTipWidget::doPin() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (parentWidget()) { | 
					
						
							|  |  |  |         // We are currently within a text editor tooltip:
 | 
					
						
							|  |  |  |         // Rip out of parent widget and re-show as a tooltip
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         WidgetContent::pinToolTip(this); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         // We have just be restored from session data.
 | 
					
						
							|  |  |  |         setWindowFlags(Qt::ToolTip); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_titleLabel->setActive(true); // User can now drag
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |  // Parse a 'yyyyMMdd' date
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | static QDate dateFromString(const QString &date) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return date.size() == 8 ? | 
					
						
							|  |  |  |         QDate(date.left(4).toInt(), date.mid(4, 2).toInt(), date.mid(6, 2).toInt()) : | 
					
						
							|  |  |  |         QDate(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AbstractDebuggerToolTipWidget *AbstractDebuggerToolTipWidget::loadSessionData(QXmlStreamReader &r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << ">DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name(); | 
					
						
							|  |  |  |     AbstractDebuggerToolTipWidget *rc = AbstractDebuggerToolTipWidget::loadSessionDataI(r); | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "<DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name() << " returns  " << rc; | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AbstractDebuggerToolTipWidget *AbstractDebuggerToolTipWidget::loadSessionDataI(QXmlStreamReader &r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!readStartElement(r, toolTipElementC)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     const QXmlStreamAttributes attributes = r.attributes(); | 
					
						
							|  |  |  |     DebuggerToolTipContext context; | 
					
						
							|  |  |  |     context.fileName = attributes.value(QLatin1String(fileNameAttributeC)).toString(); | 
					
						
							|  |  |  |     context.position = attributes.value(QLatin1String(textPositionAttributeC)).toString().toInt(); | 
					
						
							|  |  |  |     context.line = attributes.value(QLatin1String(textLineAttributeC)).toString().toInt(); | 
					
						
							|  |  |  |     context.column = attributes.value(QLatin1String(textColumnAttributeC)).toString().toInt(); | 
					
						
							|  |  |  |     context.function = attributes.value(QLatin1String(functionAttributeC)).toString(); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |     QPoint offset; | 
					
						
							|  |  |  |     const QString offsetXAttribute = QLatin1String(offsetXAttributeC); | 
					
						
							|  |  |  |     const QString offsetYAttribute = QLatin1String(offsetYAttributeC); | 
					
						
							|  |  |  |     if (attributes.hasAttribute(offsetXAttribute)) | 
					
						
							|  |  |  |         offset.setX(attributes.value(offsetXAttribute).toString().toInt()); | 
					
						
							|  |  |  |     if (attributes.hasAttribute(offsetYAttribute)) | 
					
						
							|  |  |  |         offset.setY(attributes.value(offsetYAttribute).toString().toInt()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     const QString className = attributes.value(QLatin1String(toolTipClassAttributeC)).toString(); | 
					
						
							|  |  |  |     const QString engineType = attributes.value(QLatin1String(engineTypeAttributeC)).toString(); | 
					
						
							|  |  |  |     const QDate creationDate = dateFromString(attributes.value(QLatin1String(dateAttributeC)).toString()); | 
					
						
							|  |  |  |     if (!creationDate.isValid() || creationDate.daysTo(QDate::currentDate()) >  toolTipsExpiryDays) { | 
					
						
							|  |  |  |         if (debugToolTips) | 
					
						
							|  |  |  |             qDebug() << "Expiring tooltip " << context.fileName << '@' << context.position << " from " << creationDate; | 
					
						
							|  |  |  |         r.readElementText(QXmlStreamReader::SkipChildElements); // Skip
 | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         qDebug() << "Creating tooltip " << context <<  " from " << creationDate << offset; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     AbstractDebuggerToolTipWidget *rc = 0; | 
					
						
							|  |  |  |     if (className == "Debugger::Internal::DebuggerTreeViewToolTipWidget") | 
					
						
							|  |  |  |         rc = new DebuggerTreeViewToolTipWidget; | 
					
						
							|  |  |  |     if (rc) { | 
					
						
							|  |  |  |         rc->setContext(context); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         rc->setAttribute(Qt::WA_DeleteOnClose); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         rc->setEngineType(engineType); | 
					
						
							|  |  |  |         rc->doLoadSessionData(r); | 
					
						
							|  |  |  |         rc->setCreationDate(creationDate); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |         if (!offset.isNull()) | 
					
						
							|  |  |  |             rc->setOffset(offset); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         rc->pin(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         qWarning("Unable to create debugger tool tip widget of class %s", qPrintable(className)); | 
					
						
							|  |  |  |         r.readElementText(QXmlStreamReader::SkipChildElements); // Skip
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AbstractDebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     w.writeStartElement(QLatin1String(toolTipElementC)); | 
					
						
							|  |  |  |     QXmlStreamAttributes attributes; | 
					
						
							|  |  |  |     attributes.append(QLatin1String(toolTipClassAttributeC), QString::fromAscii(metaObject()->className())); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(fileNameAttributeC), m_context.fileName); | 
					
						
							|  |  |  |     if (!m_context.function.isEmpty()) | 
					
						
							|  |  |  |         attributes.append(QLatin1String(functionAttributeC), m_context.function); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(textPositionAttributeC), QString::number(m_context.position)); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(textLineAttributeC), QString::number(m_context.line)); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(textColumnAttributeC), QString::number(m_context.column)); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(dateAttributeC), m_creationDate.toString(QLatin1String("yyyyMMdd"))); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  |     if (m_offset.x()) | 
					
						
							|  |  |  |         attributes.append(QLatin1String(offsetXAttributeC), QString::number(m_offset.x())); | 
					
						
							|  |  |  |     if (m_offset.y()) | 
					
						
							|  |  |  |         attributes.append(QLatin1String(offsetYAttributeC), QString::number(m_offset.y())); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     if (!m_engineType.isEmpty()) | 
					
						
							|  |  |  |         attributes.append(QLatin1String(engineTypeAttributeC), m_engineType); | 
					
						
							|  |  |  |     w.writeAttributes(attributes); | 
					
						
							|  |  |  |     doSaveSessionData(w); | 
					
						
							|  |  |  |     w.writeEndElement(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |     \class Debugger::Internal::DebuggerToolTipExpressionFilterModel | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     \brief Model for tooltips filtering a local variable using the locals or tooltip model, | 
					
						
							|  |  |  |     matching on the name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Expressions/names can either be flat ('foo' will match at the root level) | 
					
						
							|  |  |  |     or nested ('this.m_foo' will match 'this' at root level and 'm_foo' at level 1). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | class DebuggerToolTipExpressionFilterModel : public QSortFilterProxyModel | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     explicit DebuggerToolTipExpressionFilterModel(QAbstractItemModel *model, const QString &exp, QObject *parent = 0); | 
					
						
							|  |  |  |     virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     const QStringList m_expressions; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipExpressionFilterModel::DebuggerToolTipExpressionFilterModel(QAbstractItemModel *model, | 
					
						
							|  |  |  |                                                                            const QString &exp, | 
					
						
							|  |  |  |                                                                            QObject *parent) : | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     QSortFilterProxyModel(parent), | 
					
						
							|  |  |  |     m_expressions(exp.split(QLatin1Char('.'))) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     setSourceModel(model); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | QVariant DebuggerToolTipExpressionFilterModel::data(const QModelIndex &index, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return role != Qt::ToolTipRole ? | 
					
						
							|  |  |  |         QSortFilterProxyModel::data(index, role) : QVariant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  | // Return depth of a model index, that is, 0 for root index, 1 for level-1 children, etc.
 | 
					
						
							|  |  |  | static inline int indexDepth(QModelIndex index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int depth = 0; | 
					
						
							|  |  |  |     for ( ; index.isValid() ; index = index.parent()) | 
					
						
							|  |  |  |         depth++; | 
					
						
							|  |  |  |     return depth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | bool DebuggerToolTipExpressionFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Match on expression for top level, else pass through.
 | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     const int depth = indexDepth(sourceParent); | 
					
						
							|  |  |  |     if (depth >= m_expressions.size()) // No filters at this level
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent); | 
					
						
							|  |  |  |     return nameIndex.data().toString() == m_expressions.at(depth); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::DebuggerToolTipTreeView | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     A treeview that adapts its size to the model contents (also while expanding) | 
					
						
							|  |  |  |     to be used within DebuggerTreeViewToolTipWidget. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipTreeView::DebuggerToolTipTreeView(QWidget *parent) : | 
					
						
							|  |  |  |     QTreeView(parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     setHeaderHidden(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setUniformRowHeights(true); | 
					
						
							|  |  |  |     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  |     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(computeSize()), | 
					
						
							|  |  |  |         Qt::QueuedConnection); | 
					
						
							|  |  |  |     connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(computeSize()), | 
					
						
							|  |  |  |         Qt::QueuedConnection); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAbstractItemModel *DebuggerToolTipTreeView::swapModel(QAbstractItemModel *newModel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAbstractItemModel *previousModel = model(); | 
					
						
							|  |  |  |     if (previousModel != newModel) { | 
					
						
							|  |  |  |         if (previousModel) | 
					
						
							|  |  |  |             previousModel->disconnect(SIGNAL(rowsInserted(QModelIndex,int,int)), this); | 
					
						
							|  |  |  |         setModel(newModel); | 
					
						
							|  |  |  |         connect(newModel, SIGNAL(rowsInserted(QModelIndex,int,int)), | 
					
						
							|  |  |  |                 this, SLOT(computeSize()), Qt::QueuedConnection); | 
					
						
							|  |  |  |         computeSize(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return previousModel; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int DebuggerToolTipTreeView::computeHeight(const QModelIndex &index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int s = rowHeight(index); | 
					
						
							|  |  |  |     const int rowCount = model()->rowCount(index); | 
					
						
							|  |  |  |     for (int i = 0; i < rowCount; ++i) | 
					
						
							|  |  |  |         s += computeHeight(model()->index(i, 0, index)); | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipTreeView::computeSize() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int columns = 30; // Decoration
 | 
					
						
							|  |  |  |     int rows = 0; | 
					
						
							|  |  |  |     bool rootDecorated = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (model()) { | 
					
						
							|  |  |  |         const int columnCount = model()->columnCount(); | 
					
						
							|  |  |  |         rootDecorated = model()->rowCount() > 0; | 
					
						
							|  |  |  |         if (rootDecorated) | 
					
						
							|  |  |  |         for (int i = 0; i < columnCount; ++i) { | 
					
						
							|  |  |  |             resizeColumnToContents(i); | 
					
						
							|  |  |  |             columns += sizeHintForColumn(i); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (columns < 100) | 
					
						
							|  |  |  |             columns = 100; // Prevent toolbar from shrinking when displaying 'Previous'
 | 
					
						
							|  |  |  |         rows += computeHeight(QModelIndex()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Fit tooltip to screen, showing/hiding scrollbars as needed.
 | 
					
						
							|  |  |  |         // Add a bit of space to account for tooltip border, and not
 | 
					
						
							|  |  |  |         // touch the border of the screen.
 | 
					
						
							|  |  |  |         QPoint pos(x(), y()); | 
					
						
							|  |  |  |         QRect desktopRect = QApplication::desktop()->availableGeometry(pos); | 
					
						
							|  |  |  |         const int maxWidth = desktopRect.right() - pos.x() - 5 - 5; | 
					
						
							|  |  |  |         const int maxHeight = desktopRect.bottom() - pos.y() - 5 - 5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (columns > maxWidth) | 
					
						
							|  |  |  |             rows += horizontalScrollBar()->height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (rows > maxHeight) { | 
					
						
							|  |  |  |             setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | 
					
						
							|  |  |  |             rows = maxHeight; | 
					
						
							|  |  |  |             columns += verticalScrollBar()->width(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (columns > maxWidth) { | 
					
						
							|  |  |  |             setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | 
					
						
							|  |  |  |             columns = maxWidth; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_size = QSize(columns + 5, rows + 5); | 
					
						
							|  |  |  |     setMinimumSize(m_size); | 
					
						
							|  |  |  |     setMaximumSize(m_size); | 
					
						
							|  |  |  |     setRootIsDecorated(rootDecorated); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::DebuggerTreeViewToolTipWidget | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Tool tip widget for tree views with functionality to save/restore tree | 
					
						
							|  |  |  |     model contents to XML. | 
					
						
							|  |  |  |     With the engine acquired, it sets a filter model (by expression) on | 
					
						
							|  |  |  |     one of the engine's models (debuggerModel). | 
					
						
							|  |  |  |     On release, it serializes and restores the data to a QStandardItemModel | 
					
						
							|  |  |  |     (defaultModel) and displays that. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerTreeViewToolTipWidget::DebuggerTreeViewToolTipWidget(QWidget *parent) : | 
					
						
							|  |  |  |     AbstractDebuggerToolTipWidget(parent), | 
					
						
							|  |  |  |     m_debuggerModel(TooltipsWatch), | 
					
						
							|  |  |  |     m_treeView(new DebuggerToolTipTreeView), | 
					
						
							|  |  |  |     m_defaultModel(new QStandardItemModel(this)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     addWidget(m_treeView); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerTreeViewToolTipWidget::doAcquireEngine(Debugger::DebuggerEngine *engine) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Create a filter model on the debugger's model and switch to it.
 | 
					
						
							|  |  |  |     QAbstractItemModel *model = 0; | 
					
						
							|  |  |  |     switch (m_debuggerModel) { | 
					
						
							|  |  |  |     case LocalsWatch: | 
					
						
							|  |  |  |         model = engine->localsModel(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case WatchersWatch: | 
					
						
							|  |  |  |         model = engine->watchersModel(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case TooltipsWatch: | 
					
						
							|  |  |  |         model = engine->toolTipsModel(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(model, return); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     DebuggerToolTipExpressionFilterModel *filterModel = | 
					
						
							|  |  |  |             new DebuggerToolTipExpressionFilterModel(model, m_expression); | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     swapModel(filterModel); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QAbstractItemModel *DebuggerTreeViewToolTipWidget::swapModel(QAbstractItemModel *newModel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QAbstractItemModel *oldModel = m_treeView->swapModel(newModel); | 
					
						
							|  |  |  |     // When looking at some 'this.m_foo.x', expand all items
 | 
					
						
							|  |  |  |     if (newModel) { | 
					
						
							|  |  |  |         if (const int level = m_expression.count(QLatin1Char('.'))) { | 
					
						
							|  |  |  |             QModelIndex index = newModel->index(0, 0); | 
					
						
							|  |  |  |             for (int i = 0; i < level && index.isValid(); i++, index = index.child(0, 0)) | 
					
						
							|  |  |  |                 m_treeView->setExpanded(index, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return oldModel; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerTreeViewToolTipWidget::doReleaseEngine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Save data to stream and restore to the  m_defaultModel (QStandardItemModel)
 | 
					
						
							|  |  |  |     m_defaultModel->removeRows(0, m_defaultModel->rowCount()); | 
					
						
							|  |  |  |     if (const QAbstractItemModel *model = m_treeView->model()) { | 
					
						
							|  |  |  |         TreeModelCopyVisitor v(model, m_defaultModel); | 
					
						
							|  |  |  |         v.run(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-03-29 12:29:10 +02:00
										 |  |  |     delete swapModel(m_defaultModel); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerTreeViewToolTipWidget::restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StandardItemTreeModelBuilder builder(m); | 
					
						
							|  |  |  |     int columnCount = 1; | 
					
						
							|  |  |  |     bool withinModel = true; | 
					
						
							|  |  |  |     while (withinModel && !r.atEnd()) { | 
					
						
							|  |  |  |         const QXmlStreamReader::TokenType token = r.readNext(); | 
					
						
							|  |  |  |         switch (token) { | 
					
						
							|  |  |  |         case QXmlStreamReader::StartElement: { | 
					
						
							|  |  |  |             const QStringRef element = r.name(); | 
					
						
							|  |  |  |             // Root model element with column count.
 | 
					
						
							|  |  |  |             if (element == QLatin1String(modelElementC)) { | 
					
						
							|  |  |  |                 if (const int cc = r.attributes().value(QLatin1String(modelColumnCountAttributeC)).toString().toInt()) | 
					
						
							|  |  |  |                     columnCount = cc; | 
					
						
							|  |  |  |                 m->setColumnCount(columnCount); | 
					
						
							|  |  |  |             } else if (element == QLatin1String(modelRowElementC)) { | 
					
						
							|  |  |  |                 builder.startRow(); | 
					
						
							|  |  |  |             } else if (element == QLatin1String(modelItemElementC)) { | 
					
						
							|  |  |  |                 builder.addItem(r.readElementText()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; // StartElement
 | 
					
						
							|  |  |  |         case QXmlStreamReader::EndElement: { | 
					
						
							|  |  |  |             const QStringRef element = r.name(); | 
					
						
							|  |  |  |             // Row closing: pop off parent.
 | 
					
						
							|  |  |  |             if (element == QLatin1String(modelRowElementC)) { | 
					
						
							|  |  |  |                 builder.endRow(); | 
					
						
							|  |  |  |             } else if (element == QLatin1String(modelElementC)) { | 
					
						
							|  |  |  |                 withinModel = false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; // EndElement
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } // switch
 | 
					
						
							|  |  |  |     } // while
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerTreeViewToolTipWidget::doSaveSessionData(QXmlStreamWriter &w) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     w.writeStartElement(QLatin1String(treeElementC)); | 
					
						
							|  |  |  |     QXmlStreamAttributes attributes; | 
					
						
							|  |  |  |     attributes.append(QLatin1String(treeModelAttributeC), QString::number(m_debuggerModel)); | 
					
						
							|  |  |  |     attributes.append(QLatin1String(treeExpressionAttributeC), m_expression); | 
					
						
							|  |  |  |     w.writeAttributes(attributes); | 
					
						
							|  |  |  |     if (QAbstractItemModel *model = m_treeView->model()) { | 
					
						
							|  |  |  |         XmlWriterTreeModelVisitor v(model, w); | 
					
						
							|  |  |  |         v.run(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     w.writeEndElement(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerTreeViewToolTipWidget::doLoadSessionData(QXmlStreamReader &r) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!readStartElement(r, treeElementC)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     // Restore data to default model and show that.
 | 
					
						
							|  |  |  |     const QXmlStreamAttributes attributes = r.attributes(); | 
					
						
							|  |  |  |     m_debuggerModel = attributes.value(QLatin1String(treeModelAttributeC)).toString().toInt(); | 
					
						
							|  |  |  |     m_expression = attributes.value(QLatin1String(treeExpressionAttributeC)).toString(); | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "DebuggerTreeViewToolTipWidget::doLoadSessionData() " << m_debuggerModel << m_expression; | 
					
						
							|  |  |  |     setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + m_expression); | 
					
						
							|  |  |  |     restoreTreeModel(r, m_defaultModel); | 
					
						
							|  |  |  |     r.readNext(); // Skip </tree>
 | 
					
						
							|  |  |  |     m_treeView->swapModel(m_defaultModel); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-14 09:40:43 +01:00
										 |  |  | QString DebuggerTreeViewToolTipWidget::treeModelClipboardContents(const QAbstractItemModel *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString rc; | 
					
						
							|  |  |  |     QTextStream str(&rc); | 
					
						
							|  |  |  |     DumpTreeModelVisitor v(m, DumpTreeModelVisitor::ClipboardMode, str); | 
					
						
							|  |  |  |     v.run(); | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString DebuggerTreeViewToolTipWidget::clipboardContents() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (const QAbstractItemModel *model = m_treeView->model()) | 
					
						
							|  |  |  |         return DebuggerTreeViewToolTipWidget::treeModelClipboardContents(model); | 
					
						
							|  |  |  |     return QString(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | /*!
 | 
					
						
							| 
									
										
										
										
											2011-03-28 14:58:12 +02:00
										 |  |  |     \class Debugger::Internal::DebuggerToolTipManager | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     Manages the pinned tooltip widgets, listens on editor scroll and main window move | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     events and takes care of repositioning the tooltips. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Listens to editor change and mode change. In debug mode, if there tooltips | 
					
						
							|  |  |  |     for the current editor (by file name), position and show them. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     In addition, listens on state change and stack frame completed signals | 
					
						
							|  |  |  |     of the engine. If a stack frame is completed, have all matching tooltips | 
					
						
							|  |  |  |     (by file name and function) acquire the engine, others release. | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipManager *DebuggerToolTipManager::m_instance = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipManager::DebuggerToolTipManager(QObject *parent) : | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     QObject(parent), m_debugModeActive(false), | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     m_lastToolTipPoint(-1, -1), m_lastToolTipEditor(0) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     DebuggerToolTipManager::m_instance = this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipManager::~DebuggerToolTipManager() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DebuggerToolTipManager::m_instance = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::registerEngine(DebuggerEngine *engine) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     connect(engine, SIGNAL(stateChanged(Debugger::DebuggerState)), | 
					
						
							|  |  |  |             this, SLOT(slotDebuggerStateChanged(Debugger::DebuggerState))); | 
					
						
							|  |  |  |     connect(engine, SIGNAL(stackFrameCompleted()), this, SLOT(slotStackFrameCompleted())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | void DebuggerToolTipManager::showToolTip(const QPoint &p, IEditor *editor, | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                                          AbstractDebuggerToolTipWidget *toolTipWidget) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     QWidget *widget = editor->widget(); | 
					
						
							|  |  |  |     if (debugToolTipPositioning) | 
					
						
							|  |  |  |         qDebug() << "DebuggerToolTipManager::showToolTip" << p << " Mouse at " << QCursor::pos(); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     const WidgetContent widgetContent(toolTipWidget, true); | 
					
						
							|  |  |  |     ToolTip::instance()->show(p, widgetContent, widget); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     registerToolTip(toolTipWidget); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | void DebuggerToolTipManager::registerToolTip(AbstractDebuggerToolTipWidget *toolTipWidget) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(toolTipWidget->context().isValid(), return); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     switch (toolTipWidget->pinState()) { | 
					
						
							|  |  |  |     case PinnableToolTipWidget::Pinned: | 
					
						
							|  |  |  |         m_pinnedTooltips.push_back(toolTipWidget); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case PinnableToolTipWidget::Unpinned: | 
					
						
							|  |  |  |         // Catch the widget once it is pinned.
 | 
					
						
							|  |  |  |         connect(toolTipWidget, SIGNAL(pinned()), this, SLOT(slotPinnedFirstTime())); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::slotPinnedFirstTime() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (AbstractDebuggerToolTipWidget *tw = qobject_cast<AbstractDebuggerToolTipWidget *>(sender())) | 
					
						
							|  |  |  |         m_pinnedTooltips.push_back(tw); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DebuggerToolTipManager::DebuggerToolTipWidgetList &DebuggerToolTipManager::purgeClosedToolTips() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (!m_pinnedTooltips.isEmpty()) { | 
					
						
							|  |  |  |         for (DebuggerToolTipWidgetList::iterator it = m_pinnedTooltips.begin(); it != m_pinnedTooltips.end() ; ) { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             if (it->isNull()) { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                 it = m_pinnedTooltips.erase(it); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 ++it; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     return m_pinnedTooltips; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::moveToolTipsBy(const QPoint &distance) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, purgeClosedToolTips()) | 
					
						
							|  |  |  |         if (tw->isVisible()) | 
					
						
							|  |  |  |             tw->move (tw->pos() + distance); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-29 15:12:42 +02:00
										 |  |  | bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-29 15:12:42 +02:00
										 |  |  |     if (!hasToolTips()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     switch (e->type()) { | 
					
						
							|  |  |  |     case QEvent::Move: { // Move along with parent (toplevel)
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         const QMoveEvent *me = static_cast<const QMoveEvent *>(e); | 
					
						
							|  |  |  |         moveToolTipsBy(me->pos() - me->oldPos()); | 
					
						
							| 
									
										
										
										
											2011-03-29 15:12:42 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case QEvent::WindowStateChange: { // Hide/Show along with parent (toplevel)
 | 
					
						
							|  |  |  |         const QWindowStateChangeEvent *se = static_cast<const QWindowStateChangeEvent *>(e); | 
					
						
							|  |  |  |         const bool wasMinimized = se->oldState() & Qt::WindowMinimized; | 
					
						
							|  |  |  |         const bool isMinimized  = static_cast<const QWidget *>(o)->windowState() & Qt::WindowMinimized; | 
					
						
							|  |  |  |         if (wasMinimized ^ isMinimized) | 
					
						
							|  |  |  |             foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, purgeClosedToolTips()) | 
					
						
							|  |  |  |                 tw->setVisible(!isMinimized); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::sessionAboutToChange() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     closeAllToolTips(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::loadSessionData() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QString data = debuggerCore()->sessionValue(QLatin1String(sessionSettingsKeyC)).toString(); | 
					
						
							|  |  |  |     if (data.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     QXmlStreamReader r(data); | 
					
						
							|  |  |  |     r.readNextStartElement(); | 
					
						
							|  |  |  |     if (r.tokenType() != QXmlStreamReader::StartElement || r.name() != QLatin1String(sessionDocumentC)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     const double version = r.attributes().value(QLatin1String(sessionVersionAttributeC)).toString().toDouble(); | 
					
						
							|  |  |  |     while (!r.atEnd()) | 
					
						
							|  |  |  |         if (AbstractDebuggerToolTipWidget *tw = AbstractDebuggerToolTipWidget::loadSessionData(r)) | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |             registerToolTip(tw); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         qDebug() << "DebuggerToolTipManager::loadSessionData version " << version << " restored " << m_pinnedTooltips.size(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     slotUpdateVisibleToolTips(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::saveSessionData() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString data; | 
					
						
							|  |  |  |     if (!purgeClosedToolTips().isEmpty()) { | 
					
						
							|  |  |  |         QXmlStreamWriter w(&data); | 
					
						
							|  |  |  |         w.writeStartDocument(); | 
					
						
							|  |  |  |         w.writeStartElement(QLatin1String(sessionDocumentC)); | 
					
						
							|  |  |  |         w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0")); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, m_pinnedTooltips) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             tw->saveSessionData(w); | 
					
						
							|  |  |  |         w.writeEndDocument(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         qDebug() << "DebuggerToolTipManager::saveSessionData" << m_pinnedTooltips.size() << data ; | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     debuggerCore()->setSessionValue(QLatin1String(sessionSettingsKeyC), QVariant(data)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::closeAllToolTips() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "DebuggerToolTipManager::closeAllToolTips"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, purgeClosedToolTips()) | 
					
						
							|  |  |  |         tw->close(); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     m_pinnedTooltips.clear(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::hide() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, purgeClosedToolTips()) | 
					
						
							|  |  |  |         tw->hide(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::slotUpdateVisibleToolTips() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (purgeClosedToolTips().isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (!m_debugModeActive) { | 
					
						
							|  |  |  |         hide(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     DebuggerToolTipEditor toolTipEditor = DebuggerToolTipEditor::currentToolTipEditor(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         qDebug() << "DebuggerToolTipManager::slotUpdateVisibleToolTips() " << sender(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     if (!toolTipEditor.isValid() || toolTipEditor.fileName().isEmpty()) { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         hide(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Reposition and show all tooltips of that file.
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     const QString fileName = toolTipEditor.fileName(); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, m_pinnedTooltips) { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         if (tw->fileName() == fileName) { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |             tw->positionShow(toolTipEditor); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             tw->hide(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::slotDebuggerStateChanged(Debugger::DebuggerState state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QObject *engine = sender(); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(engine, return); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const QString name = engine->objectName(); | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "DebuggerToolTipWidget::debuggerStateChanged" | 
					
						
							|  |  |  |                  << engine << Debugger::DebuggerEngine::stateName(state); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Release at earliest possible convenience.
 | 
					
						
							|  |  |  |     switch (state) { | 
					
						
							|  |  |  |     case InferiorRunRequested: | 
					
						
							|  |  |  |     case DebuggerNotReady: | 
					
						
							|  |  |  |     case InferiorShutdownRequested: | 
					
						
							|  |  |  |     case EngineShutdownRequested: | 
					
						
							|  |  |  |     case DebuggerFinished: | 
					
						
							|  |  |  |     case EngineShutdownOk: | 
					
						
							|  |  |  |         foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, purgeClosedToolTips()) | 
					
						
							|  |  |  |             if (tw->engineType() == name) | 
					
						
							|  |  |  |                 tw->releaseEngine(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::slotStackFrameCompleted() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (purgeClosedToolTips().isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     DebuggerEngine *engine = qobject_cast<DebuggerEngine *>(sender()); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     QTC_ASSERT(engine, return); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Stack frame changed: All tooltips of that file acquire the engine,
 | 
					
						
							|  |  |  |     // all others release (arguable, this could be more precise?)
 | 
					
						
							|  |  |  |     QString fileName; | 
					
						
							|  |  |  |     int lineNumber = 0; | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |     // Get the current frame.
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     const QString engineName = engine->objectName(); | 
					
						
							|  |  |  |     QString function; | 
					
						
							|  |  |  |     const int index = engine->stackHandler()->currentIndex(); | 
					
						
							|  |  |  |     if (index >= 0) { | 
					
						
							|  |  |  |         const StackFrame frame = engine->stackHandler()->currentFrame(); | 
					
						
							|  |  |  |         if (frame.usable) { | 
					
						
							|  |  |  |             fileName = frame.file; | 
					
						
							|  |  |  |             lineNumber = frame.line; | 
					
						
							|  |  |  |             function = frame.function; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug("DebuggerToolTipWidget::slotStackFrameCompleted(%s, %s@%d, %s())", | 
					
						
							|  |  |  |                qPrintable(engineName), qPrintable(fileName), lineNumber, | 
					
						
							|  |  |  |                qPrintable(function)); | 
					
						
							|  |  |  |     unsigned acquiredCount = 0; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, m_pinnedTooltips) { | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         if (tw->matches(fileName, engineName, function)) { | 
					
						
							|  |  |  |             tw->acquireEngine(engine); | 
					
						
							|  |  |  |             acquiredCount++; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             tw->releaseEngine(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     slotUpdateVisibleToolTips(); // Move out when stepping in same file.
 | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "DebuggerToolTipWidget::slotStackFrameCompleted()" | 
					
						
							|  |  |  |                  << engineName << fileName << lineNumber << " acquired " << acquiredCount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DebuggerToolTipManager::debug() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return debugToolTips; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | void DebuggerToolTipManager::slotEditorOpened(IEditor *e) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // Move tooltip along when scrolled.
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     if (DebuggerToolTipEditor toolTipEditor = DebuggerToolTipEditor(e)) { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         connect(toolTipEditor.baseTextEditor->verticalScrollBar(), SIGNAL(valueChanged(int)), | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |                 this, SLOT(slotUpdateVisibleToolTips())); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         connect(toolTipEditor.textEditor, | 
					
						
							|  |  |  |             SIGNAL(tooltipOverrideRequested(TextEditor::ITextEditor*,QPoint,int,bool*)), | 
					
						
							|  |  |  |             SLOT(slotTooltipOverrideRequested(TextEditor::ITextEditor*,QPoint,int,bool*))); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::debugModeEntered() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug("DebuggerToolTipManager::debugModeEntered"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Hook up all signals in debug mode.
 | 
					
						
							|  |  |  |     if (!m_debugModeActive) { | 
					
						
							|  |  |  |         m_debugModeActive = true; | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         QWidget *topLevel = ICore::instance()->mainWindow()->topLevelWidget(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         topLevel->installEventFilter(this); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         EditorManager *em = EditorManager::instance(); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)), | 
					
						
							|  |  |  |                 this, SLOT(slotUpdateVisibleToolTips())); | 
					
						
							|  |  |  |         connect(em, SIGNAL(editorOpened(Core::IEditor*)), | 
					
						
							|  |  |  |                 this, SLOT(slotEditorOpened(Core::IEditor*))); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         foreach (IEditor *e, em->openedEditors()) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             slotEditorOpened(e); | 
					
						
							|  |  |  |         // Position tooltips delayed once all the editor placeholder layouting is done.
 | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         if (!m_pinnedTooltips.isEmpty()) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |             QTimer::singleShot(0, this, SLOT(slotUpdateVisibleToolTips())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DebuggerToolTipManager::leavingDebugMode() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |             qDebug("DebuggerToolTipManager::leavingDebugMode"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remove all signals in debug mode.
 | 
					
						
							|  |  |  |     if (m_debugModeActive) { | 
					
						
							|  |  |  |         m_debugModeActive = false; | 
					
						
							|  |  |  |         hide(); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         if (QWidget *topLevel = ICore::instance()->mainWindow()->topLevelWidget()) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |             topLevel->removeEventFilter(this); | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  |         if (EditorManager *em = EditorManager::instance()) { | 
					
						
							|  |  |  |             foreach (IEditor *e, em->openedEditors()) { | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |                 if (DebuggerToolTipEditor toolTipEditor = DebuggerToolTipEditor(e)) { | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |                     toolTipEditor.baseTextEditor->verticalScrollBar()->disconnect(this); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |                     toolTipEditor.textEditor->disconnect(this); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             em->disconnect(this); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         m_lastToolTipEditor = 0; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         m_lastToolTipPoint = QPoint(-1, -1); | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 18:02:29 +01:00
										 |  |  | void DebuggerToolTipManager::slotTooltipOverrideRequested(ITextEditor *editor, | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |                                                           const QPoint &point, | 
					
						
							|  |  |  |                                                           int pos, bool *handled) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(handled, return); | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const int movedDistance = (point - m_lastToolTipPoint).manhattanLength(); | 
					
						
							|  |  |  |     const bool samePosition = m_lastToolTipEditor == editor && movedDistance < 25; | 
					
						
							|  |  |  |     if (debugToolTipPositioning) | 
					
						
							|  |  |  |         qDebug() << ">slotTooltipOverrideRequested() " << editor << point | 
					
						
							|  |  |  |                  << "from " << m_lastToolTipPoint << ") pos: " | 
					
						
							|  |  |  |                  << pos << *handled | 
					
						
							|  |  |  |                  << " Same position=" << samePosition << " d=" << movedDistance; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     DebuggerEngine *currentEngine = 0; | 
					
						
							|  |  |  |     do { | 
					
						
							| 
									
										
										
										
											2011-04-20 14:27:34 +02:00
										 |  |  |         if (samePosition) | 
					
						
							|  |  |  |             *handled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (*handled) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |             break; // Avoid flicker.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         DebuggerCore  *core = debuggerCore(); | 
					
						
							|  |  |  |         if (!isEditorDebuggable(editor) || !core->boolSetting(UseToolTipsInMainEditor)) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         currentEngine = core->currentEngine(); | 
					
						
							|  |  |  |         if (!currentEngine || !currentEngine->canDisplayTooltip()) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const DebuggerToolTipContext context = DebuggerToolTipContext::fromEditor(editor, pos); | 
					
						
							|  |  |  |         if (context.isValid() && currentEngine->setToolTipExpression(point, editor, context)) { | 
					
						
							|  |  |  |             *handled = true; | 
					
						
							|  |  |  |             m_lastToolTipEditor = editor; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |             m_lastToolTipPoint = point; | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } while (false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Other tooltip, close all in case mouse never entered the tooltip
 | 
					
						
							|  |  |  |     // and no leave was triggered.
 | 
					
						
							|  |  |  |     if (!*handled) { | 
					
						
							|  |  |  |         m_lastToolTipEditor = 0; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |         m_lastToolTipPoint = QPoint(-1, -1); | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     if (debugToolTipPositioning) | 
					
						
							| 
									
										
										
										
											2011-02-17 10:08:57 +01:00
										 |  |  |         qDebug() << "<slotTooltipOverrideRequested() " << currentEngine << *handled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  | QStringList DebuggerToolTipManager::treeWidgetExpressions(const QString &fileName, | 
					
						
							|  |  |  |                                                           const QString &engineType, | 
					
						
							|  |  |  |                                                           const QString &function) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QStringList rc; | 
					
						
							| 
									
										
										
										
											2011-02-21 16:45:07 +01:00
										 |  |  |     foreach (const QPointer<AbstractDebuggerToolTipWidget> &tw, m_pinnedTooltips) | 
					
						
							| 
									
										
										
										
											2011-02-11 15:00:13 +01:00
										 |  |  |         if (!tw.isNull() && tw->matches(fileName, engineType, function)) | 
					
						
							|  |  |  |             if (const DebuggerTreeViewToolTipWidget *ttw = qobject_cast<const DebuggerTreeViewToolTipWidget *>(tw.data())) | 
					
						
							|  |  |  |                 rc.push_back(ttw->expression()); | 
					
						
							|  |  |  |     if (debugToolTips) | 
					
						
							|  |  |  |         qDebug() << "DebuggerToolTipManager::treeWidgetExpressions" | 
					
						
							|  |  |  |                  << fileName << engineType << function << rc; | 
					
						
							|  |  |  |     return rc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace Debugger
 | 
					
						
							| 
									
										
										
										
											2011-02-17 10:57:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "debuggertooltipmanager.moc"
 |