diff options
author | hjk <hjk@qt.io> | 2020-11-02 14:23:46 +0100 |
---|---|---|
committer | hjk <hjk@qt.io> | 2020-11-05 08:39:21 +0000 |
commit | c05ad9a951118ed0fb4343218b5ec55dae21b9c1 (patch) | |
tree | 68e6ece93586e872a7b417e132fc88a2f457c3d7 /src/plugins/debugger/stackhandler.cpp | |
parent | c5544c30f29bf43b86913df92b332c56d903ebe7 (diff) |
Debugger: Allow copying only selected lines in stack view
Fixes: QTCREATORBUG-24701
Change-Id: Ica81a4e96bc5d888efca4307f91ebdca2488003a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/debugger/stackhandler.cpp')
-rw-r--r-- | src/plugins/debugger/stackhandler.cpp | 107 |
1 files changed, 73 insertions, 34 deletions
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 78da176cef..ecbe04e98c 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -353,6 +353,71 @@ static StackFrame inputFunctionForDisassembly() return frame; } +template<typename Functor> +void forEachCell(Functor f, QAbstractItemModel *model, const QModelIndex &idx) +{ + f(idx); + for (int i = 0, n = model->rowCount(idx); i < n; ++i) + forEachCell(f, model, model->index(i, 0, idx)); +} + +static QString selectedText(QWidget *widget, bool useAll) +{ + QAbstractItemView *view = qobject_cast<QAbstractItemView *>(widget); + QTC_ASSERT(view, return {}); + QAbstractItemModel *model = view->model(); + QTC_ASSERT(model, return {}); + + const int ncols = model->columnCount(QModelIndex()); + QVector<int> largestColumnWidths(ncols, 0); + + QSet<QModelIndex> selected; + if (QItemSelectionModel *selection = view->selectionModel()) { + const QModelIndexList list = selection->selectedIndexes(); + selected = QSet<QModelIndex>(list.begin(), list.end()); + } + if (selected.isEmpty()) + useAll = true; + + // First, find the widths of the largest columns, + // so that we can print them out nicely aligned. + forEachCell([ncols, model, &largestColumnWidths, selected, useAll](const QModelIndex &idx) { + if (useAll || selected.contains(idx)) { + for (int j = 0; j < ncols; ++j) { + const QModelIndex sibling = model->sibling(idx.row(), j, idx); + const int columnWidth = model->data(sibling, Qt::DisplayRole).toString().size(); + if (columnWidth > largestColumnWidths.at(j)) + largestColumnWidths[j] = columnWidth; + } + } + }, model, QModelIndex()); + + QString str; + forEachCell([ncols, model, largestColumnWidths, &str, selected, useAll](const QModelIndex &idx) { + if (useAll || selected.contains(idx)) { + for (int j = 0; j != ncols; ++j) { + const QModelIndex sibling = model->sibling(idx.row(), j, idx); + const QString columnEntry = model->data(sibling, Qt::DisplayRole).toString(); + str += columnEntry; + const int difference = largestColumnWidths.at(j) - columnEntry.size(); + // Add one extra space between columns. + str += QString(qMax(difference, 0) + 1, QChar(' ')); + } + str += '\n'; + } + }, model, QModelIndex()); + + return str; +} + +static void copyTextToClipboard(const QString &str) +{ + QClipboard *clipboard = QApplication::clipboard(); + if (clipboard->supportsSelection()) + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + // Write stack frames as task file for displaying it in the build issues pane. void StackHandler::saveTaskFile() { @@ -392,7 +457,14 @@ bool StackHandler::contextMenuEvent(const ItemViewEvent &ev) menu->addAction(action(ExpandStack)->action()); - addAction(menu, tr("Copy Contents to Clipboard"), true, [this] { copyContentsToClipboard(); }); + addAction(menu, tr("Copy Contents to Clipboard"), true, [ev] { + copyTextToClipboard(selectedText(ev.view(), true)); + }); + + addAction(menu, tr("Copy Selection to Clipboard"), true, [ev] { + copyTextToClipboard(selectedText(ev.view(), false)); + }); + addAction(menu, tr("Save as Task File..."), true, [this] { saveTaskFile(); }); if (m_engine->hasCapability(CreateFullBacktraceCapability)) @@ -451,39 +523,6 @@ bool StackHandler::contextMenuEvent(const ItemViewEvent &ev) return true; } -void StackHandler::copyContentsToClipboard() -{ - const int m = columnCount(QModelIndex()); - QVector<int> largestColumnWidths(m, 0); - - // First, find the widths of the largest columns, - // so that we can print them out nicely aligned. - forItemsAtLevel<2>([m, &largestColumnWidths](StackFrameItem *item) { - for (int j = 0; j < m; ++j) { - const int columnWidth = item->data(j, Qt::DisplayRole).toString().size(); - if (columnWidth > largestColumnWidths.at(j)) - largestColumnWidths[j] = columnWidth; - } - }); - - QString str; - forItemsAtLevel<2>([m, largestColumnWidths, &str](StackFrameItem *item) { - for (int j = 0; j != m; ++j) { - const QString columnEntry = item->data(j, Qt::DisplayRole).toString(); - str += columnEntry; - const int difference = largestColumnWidths.at(j) - columnEntry.size(); - // Add one extra space between columns. - str += QString(qMax(difference, 0) + 1, QChar(' ')); - } - str += '\n'; - }); - - QClipboard *clipboard = QApplication::clipboard(); - if (clipboard->supportsSelection()) - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - void StackHandler::reloadFullStack() { m_engine->reloadFullStack(); |