aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/debugger/stackhandler.cpp
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2020-11-02 14:23:46 +0100
committerhjk <hjk@qt.io>2020-11-05 08:39:21 +0000
commitc05ad9a951118ed0fb4343218b5ec55dae21b9c1 (patch)
tree68e6ece93586e872a7b417e132fc88a2f457c3d7 /src/plugins/debugger/stackhandler.cpp
parentc5544c30f29bf43b86913df92b332c56d903ebe7 (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.cpp107
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();