diff --git a/src/libs/qmljsdebugclient/qdebugmessageclient.cpp b/src/libs/qmljsdebugclient/qdebugmessageclient.cpp index a140fdeaba17ca1c428740f47dcf3f22436cb9f5..6da461eb3de54943556d5dbe7d5e525afd9140e3 100644 --- a/src/libs/qmljsdebugclient/qdebugmessageclient.cpp +++ b/src/libs/qmljsdebugclient/qdebugmessageclient.cpp @@ -63,12 +63,21 @@ void QDebugMessageClient::messageReceived(const QByteArray &data) int type; QDataStream ms(messagePacket); ms >> type >> debugMessage; - emit message(QtMsgType(type), QString::fromUtf8(debugMessage.data())); + QDebugContextInfo info; + emit message(QtMsgType(type), QString::fromUtf8(debugMessage.data()), + info); } else { int type; + int line; QByteArray debugMessage; - ds >> type >> debugMessage; - emit message(QtMsgType(type), QString::fromUtf8(debugMessage)); + QByteArray file; + QByteArray function; + ds >> type >> debugMessage >> file >> line >> function; + QDebugContextInfo info; + info.line = line; + info.file = QString::fromUtf8(file); + info.function = QString::fromUtf8(function); + emit message(QtMsgType(type), QString::fromUtf8(debugMessage), info); } } } diff --git a/src/libs/qmljsdebugclient/qdebugmessageclient.h b/src/libs/qmljsdebugclient/qdebugmessageclient.h index 032e3b2c508e0a9127a915f414cb39b3811bc3a8..36381392d3a7137306d25db8866676d514907bd8 100644 --- a/src/libs/qmljsdebugclient/qdebugmessageclient.h +++ b/src/libs/qmljsdebugclient/qdebugmessageclient.h @@ -39,6 +39,13 @@ namespace QmlJsDebugClient { class QDebugMessageClientPrivate; +struct QDebugContextInfo +{ + int line; + QString file; + QString function; +}; + class QMLJSDEBUGCLIENT_EXPORT QDebugMessageClient : public QDeclarativeDebugClient { Q_OBJECT @@ -53,7 +60,8 @@ protected: signals: void newStatus(QDeclarativeDebugClient::Status); - void message(QtMsgType, const QString &); + void message(QtMsgType, const QString &, + const QmlJsDebugClient::QDebugContextInfo &); private: class QDebugMessageClientPrivate *d; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index ccd03eb75c3e5efb570603fe4c70471334cdcf98..36ce8e534565ef0a6a3a678b784835a33fe97b3e 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -66,6 +66,7 @@ #include <utils/savedaction.h> #include <utils/qtcassert.h> +#include <utils/fileinprojectfinder.h> #include <QDebug> #include <QTimer> @@ -312,6 +313,7 @@ public: bool m_isStateDebugging; + Utils::FileInProjectFinder m_fileFinder; // Testing void handleAutoTests(); void handleAutoTestLine(int line); @@ -1282,6 +1284,16 @@ DebuggerLanguages DebuggerEngine::languages() const return d->m_languages; } +QString DebuggerEngine::toFileInProject(const QUrl &fileUrl) +{ + // make sure file finder is properly initialized + d->m_fileFinder.setProjectDirectory(startParameters().projectSourceDirectory); + d->m_fileFinder.setProjectFiles(startParameters().projectSourceFiles); + d->m_fileFinder.setSysroot(startParameters().sysroot); + + return d->m_fileFinder.findFile(fileUrl); +} + bool DebuggerEngine::debuggerActionsEnabled() const { return debuggerActionsEnabled(d->m_state); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 5c5eeedb58f6e6e83dd25bb551b02cba13150654..1e559e3e658396c1eb48b3f2e024a969fb146d40 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -286,6 +286,8 @@ public: virtual void notifyInferiorIll(); + QString toFileInProject(const QUrl &fileUrl); + signals: void stateChanged(const Debugger::DebuggerState &state); // A new stack frame is on display including locals. diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 541d7b37d874c9c808a8ee7444f8069b89ae8039..53ca0368a032e163c428519ce433c3920ff0fca3 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -58,11 +58,9 @@ #include <projectexplorer/applicationlauncher.h> #include <qmljsdebugclient/qdeclarativeoutputparser.h> #include <qmljseditor/qmljseditorconstants.h> -#include <qmljsdebugclient/qdebugmessageclient.h> #include <utils/environment.h> #include <utils/qtcassert.h> -#include <utils/fileinprojectfinder.h> #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> @@ -110,7 +108,6 @@ private: friend class QmlEngine; QmlAdapter m_adapter; ApplicationLauncher m_applicationLauncher; - Utils::FileInProjectFinder fileFinder; QTimer m_noDebugOutputTimer; QmlJsDebugClient::QDeclarativeOutputParser m_outputParser; QHash<QString, QTextDocument*> m_sourceDocuments; @@ -157,8 +154,11 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters, SLOT(updateCurrentContext())); connect(&d->m_adapter, SIGNAL(selectionChanged()), SLOT(updateCurrentContext())); - connect(d->m_adapter.messageClient(), SIGNAL(message(QtMsgType,QString)), - SLOT(appendDebugOutput(QtMsgType,QString))); + connect(d->m_adapter.messageClient(), + SIGNAL(message(QtMsgType,QString, + QmlJsDebugClient::QDebugContextInfo)), + SLOT(appendDebugOutput(QtMsgType,QString, + QmlJsDebugClient::QDebugContextInfo))); connect(&d->m_applicationLauncher, SIGNAL(processExited(int)), @@ -852,16 +852,6 @@ bool QmlEngine::hasCapability(unsigned cap) const | AddWatcherCapability;*/ } -QString QmlEngine::toFileInProject(const QUrl &fileUrl) -{ - // make sure file finder is properly initialized - d->fileFinder.setProjectDirectory(startParameters().projectSourceDirectory); - d->fileFinder.setProjectFiles(startParameters().projectSourceFiles); - d->fileFinder.setSysroot(startParameters().sysroot); - - return d->fileFinder.findFile(fileUrl); -} - void QmlEngine::inferiorSpontaneousStop() { if (state() == InferiorRunOk) @@ -892,7 +882,8 @@ void QmlEngine::updateCurrentContext() showMessage(tr("Context: ").append(context), QtMessageLogStatus); } -void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message) +void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message, + const QmlJsDebugClient::QDebugContextInfo &info) { QtMessageLogHandler::ItemType itemType; switch (type) { @@ -910,7 +901,10 @@ void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message) //This case is not possible return; } - qtMessageLogHandler()->appendItem(new QtMessageLogItem(itemType, message)); + QtMessageLogItem *item = new QtMessageLogItem(itemType, message); + item->file = info.file; + item->line = info.line; + qtMessageLogHandler()->appendItem(item); } void QmlEngine::executeDebuggerCommand(const QString& command) @@ -987,7 +981,7 @@ void QmlEngine::setSourceFiles(const QStringList &fileNames) QMap<QString,QString> files; foreach (const QString &file, fileNames) { QString shortName = file; - QString fullName = d->fileFinder.findFile(file); + QString fullName = toFileInProject(file); files.insert(shortName, fullName); } @@ -1080,9 +1074,9 @@ QtMessageLogItem *QmlEngine::constructLogItemTree( QtMessageLogItem *item = new QtMessageLogItem(); if (result.type() == QVariant::Map) { if (key.isEmpty()) - item->setText(_("Object")); + item->text = _("Object"); else - item->setText(QString(_("%1: Object")).arg(key)); + item->text = QString(_("%1: Object")).arg(key); QMapIterator<QString, QVariant> i(result.toMap()); while (i.hasNext()) { @@ -1093,9 +1087,9 @@ QtMessageLogItem *QmlEngine::constructLogItemTree( } } else if (result.type() == QVariant::List) { if (key.isEmpty()) - item->setText(_("List")); + item->text = _("List"); else - item->setText(QString(_("[%1] : List")).arg(key)); + item->text = QString(_("[%1] : List")).arg(key); QVariantList resultList = result.toList(); for (int i = 0; i < resultList.count(); i++) { QtMessageLogItem *child = constructLogItemTree(resultList.at(i), @@ -1104,9 +1098,9 @@ QtMessageLogItem *QmlEngine::constructLogItemTree( item->insertChild(item->childCount(), child); } } else if (result.canConvert(QVariant::String)) { - item->setText(result.toString()); + item->text = result.toString(); } else { - item->setText(_("Unknown Value")); + item->text = _("Unknown Value"); } return item; diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index c6170bbc917336593c4674644d0f75b783da0df5..fc7c47c268bdde0bb1260033f774dce4576cc0de 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -35,6 +35,7 @@ #include "debuggerengine.h" #include <qmljsdebugclient/qdeclarativeenginedebug.h> +#include <qmljsdebugclient/qdebugmessageclient.h> #include <utils/outputformat.h> #include <QAbstractSocket> @@ -80,7 +81,6 @@ public: void gotoLocation(const Internal::Location &location); void filterApplicationMessage(const QString &msg, int channel); - QString toFileInProject(const QUrl &fileUrl); void inferiorSpontaneousStop(); void logMessage(const QString &service, LogDirection direction, const QString &str); @@ -98,7 +98,8 @@ private slots: void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int result); void updateCurrentContext(); - void appendDebugOutput(QtMsgType type, const QString &message); + void appendDebugOutput(QtMsgType type, const QString &message, + const QmlJsDebugClient::QDebugContextInfo &info); private: // DebuggerEngine implementation. diff --git a/src/plugins/debugger/qtmessagelogeditor.cpp b/src/plugins/debugger/qtmessagelogeditor.cpp index 2d95d4caf1f814c1704a059432c5397ab6cd704b..62e3fdf821d722777deebd1a859b22d1c7cdb572 100644 --- a/src/plugins/debugger/qtmessagelogeditor.cpp +++ b/src/plugins/debugger/qtmessagelogeditor.cpp @@ -164,6 +164,10 @@ void QtMessageLogEditor::keyPressEvent(QKeyEvent *e) void QtMessageLogEditor::contextMenuEvent(QContextMenuEvent *event) { + //TODO:: on right click the editor closes + //FIXIT + return QTextEdit::contextMenuEvent(event); + QTextCursor cursor = textCursor(); bool editable = cursor.position() > m_startOfEditableArea; QMenu *menu = new QMenu(); diff --git a/src/plugins/debugger/qtmessageloghandler.cpp b/src/plugins/debugger/qtmessageloghandler.cpp index a9bf672ea698f371a9b16ca67ac203000cb2014b..e8eae4038aec50f2cd716dd812e4fd7accb81127 100644 --- a/src/plugins/debugger/qtmessageloghandler.cpp +++ b/src/plugins/debugger/qtmessageloghandler.cpp @@ -32,6 +32,10 @@ #include "qtmessageloghandler.h" +#include <utils/qtcassert.h> + +#include <QFontMetrics> + namespace Debugger { namespace Internal { @@ -43,9 +47,10 @@ namespace Internal { QtMessageLogItem::QtMessageLogItem(QtMessageLogHandler::ItemType itemType, const QString &text, QtMessageLogItem *parent) - : m_text(text), - m_itemType(itemType), - m_parentItem(parent) + : m_parentItem(parent), + text(text), + itemType(itemType), + line(-1) { } @@ -62,34 +67,27 @@ QtMessageLogItem *QtMessageLogItem::child(int number) int QtMessageLogItem::childCount() const { - return m_childItems.count(); + return m_childItems.size(); } int QtMessageLogItem::childNumber() const { if (m_parentItem) - return m_parentItem->m_childItems.indexOf(const_cast<QtMessageLogItem *>(this)); + return m_parentItem->m_childItems.indexOf( + const_cast<QtMessageLogItem *>(this)); return 0; } -QString QtMessageLogItem::text() const -{ - return m_text; -} - -QtMessageLogHandler::ItemType QtMessageLogItem::itemType() const -{ - return m_itemType; -} -\ bool QtMessageLogItem::insertChildren(int position, int count) { if (position < 0 || position > m_childItems.size()) return false; for (int row = 0; row < count; ++row) { - QtMessageLogItem *item = new QtMessageLogItem(QtMessageLogHandler::UndefinedType, QString(), this); + QtMessageLogItem *item = new + QtMessageLogItem(QtMessageLogHandler::UndefinedType, QString(), + this); m_childItems.insert(position, item); } @@ -136,18 +134,6 @@ bool QtMessageLogItem::detachChild(int position) return true; } -bool QtMessageLogItem::setText(const QString &text) -{ - m_text = text; - return true; -} - -bool QtMessageLogItem::setItemType(QtMessageLogHandler::ItemType itemType) -{ - m_itemType = itemType; - return true; -} - /////////////////////////////////////////////////////////////////////// // // QtMessageLogHandler @@ -157,7 +143,8 @@ bool QtMessageLogItem::setItemType(QtMessageLogHandler::ItemType itemType) QtMessageLogHandler::QtMessageLogHandler(QObject *parent) : QAbstractItemModel(parent), m_hasEditableRow(false), - m_rootItem(new QtMessageLogItem()) + m_rootItem(new QtMessageLogItem()), + m_maxSizeOfFileName(0) { } @@ -222,10 +209,37 @@ void QtMessageLogHandler::appendEditableRow() void QtMessageLogHandler::removeEditableRow() { - if (m_rootItem->child(m_rootItem->childCount() - 1)->itemType() == QtMessageLogHandler::InputType) + if (m_rootItem->child(m_rootItem->childCount() - 1)->itemType == + QtMessageLogHandler::InputType) removeRow(m_rootItem->childCount() - 1); } +int QtMessageLogHandler::sizeOfFile(const QFont &font) +{ + int lastReadOnlyRow = m_rootItem->childCount(); + if (m_hasEditableRow) + lastReadOnlyRow -= 2; + else + lastReadOnlyRow -= 1; + if (lastReadOnlyRow < 0) + return 0; + QString filename = m_rootItem->child(lastReadOnlyRow)->file; + const int pos = filename.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + filename = filename.mid(pos + 1); + + QFontMetrics fm(font); + m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename)); + + return m_maxSizeOfFileName; +} + +int QtMessageLogHandler::sizeOfLineNumber(const QFont &font) +{ + QFontMetrics fm(font); + return fm.width(QLatin1String("88888")); +} + QVariant QtMessageLogHandler::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -234,9 +248,13 @@ QVariant QtMessageLogHandler::data(const QModelIndex &index, int role) const QtMessageLogItem *item = getItem(index); if (role == Qt::DisplayRole ) - return item->text(); + return item->text; else if (role == QtMessageLogHandler::TypeRole) - return int(item->itemType()); + return int(item->itemType); + else if (role == QtMessageLogHandler::FileRole) + return item->file; + else if (role == QtMessageLogHandler::LineRole) + return item->line; else return QVariant(); } @@ -270,6 +288,8 @@ QModelIndex QtMessageLogHandler::parent(const QModelIndex &index) const if (parentItem == m_rootItem) return QModelIndex(); + //can parentItem be 0? + QTC_ASSERT(parentItem, qDebug("Parent is Null!!")); return createIndex(parentItem->childNumber(), 0, parentItem); } @@ -302,12 +322,19 @@ bool QtMessageLogHandler::setData(const QModelIndex &index, const QVariant &valu { QtMessageLogItem *item = getItem(index); bool result = false; - if (role == Qt::DisplayRole ) - result = item->setText(value.toString()); - else if (role == QtMessageLogHandler::TypeRole) - result = item->setItemType((QtMessageLogHandler::ItemType)value.toInt()); - else if (value.canConvert(QVariant::String)) - result = item->setText(value.toString()); + if (role == Qt::DisplayRole) { + item->text = value.toString(); + result = true; + } else if (role == QtMessageLogHandler::TypeRole) { + item->itemType = (QtMessageLogHandler::ItemType)value.toInt(); + result = true; + } else if (role == QtMessageLogHandler::FileRole) { + item->file = value.toString(); + result = true; + } else if (role == QtMessageLogHandler::LineRole) { + item->line = value.toInt(); + result = true; + } if (result) emit dataChanged(index, index); diff --git a/src/plugins/debugger/qtmessageloghandler.h b/src/plugins/debugger/qtmessageloghandler.h index f83ea3d2c929c6adc2683ac139c7b19c71ce6727..9031c8e94c31a44b8ed51a300ce23498eafa4a3b 100644 --- a/src/plugins/debugger/qtmessageloghandler.h +++ b/src/plugins/debugger/qtmessageloghandler.h @@ -35,6 +35,7 @@ #include <QAbstractItemModel> #include <QItemSelectionModel> +#include <QFont> namespace Debugger { namespace Internal { @@ -56,7 +57,7 @@ public: }; Q_DECLARE_FLAGS(ItemTypes, ItemType) - enum Roles { TypeRole = Qt::UserRole }; + enum Roles { TypeRole = Qt::UserRole, FileRole, LineRole }; explicit QtMessageLogHandler(QObject *parent = 0); ~QtMessageLogHandler(); @@ -74,6 +75,9 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const; + int sizeOfFile(const QFont &font); + int sizeOfLineNumber(const QFont &font); + public slots: void clear(); @@ -106,35 +110,36 @@ protected: private: bool m_hasEditableRow; QtMessageLogItem *m_rootItem; + int m_maxSizeOfFileName; }; class QtMessageLogItem - { - public: +{ +public: QtMessageLogItem(QtMessageLogHandler::ItemType type = QtMessageLogHandler::UndefinedType, - const QString &data = QString(), - QtMessageLogItem *parent = 0); - ~QtMessageLogItem(); - - QtMessageLogItem *child(int number); - int childCount() const; - QString text() const; - QtMessageLogHandler::ItemType itemType() const; - bool insertChildren(int position, int count); - bool insertChild(int position, QtMessageLogItem *item); - QtMessageLogItem *parent(); - bool removeChildren(int position, int count); - bool detachChild(int position); - int childNumber() const; - bool setText(const QString &text); - bool setItemType(QtMessageLogHandler::ItemType itemType); - - private: - QList<QtMessageLogItem *> m_childItems; - QString m_text; - QtMessageLogHandler::ItemType m_itemType; - QtMessageLogItem *m_parentItem; - }; + const QString &data = QString(), + QtMessageLogItem *parent = 0); + ~QtMessageLogItem(); + + QtMessageLogItem *child(int number); + int childCount() const; + bool insertChildren(int position, int count); + bool insertChild(int position, QtMessageLogItem *item); + QtMessageLogItem *parent(); + bool removeChildren(int position, int count); + bool detachChild(int position); + int childNumber() const; + +private: + QtMessageLogItem *m_parentItem; + QList<QtMessageLogItem *> m_childItems; + +public: + QString text; + QtMessageLogHandler::ItemType itemType; + QString file; + int line; +}; } //Internal } //Debugger diff --git a/src/plugins/debugger/qtmessagelogitemdelegate.cpp b/src/plugins/debugger/qtmessagelogitemdelegate.cpp index b08ab5e45ce96decdc136426dd2418b9fcd9dbf3..1d8122f538c3f640dcc1ec61997ad24cdedf49cc 100644 --- a/src/plugins/debugger/qtmessagelogitemdelegate.cpp +++ b/src/plugins/debugger/qtmessagelogitemdelegate.cpp @@ -32,10 +32,10 @@ #include "qtmessagelogitemdelegate.h" #include "qtmessagelogeditor.h" -#include "qtmessageloghandler.h" #include <QPainter> #include <QTreeView> +#include <QScrollBar> const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#E8EEF2"; const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#F6F4EB"; @@ -54,6 +54,8 @@ const char CONSOLE_EDITOR_TEXT_COLOR[] = "#000000"; const char CONSOLE_BORDER_COLOR[] = "#C9C9C9"; +const int ELLIPSIS_GRADIENT_WIDTH = 16; + namespace Debugger { namespace Internal { @@ -70,7 +72,8 @@ QtMessageLogItemDelegate::QtMessageLogItemDelegate(QObject *parent) : m_errorIcon(QLatin1String(":/debugger/images/error.png")), m_expandIcon(QLatin1String(":/debugger/images/expand.png")), m_collapseIcon(QLatin1String(":/debugger/images/collapse.png")), - m_prompt(QLatin1String(":/debugger/images/prompt.png")) + m_prompt(QLatin1String(":/debugger/images/prompt.png")), + m_itemModel(0) { } @@ -79,7 +82,7 @@ void QtMessageLogItemDelegate::emitSizeHintChanged(const QModelIndex &index) emit sizeHintChanged(index); } -void QtMessageLogItemDelegate::drawBackground(QPainter *painter, const QRect &rect, +QColor QtMessageLogItemDelegate::drawBackground(QPainter *painter, const QRect &rect, const QModelIndex &index, bool selected) const { @@ -110,7 +113,14 @@ void QtMessageLogItemDelegate::drawBackground(QPainter *painter, const QRect &re painter->setBrush(backgroundColor); painter->setPen(Qt::NoPen); painter->drawRect(rect); + + // Separator lines + painter->setPen(QColor(CONSOLE_BORDER_COLOR)); + if (!(index.flags() & Qt::ItemIsEditable)) + painter->drawLine(0, rect.bottom(), rect.right(), + rect.bottom()); painter->restore(); + return backgroundColor; } void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, @@ -148,7 +158,7 @@ void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewIt } //Paint background - drawBackground(painter, opt.rect, index, + QColor backgroundColor = drawBackground(painter, opt.rect, index, bool(opt.state & QStyle::State_Selected)); //Calculate positions @@ -159,13 +169,14 @@ void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewIt idx = idx.parent(); level++; } - int width = view->width() - level * view->indentation(); + int width = view->width() - level * view->indentation() - + view->verticalScrollBar()->width(); bool showTypeIcon = index.parent() == QModelIndex(); bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType; QRect rect(opt.rect.x(), opt.rect.top(), width, opt.rect.height()); ConsoleItemPositions positions(rect, opt.font, showTypeIcon, - showExpandableIcon); + showExpandableIcon, m_itemModel); // Paint TaskIconArea: if (showTypeIcon) @@ -198,11 +209,39 @@ void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewIt positions.expandCollapseIconHeight())); } - // Separator lines - painter->setPen(QColor(CONSOLE_BORDER_COLOR)); - if (!(index.flags() & Qt::ItemIsEditable)) - painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), - opt.rect.bottom()); + //Check for file info + QString file = index.data(QtMessageLogHandler::FileRole).toString(); + if (!file.isEmpty()) { + QFontMetrics fm(option.font); + // Paint FileArea + const int pos = file.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + file = file.mid(pos +1); + const int realFileWidth = fm.width(file); + painter->setClipRect(positions.fileArea()); + painter->drawText(qMin(positions.fileAreaLeft(), + positions.fileAreaRight() - realFileWidth), + positions.adjustedTop() + fm.ascent(), file); + if (realFileWidth > positions.fileAreaWidth()) { + // draw a gradient to mask the text + int gradientStart = positions.fileAreaLeft() - 1; + QLinearGradient lg(gradientStart + + ELLIPSIS_GRADIENT_WIDTH, 0, gradientStart, 0); + lg.setColorAt(0, Qt::transparent); + lg.setColorAt(1, backgroundColor); + painter->fillRect(gradientStart, positions.adjustedTop(), + ELLIPSIS_GRADIENT_WIDTH, positions.lineHeight(), + lg); + } + + // Paint LineArea + QString lineText = index.data(QtMessageLogHandler::LineRole).toString(); + painter->setClipRect(positions.lineArea()); + const int realLineWidth = fm.width(lineText); + painter->drawText(positions.lineAreaRight() - realLineWidth, + positions.adjustedTop() + fm.ascent(), lineText); + } + painter->setClipRect(opt.rect); painter->restore(); } @@ -219,7 +258,8 @@ QSize QtMessageLogItemDelegate::sizeHint(const QStyleOptionViewItem &option, idx = idx.parent(); level++; } - int width = view->width() - level * view->indentation(); + int width = view->width() - level * view->indentation() - + view->verticalScrollBar()->width(); if (index.flags() & Qt::ItemIsEditable) return QSize(width, view->height() * 1/2); @@ -230,8 +270,7 @@ QSize QtMessageLogItemDelegate::sizeHint(const QStyleOptionViewItem &option, QRect rect(level * view->indentation(), 0, width, 0); ConsoleItemPositions positions(rect, opt.font, - showTypeIcon, - showExpandableIcon); + showTypeIcon, showExpandableIcon, m_itemModel); QTextLayout tl(index.data(Qt::DisplayRole).toString(), option.font); qreal height = layoutText(tl, positions.textAreaWidth()); @@ -310,5 +349,10 @@ qreal QtMessageLogItemDelegate::layoutText(QTextLayout &tl, int width) const return height; } +void QtMessageLogItemDelegate::setItemModel(QtMessageLogHandler *model) +{ + m_itemModel = model; +} + } //Internal } //Debugger diff --git a/src/plugins/debugger/qtmessagelogitemdelegate.h b/src/plugins/debugger/qtmessagelogitemdelegate.h index 7bce80fb4df54dc824bc3006519e0d7c3668898b..7d35f507273c8c3dd6af8b07d1714e853baef3a9 100644 --- a/src/plugins/debugger/qtmessagelogitemdelegate.h +++ b/src/plugins/debugger/qtmessagelogitemdelegate.h @@ -33,6 +33,8 @@ #ifndef QTMESSAGELOGITEMDELEGATE_H #define QTMESSAGELOGITEMDELEGATE_H +#include "qtmessageloghandler.h" + #include <QTextLayout> #include <QStyledItemDelegate> @@ -45,10 +47,12 @@ class QtMessageLogItemDelegate : public QStyledItemDelegate public: explicit QtMessageLogItemDelegate(QObject *parent = 0); void emitSizeHintChanged(const QModelIndex &index); - void drawBackground(QPainter *painter, const QRect &rect, + QColor drawBackground(QPainter *painter, const QRect &rect, const QModelIndex &index, bool selected) const; + void setItemModel(QtMessageLogHandler *model); + public slots: void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); @@ -80,11 +84,12 @@ private: const QIcon m_expandIcon; const QIcon m_collapseIcon; const QIcon m_prompt; + QtMessageLogHandler *m_itemModel; }; /* +----------------------------------------------------------------------------+ - | TYPEICONAREA EXPANDABLEICONAREA TEXTAREA | + | TYPEICONAREA EXPANDABLEICONAREA TEXTAREA FILEAREA LINEAREA | +----------------------------------------------------------------------------+ */ @@ -98,9 +103,10 @@ class ConsoleItemPositions { public: ConsoleItemPositions(const QRect &rect, - const QFont &font = QFont(), - bool showTaskIconArea = true, - bool showExpandableIconArea = true) + const QFont &font, + bool showTaskIconArea, + bool showExpandableIconArea, + QtMessageLogHandler *model = 0) : m_x(rect.x()), m_width(rect.width()), m_top(rect.top()), @@ -109,6 +115,10 @@ public: m_showExpandableIconArea(showExpandableIconArea) { m_fontHeight = QFontMetrics(font).height(); + if (model) { + m_maxFileLength = model->sizeOfFile(font); + m_maxLineLength = model->sizeOfLineNumber(font); + } } int adjustedTop() const { return m_top + ITEM_PADDING; } @@ -141,16 +151,30 @@ public: int textAreaLeft() const { return expandCollapseIconRight() + ITEM_SPACING; } int textAreaWidth() const { return textAreaRight() - textAreaLeft(); } - int textAreaRight() const { return adjustedRight() - ITEM_SPACING; } + int textAreaRight() const { return fileAreaLeft() - ITEM_SPACING; } QRect textArea() const { return QRect(textAreaLeft(), adjustedTop(), textAreaWidth(), lineHeight()); } + int fileAreaLeft() const { return fileAreaRight() - fileAreaWidth(); } + int fileAreaWidth() const { return m_maxFileLength; } + int fileAreaRight() const { return lineAreaLeft() - ITEM_SPACING; } + QRect fileArea() const { return + QRect(fileAreaLeft(), adjustedTop(), fileAreaWidth(), lineHeight()); } + + int lineAreaLeft() const { return lineAreaRight() - lineAreaWidth(); } + int lineAreaWidth() const { return m_maxLineLength; } + int lineAreaRight() const { return adjustedRight() - ITEM_SPACING; } + QRect lineArea() const { return + QRect(lineAreaLeft(), adjustedTop(), lineAreaWidth(), lineHeight()); } + private: int m_x; int m_width; int m_top; int m_bottom; int m_fontHeight; + int m_maxFileLength; + int m_maxLineLength; bool m_showTaskIconArea; bool m_showExpandableIconArea; diff --git a/src/plugins/debugger/qtmessagelogview.cpp b/src/plugins/debugger/qtmessagelogview.cpp index 34f7ba96e2276ce69fbfd3986bdaf18bde0e6aa7..0029235ea3d697a051761323f84e8f1a774a268a 100644 --- a/src/plugins/debugger/qtmessagelogview.cpp +++ b/src/plugins/debugger/qtmessagelogview.cpp @@ -33,10 +33,20 @@ #include "qtmessagelogview.h" #include "qtmessagelogitemdelegate.h" #include "qtmessageloghandler.h" +#include "debuggerstringutils.h" +#include "debuggercore.h" +#include "debuggerengine.h" + +#include <texteditor/basetexteditor.h> #include <QMouseEvent> #include <QProxyStyle> #include <QPainter> +#include <QApplication> +#include <QClipboard> +#include <QAbstractProxyModel> +#include <QFileInfo> +#include <QUrl> namespace Debugger { namespace Internal { @@ -97,6 +107,12 @@ QtMessageLogView::QtMessageLogView(QWidget *parent) : QtMessageLogViewViewStyle *style = new QtMessageLogViewViewStyle; setStyle(style); style->setParent(this); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + + connect(this, SIGNAL(activated(QModelIndex)), + SLOT(onRowActivated(QModelIndex))); } void QtMessageLogView::mousePressEvent(QMouseEvent *event) @@ -106,19 +122,22 @@ void QtMessageLogView::mousePressEvent(QMouseEvent *event) if (index.isValid()) { QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data( QtMessageLogHandler::TypeRole).toInt(); - bool showTypeIcon = index.parent() == QModelIndex(); - bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType; - ConsoleItemPositions positions(visualRect(index), viewOptions().font, - showTypeIcon, showExpandableIcon); - - if (positions.expandCollapseIcon().contains(pos)) { - if (isExpanded(index)) - setExpanded(index, false); - else - setExpanded(index, true); - } else { - QTreeView::mousePressEvent(event); + bool handled = false; + if (type == QtMessageLogHandler::UndefinedType) { + bool showTypeIcon = index.parent() == QModelIndex(); + ConsoleItemPositions positions(visualRect(index), viewOptions().font, + showTypeIcon, true); + + if (positions.expandCollapseIcon().contains(pos)) { + if (isExpanded(index)) + setExpanded(index, false); + else + setExpanded(index, true); + handled = true; + } } + if (!handled) + QTreeView::mousePressEvent(event); } else { selectionModel()->setCurrentIndex(model()->index( model()->rowCount() - 1, 0), @@ -126,6 +145,16 @@ void QtMessageLogView::mousePressEvent(QMouseEvent *event) } } +void QtMessageLogView::keyPressEvent(QKeyEvent *e) +{ + if (!e->modifiers() && e->key() == Qt::Key_Return) { + emit activated(currentIndex()); + e->accept(); + return; + } + QTreeView::keyPressEvent(e); +} + void QtMessageLogView::resizeEvent(QResizeEvent *e) { static_cast<QtMessageLogItemDelegate *>(itemDelegate())->emitSizeHintChanged( @@ -141,5 +170,95 @@ void QtMessageLogView::drawBranches(QPainter *painter, const QRect &rect, QTreeView::drawBranches(painter, rect, index); } +void QtMessageLogView::contextMenuEvent(QContextMenuEvent *event) +{ + QModelIndex itemIndex = indexAt(event->pos()); + QMenu menu; + + QAction *copy = new QAction(tr("&Copy"), this); + copy->setEnabled(itemIndex.isValid()); + menu.addAction(copy); + QAction *show = new QAction(tr("&Show in Editor"), this); + show->setEnabled(canShowItemInTextEditor(itemIndex)); + menu.addAction(show); + menu.addSeparator(); + QAction *clear = new QAction(tr("C&lear"), this); + menu.addAction(clear); + + QAction *a = menu.exec(event->globalPos()); + if (a == 0) + return; + + if (a == copy) + copyToClipboard(itemIndex); + else if (a == show) + onRowActivated(itemIndex); + else if (a == clear) { + QAbstractProxyModel *proxyModel = + qobject_cast<QAbstractProxyModel *>(model()); + QtMessageLogHandler *handler = + qobject_cast<QtMessageLogHandler *>(proxyModel->sourceModel()); + handler->clear(); + } +} + +void QtMessageLogView::onRowActivated(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + //See if we have file and line Info + QString filePath = model()->data(index, + QtMessageLogHandler::FileRole).toString(); + if (!filePath.isEmpty()) { + filePath = debuggerCore()->currentEngine()->toFileInProject( + QUrl(filePath)); + QFileInfo fi(filePath); + if (fi.exists() && fi.isFile() && fi.isReadable()) { + int line = model()->data(index, + QtMessageLogHandler::LineRole).toInt(); + TextEditor::BaseTextEditorWidget::openEditorAt( + fi.canonicalFilePath(), line); + } + } +} + +void QtMessageLogView::copyToClipboard(const QModelIndex &index) +{ + if (!index.isValid()) + return; + + QString contents = model()->data(index).toString(); + //See if we have file and line Info + QString filePath = model()->data(index, + QtMessageLogHandler::FileRole).toString(); + if (!filePath.isEmpty()) { + contents = QString(_("%1 %2: %3")).arg(contents).arg(filePath).arg( + model()->data(index, + QtMessageLogHandler::LineRole).toString()); + } + QClipboard *cb = QApplication::clipboard(); + cb->setText(contents); +} + +bool QtMessageLogView::canShowItemInTextEditor(const QModelIndex &index) +{ + if (!index.isValid()) + return false; + + //See if we have file and line Info + QString filePath = model()->data(index, + QtMessageLogHandler::FileRole).toString(); + if (!filePath.isEmpty()) { + filePath = debuggerCore()->currentEngine()->toFileInProject( + QUrl(filePath)); + QFileInfo fi(filePath); + if (fi.exists() && fi.isFile() && fi.isReadable()) { + return true; + } + } + return false; +} + } //Internal } //Debugger diff --git a/src/plugins/debugger/qtmessagelogview.h b/src/plugins/debugger/qtmessagelogview.h index 4a6a301d268c5627f2efef03cf6a0154e665dfe8..103d6ff19dfa15a0d8f028457782016152e7eeea 100644 --- a/src/plugins/debugger/qtmessagelogview.h +++ b/src/plugins/debugger/qtmessagelogview.h @@ -46,9 +46,18 @@ public: protected: void mousePressEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *e); void resizeEvent(QResizeEvent *e); void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const; + void contextMenuEvent(QContextMenuEvent *event); + +private slots: + void onRowActivated(const QModelIndex &index); + +private: + void copyToClipboard(const QModelIndex &index); + bool canShowItemInTextEditor(const QModelIndex &index); }; } //Internal diff --git a/src/plugins/debugger/qtmessagelogwindow.cpp b/src/plugins/debugger/qtmessagelogwindow.cpp index c3a8e52638b951a565d4448bf4e19e94ba3e04c9..e54ccae8ab29ca01a2d3991fac5dfeae242db55a 100644 --- a/src/plugins/debugger/qtmessagelogwindow.cpp +++ b/src/plugins/debugger/qtmessagelogwindow.cpp @@ -161,10 +161,10 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_treeView, SLOT(scrollToBottom())); - QtMessageLogItemDelegate *itemDelegate = new QtMessageLogItemDelegate(this); + m_itemDelegate = new QtMessageLogItemDelegate(this); connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - itemDelegate, SLOT(currentChanged(QModelIndex,QModelIndex))); - m_treeView->setItemDelegate(itemDelegate); + m_itemDelegate, SLOT(currentChanged(QModelIndex,QModelIndex))); + m_treeView->setItemDelegate(m_itemDelegate); vbox->addWidget(statusbarContainer); vbox->addWidget(m_treeView); @@ -204,6 +204,7 @@ void QtMessageLogWindow::setModel(QAbstractItemModel *model) { m_proxyModel->setSourceModel(model); QtMessageLogHandler *handler = qobject_cast<QtMessageLogHandler *>(model); + m_itemDelegate->setItemModel(handler); connect(m_clearAction, SIGNAL(triggered()), handler, SLOT(clear())); connect(handler, SIGNAL(selectEditableRow(QModelIndex,QItemSelectionModel::SelectionFlags)), diff --git a/src/plugins/debugger/qtmessagelogwindow.h b/src/plugins/debugger/qtmessagelogwindow.h index 25caa0140a7a84e5049c3e927cb2c1789cb2815f..e8cc96478c0c669eb05061156e33fc64bb7ea6d6 100644 --- a/src/plugins/debugger/qtmessagelogwindow.h +++ b/src/plugins/debugger/qtmessagelogwindow.h @@ -49,6 +49,7 @@ namespace Debugger { namespace Internal { class QtMessageLogView; +class QtMessageLogItemDelegate; class QtMessageLogProxyModel; class QtMessageLogWindow : public QWidget { @@ -71,6 +72,7 @@ private: Utils::SavedAction *m_showErrorAction; QAction *m_clearAction; QtMessageLogView *m_treeView; + QtMessageLogItemDelegate *m_itemDelegate; QtMessageLogProxyModel *m_proxyModel; };