aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Barany <akb825@gmail.com>2018-12-11 23:09:39 -0800
committerAaron Barany <akb825@gmail.com>2019-01-08 18:43:44 +0000
commit21c0f5395ed163a122cc11de5f1ba8eb0805e25f (patch)
tree183db79686d0130fe557ce543bb3f08f24067b49
parent6c40d9570cd0eb14f8e0651c51c730b8d19ebf14 (diff)
Debugger: Fix sizing of debugger columns
Added span column property to BaseTreeView. This takes an index to a column that will span remaining space not explicitly taken by the other columns. This listens to resizing of the tree view and columns that are manually resized to keep the sizes consistent. The stack view now once again uses the StackView class, which now sets the function column as the span column. This will adjust the column size the first time stack frame contents are encountered. It will not resize automatically until it's re-created (the next debug session) so it doesn't undo custom resizing. This also restores the ability to toggle stack addresses. Some obsolete parts of this class were removed as part of retrofitting it for the current state of the debugger. Stack, breakpoint, and thread views now resize remaining space for the function column rather than empty space at the end. This is generally the most important field when debugging and can get very long, especially in C++. Task-number: QTCREATORBUG-21763 Change-Id: I821c83d1d951f3311d7fa9fcddcbdeedfeed1573 Reviewed-by: Orgad Shaneh <orgads@gmail.com>
-rw-r--r--src/libs/utils/basetreeview.cpp129
-rw-r--r--src/libs/utils/basetreeview.h8
-rw-r--r--src/plugins/debugger/debuggerengine.cpp4
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp1
-rw-r--r--src/plugins/debugger/stackwindow.cpp41
-rw-r--r--src/plugins/debugger/stackwindow.h9
6 files changed, 177 insertions, 15 deletions
diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp
index bae4c16fef..03139a4154 100644
--- a/src/libs/utils/basetreeview.cpp
+++ b/src/libs/utils/basetreeview.cpp
@@ -55,6 +55,40 @@ public:
m_settingsTimer.setSingleShot(true);
connect(&m_settingsTimer, &QTimer::timeout,
this, &BaseTreeViewPrivate::doSaveState);
+ connect(q->header(), &QHeaderView::sectionResized, this, [this](int logicalIndex, int oldSize, int newSize) {
+ if (m_processingSpans || m_spanColumn < 0)
+ return;
+
+ QHeaderView *h = q->header();
+ QTC_ASSERT(h, return);
+
+ // Last non-hidden column.
+ int count = h->count();
+ while (count > 0 && h->isSectionHidden(count - 1))
+ --count;
+
+ if (count == 0)
+ return;
+
+ int column = logicalIndex;
+ if (oldSize < newSize)
+ {
+ // Protect against sizing past the next section.
+ while (column + 1 < count && h->sectionSize(column + 1) == h->minimumSectionSize())
+ ++column;
+ }
+
+ if (logicalIndex >= m_spanColumn) {
+ // Resize after the span column.
+ column = column + 1;
+ } else {
+ // Resize the span column or before it.
+ column = m_spanColumn;
+ }
+
+ rebalanceColumns(column, false);
+ });
+ connect(q->header(), &QHeaderView::geometriesChanged, this, QOverload<>::of(&BaseTreeViewPrivate::rebalanceColumns));
}
bool eventFilter(QObject *, QEvent *event) override
@@ -197,6 +231,17 @@ public:
}
}
+ void setSpanColumn(int column)
+ {
+ if (column == m_spanColumn)
+ return;
+
+ m_spanColumn = column;
+ if (m_spanColumn >= 0)
+ q->header()->setStretchLastSection(false);
+ rebalanceColumns();
+ }
+
void toggleColumnWidth(int logicalIndex)
{
QHeaderView *h = q->header();
@@ -211,11 +256,72 @@ public:
int minSize = 10 * fm.width(QLatin1Char('x'));
targetSize = qMax(minSize, headerSize);
}
+
+ // Prevent rebalance as part of this resize.
+ m_processingSpans = true;
h->resizeSection(logicalIndex, targetSize);
+ m_processingSpans = false;
+
+ // Now trigger a rebalance so it resizes the span column. (if set)
+ rebalanceColumns();
+
m_userHandled.remove(logicalIndex); // Reset.
saveState();
}
+ void rebalanceColumns()
+ {
+ rebalanceColumns(m_spanColumn, true);
+ }
+
+ void rebalanceColumns(int column, bool allowResizePrevious)
+ {
+ if (m_spanColumn < 0 || column < 0 || m_processingSpans)
+ return;
+
+ QHeaderView *h = q->header();
+ QTC_ASSERT(h, return);
+
+ int count = h->count();
+ if (column >= count)
+ return;
+
+ // Start with the target column, and resize other columns as necessary.
+ int totalSize = q->viewport()->width();
+ if (tryRebalanceColumns(column, totalSize))
+ return;
+
+ for (int i = allowResizePrevious ? 0 : column + 1; i < count; ++i) {
+ if (i != column && tryRebalanceColumns(i, totalSize))
+ return;
+ }
+ }
+
+ bool tryRebalanceColumns(int column, int totalSize)
+ {
+ QHeaderView *h = q->header();
+
+ int count = h->count();
+ int otherColumnTotal = 0;
+ for (int i = 0; i < count; ++i) {
+ if (i != column)
+ otherColumnTotal += h->sectionSize(i);
+ }
+
+ if (otherColumnTotal < totalSize) {
+ m_processingSpans = true;
+ h->resizeSection(column, totalSize - otherColumnTotal);
+ m_processingSpans = false;
+ } else
+ return false;
+
+ // Make sure this didn't go over the total size.
+ int totalColumnSize = 0;
+ for (int i = 0; i < count; ++i)
+ totalColumnSize += h->sectionSize(i);
+ return totalColumnSize == totalSize;
+ }
+
public:
BaseTreeView *q;
QMap<int, int> m_userHandled; // column -> width, "not present" means "automatic"
@@ -224,6 +330,8 @@ public:
QString m_settingsKey;
bool m_expectUserChanges = false;
ProgressIndicator *m_progressIndicator = nullptr;
+ int m_spanColumn = -1;
+ bool m_processingSpans = false;
};
class BaseTreeViewDelegate : public QItemDelegate
@@ -369,6 +477,12 @@ void BaseTreeView::mouseDoubleClickEvent(QMouseEvent *ev)
TreeView::mouseDoubleClickEvent(ev);
}
+void BaseTreeView::resizeEvent(QResizeEvent *ev)
+{
+ TreeView::resizeEvent(ev);
+ d->rebalanceColumns();
+}
+
void BaseTreeView::showEvent(QShowEvent *ev)
{
emit aboutToShow();
@@ -416,6 +530,21 @@ void BaseTreeView::resizeColumns()
d->resizeColumns();
}
+int BaseTreeView::spanColumn() const
+{
+ return d->m_spanColumn;
+}
+
+void BaseTreeView::setSpanColumn(int column)
+{
+ d->setSpanColumn(column);
+}
+
+void BaseTreeView::refreshSpanColumn()
+{
+ d->rebalanceColumns();
+}
+
void BaseTreeView::setSettings(QSettings *settings, const QByteArray &key)
{
QTC_ASSERT(!d->m_settings, qDebug() << "DUPLICATED setSettings" << key);
diff --git a/src/libs/utils/basetreeview.h b/src/libs/utils/basetreeview.h
index 923c69b042..36da658913 100644
--- a/src/libs/utils/basetreeview.h
+++ b/src/libs/utils/basetreeview.h
@@ -68,11 +68,19 @@ public:
void dropEvent(QDropEvent *ev) override;
void dragMoveEvent(QDragMoveEvent *ev) override;
void mouseDoubleClickEvent(QMouseEvent *ev) override;
+ void resizeEvent(QResizeEvent *event) override;
void showProgressIndicator();
void hideProgressIndicator();
void resizeColumns();
+ int spanColumn() const;
+ void setSpanColumn(int column);
+
+ // In some situations this needs to be called when manually resizing columns when the span
+ // column is set.
+ void refreshSpanColumn();
+
signals:
void aboutToShow();
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 6594e7d00c..1f06fef2af 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -642,7 +642,7 @@ void DebuggerEnginePrivate::setupViews()
m_registerWindow->setObjectName(DOCKWIDGET_REGISTER);
m_registerWindow->setWindowTitle(tr("Reg&isters"));
- m_stackView = new BaseTreeView;
+ m_stackView = new StackTreeView;
m_stackView->setModel(m_stackHandler.model());
m_stackView->setSettings(settings, "Debugger.StackView");
m_stackView->setIconSize(QSize(10, 10));
@@ -666,6 +666,7 @@ void DebuggerEnginePrivate::setupViews()
m_threadsView->setSortingEnabled(true);
m_threadsView->setSettings(settings, "Debugger.ThreadsView");
m_threadsView->setIconSize(QSize(10, 10));
+ m_threadsView->setSpanColumn(ThreadData::FunctionColumn);
m_threadsWindow = addSearch(m_threadsView);
m_threadsWindow->setObjectName(DOCKWIDGET_THREADS);
m_threadsWindow->setWindowTitle(tr("&Threads"));
@@ -711,6 +712,7 @@ void DebuggerEnginePrivate::setupViews()
m_breakView->setIconSize(QSize(10, 10));
m_breakView->setWindowIcon(Icons::BREAKPOINTS.icon());
m_breakView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ m_breakView->setSpanColumn(BreakpointFunctionColumn);
connect(action(UseAddressInBreakpointsView), &QAction::toggled,
this, [this](bool on) { m_breakView->setColumnHidden(BreakpointAddressColumn, !on); });
m_breakView->setSettings(settings, "Debugger.BreakWindow");
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 04b1b8d341..042a7f4368 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -1038,6 +1038,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_breakpointManagerView->setSettings(settings, "Debugger.BreakWindow");
m_breakpointManagerView->setRootIsDecorated(true);
m_breakpointManagerView->setModel(BreakpointManager::model());
+ m_breakpointManagerView->setSpanColumn(BreakpointFunctionColumn);
m_breakpointManagerWindow = addSearch(m_breakpointManagerView);
m_breakpointManagerWindow->setWindowTitle(tr("Breakpoint Preset"));
m_breakpointManagerWindow->setObjectName(DOCKWIDGET_BREAKPOINTMANAGER);
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index 83e6af2829..e25f6aa72b 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -32,33 +32,56 @@
#include <utils/savedaction.h>
#include <QAction>
+#include <QHeaderView>
namespace Debugger {
namespace Internal {
-StackTreeView::StackTreeView()
+StackTreeView::StackTreeView(QWidget *parent)
+ : BaseTreeView(parent)
{
- setWindowTitle(tr("Stack"));
-
connect(action(UseAddressInStackView), &QAction::toggled,
this, &StackTreeView::showAddressColumn);
+ setSpanColumn(StackFunctionNameColumn);
showAddressColumn(false);
}
+void StackTreeView::setModel(QAbstractItemModel *model)
+{
+ BaseTreeView::setModel(model);
+ connect(static_cast<StackHandler*>(model), &StackHandler::stackChanged,
+ this, [this]() {
+ if (!m_contentsAdjusted)
+ adjustForContents();
+ });
+
+ // Resize for the current contents if any are available.
+ showAddressColumn(action(UseAddressInStackView)->isChecked());
+}
+
void StackTreeView::showAddressColumn(bool on)
{
setColumnHidden(StackAddressColumn, !on);
- resizeColumnToContents(StackLevelColumn);
- resizeColumnToContents(StackLineNumberColumn);
- resizeColumnToContents(StackAddressColumn);
+ adjustForContents(true);
}
-void StackTreeView::setModel(QAbstractItemModel *model)
+void StackTreeView::adjustForContents(bool refreshSpan)
{
- BaseTreeView::setModel(model);
+ // Skip resizing if no contents. This will be called again once contents are available.
+ if (!model() || model()->rowCount() == 0) {
+ if (refreshSpan)
+ refreshSpanColumn();
+ return;
+ }
+
+ // Resize without attempting to fix up the columns.
+ setSpanColumn(-1);
resizeColumnToContents(StackLevelColumn);
+ resizeColumnToContents(StackFileNameColumn);
resizeColumnToContents(StackLineNumberColumn);
- showAddressColumn(action(UseAddressInStackView)->isChecked());
+ resizeColumnToContents(StackAddressColumn);
+ setSpanColumn(StackFunctionNameColumn);
+ m_contentsAdjusted = true;
}
} // namespace Internal
diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h
index 5439ead73f..79f2974e82 100644
--- a/src/plugins/debugger/stackwindow.h
+++ b/src/plugins/debugger/stackwindow.h
@@ -34,17 +34,16 @@ namespace Internal {
class StackTreeView : public Utils::BaseTreeView
{
- Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::StackTreeView)
-
public:
- StackTreeView();
+ explicit StackTreeView(QWidget *parent = nullptr);
private:
void setModel(QAbstractItemModel *model) override;
void showAddressColumn(bool on);
- void reloadFullStack();
- void copyContentsToClipboard();
+ void adjustForContents(bool refreshSpan = false);
+
+ bool m_contentsAdjusted = false;
};
} // namespace Internal