[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdevelop/5.3] kdevplatform/sublime: Sublime: Fix crash when changing areas
From: Amish Naidu <null () kde ! org>
Date: 2018-09-27 17:14:00
Message-ID: E1g5ZrU-0008DO-5S () code ! kde ! org
[Download RAW message or body]
Git commit 7169b3ac931c88783688702ef6013d3d536c68f4 by Amish Naidu.
Committed on 27/09/2018 at 17:12.
Pushed by anaidu into branch '5.3'.
Sublime: Fix crash when changing areas
Summary:
Fixes regression introduced in D15450 by making IdealButtonBarLayout derive \
from QBoxLayout instead of QLayout and thus delete most operations to Qt \
instead of manually handling them, removing the bugged implementation.
Added minimumSizeHint in IdealToolButton to prevent it from being resized
to zero.
IdealButtonBarLayout is now a child layout for vertical bars as well,
the top level layout is stretched and allows for context menu.
BUG: 399025
Reviewers: #kdevelop, kossebau, rjvbb
Reviewed By: #kdevelop, kossebau, rjvbb
Subscribers: kossebau, rjvbb, kdevelop-devel
Tags: #kdevelop
Differential Revision: https://phabricator.kde.org/D15625
M +7 -3 kdevplatform/sublime/idealbuttonbarwidget.cpp
M +24 -247 kdevplatform/sublime/ideallayout.cpp
M +5 -30 kdevplatform/sublime/ideallayout.h
M +40 -0 kdevplatform/sublime/idealtoolbutton.cpp
M +2 -0 kdevplatform/sublime/idealtoolbutton.h
https://commits.kde.org/kdevelop/7169b3ac931c88783688702ef6013d3d536c68f4
diff --git a/kdevplatform/sublime/idealbuttonbarwidget.cpp \
b/kdevplatform/sublime/idealbuttonbarwidget.cpp index \
d76597411e..24e7899119 100644
--- a/kdevplatform/sublime/idealbuttonbarwidget.cpp
+++ b/kdevplatform/sublime/idealbuttonbarwidget.cpp
@@ -110,12 +110,12 @@ \
IdealButtonBarWidget::IdealButtonBarWidget(Qt::DockWidgetArea area, \
setContextMenuPolicy(Qt::CustomContextMenu);
setToolTip(i18nc("@info:tooltip", "Right click to add new tool \
views."));
+ m_buttonsLayout = new IdealButtonBarLayout(orientation(), this);
if (area == Qt::BottomDockWidgetArea)
{
QBoxLayout *statusLayout = new QBoxLayout(QBoxLayout::LeftToRight, \
this); statusLayout->setMargin(0);
- m_buttonsLayout = new IdealButtonBarLayout(orientation());
statusLayout->addLayout(m_buttonsLayout);
statusLayout->addStretch(1);
@@ -125,9 +125,13 @@ \
IdealButtonBarWidget::IdealButtonBarWidget(Qt::DockWidgetArea area, \
cornerLayout->setMargin(0); cornerLayout->setSpacing(0);
statusLayout->addWidget(m_corner);
+ } else {
+ QBoxLayout *superLayout = new QBoxLayout(QBoxLayout::TopToBottom, \
this); + superLayout->setMargin(0);
+
+ superLayout->addLayout(m_buttonsLayout);
+ superLayout->addStretch(1);
}
- else
- m_buttonsLayout = new IdealButtonBarLayout(orientation(), this);
}
QAction* IdealButtonBarWidget::addWidget(IdealDockWidget *dock,
diff --git a/kdevplatform/sublime/ideallayout.cpp \
b/kdevplatform/sublime/ideallayout.cpp index 8bc4347919..41a328726b 100644
--- a/kdevplatform/sublime/ideallayout.cpp
+++ b/kdevplatform/sublime/ideallayout.cpp
@@ -24,42 +24,37 @@
#include <QStyle>
#include <QWidget>
+#include <QEvent>
#include <numeric>
using namespace Sublime;
-IdealButtonBarLayout::IdealButtonBarLayout(Qt::Orientation orientation, \
QWidget *parent)
- : QLayout(parent)
- , _orientation(orientation)
- , _height(0)
-
+namespace
{
- setContentsMargins(0, 0, 0, 0);
- invalidate();
-}
-void IdealButtonBarLayout::invalidate()
-{
- m_minSizeDirty = true;
- m_sizeHintDirty = true;
- m_layoutDirty = true;
- QLayout::invalidate();
-}
+ QBoxLayout::Direction toDirection(Qt::Orientation orientation)
+ {
+ return orientation == Qt::Horizontal ? QBoxLayout::LeftToRight : \
QBoxLayout::TopToBottom; + }
-IdealButtonBarLayout::~IdealButtonBarLayout()
-{
- qDeleteAll(_items);
}
-void IdealButtonBarLayout::setHeight(int height)
+IdealButtonBarLayout::IdealButtonBarLayout(Qt::Orientation orientation, \
QWidget* styleParent) + : QBoxLayout(toDirection(orientation)) // \
creating a child layout, styleParent is only saved for style + , \
m_styleParentWidget(styleParent) + , _orientation(orientation)
{
- Q_ASSERT(orientation() == Qt::Vertical);
- _height = height;
+ if (m_styleParentWidget) {
+ m_styleParentWidget->installEventFilter(this);
+ }
- (void) invalidate();
+ setContentsMargins(0, 0, 0, 0);
+ setSpacing(buttonSpacing());
}
+IdealButtonBarLayout::~IdealButtonBarLayout() = default;
+
Qt::Orientation IdealButtonBarLayout::orientation() const
{
return _orientation;
@@ -70,237 +65,19 @@ Qt::Orientations \
IdealButtonBarLayout::expandingDirections() const return orientation();
}
-QSize IdealButtonBarLayout::minimumSize() const
-{
- // The code below appears to be completely wrong --
- // it will return the maximum size of a single button, not any
- // estimate as to how much space is necessary to draw all buttons
- // in a minimally acceptable way.
- if (m_minSizeDirty) {
- if (orientation() == Qt::Vertical) {
- const int width = doVerticalLayout(QRect(0, 0, 0, _height), \
false);
- return QSize(width, 0);
- }
-
- m_min = QSize(0, 0);
- for (QLayoutItem* item : _items) {
- m_min = m_min.expandedTo(item->minimumSize());
- }
-
- m_minSizeDirty = false;
- }
- return m_min;
-}
-
-QSize IdealButtonBarLayout::sizeHint() const
-{
- if (m_sizeHintDirty) {
- const int buttonSpacing = this->buttonSpacing();
-
- int orientationSize = 0;
- int crossSize = 0;
-
- bool first = true;
- for (QLayoutItem *item : _items) {
- QSize hint = item->sizeHint();
- int orientationSizeHere;
- int crossSizeHere;
- if (orientation() == Qt::Vertical)
- {
- orientationSizeHere = hint.height();
- crossSizeHere = hint.width();
- }
- else
- {
- orientationSizeHere = hint.width();
- crossSizeHere = hint.height();
- }
-
- if (first)
- {
- crossSize = crossSizeHere;
- }
- else
- {
- orientationSize += buttonSpacing;
- }
- orientationSize += orientationSizeHere;
- first = false;
- }
-
- if (orientation() == Qt::Vertical)
- m_hint = QSize(crossSize, orientationSize);
- else
- m_hint = QSize(orientationSize, crossSize);
-
- if (!_items.empty())
- {
- /* If we have no items, just use (0, 0) as hint, don't
- append any margins. */
- int l, t, r, b;
- getContentsMargins(&l, &t, &r, &b);
- m_hint += QSize(l+r, t+b);
- }
-
- m_sizeHintDirty = false;
- }
- return m_hint;
-}
-
-void IdealButtonBarLayout::setGeometry(const QRect &rect)
-{
- if (m_layoutDirty || rect != geometry()) {
- if (orientation() == Qt::Vertical)
- doVerticalLayout(rect);
- else
- doHorizontalLayout(rect);
- }
-}
-
-void IdealButtonBarLayout::addItem(QLayoutItem *item)
-{
- _items.append(item);
- invalidate();
-}
-
-QLayoutItem* IdealButtonBarLayout::itemAt(int index) const
-{
- return _items.value(index, nullptr);
-}
-
-QLayoutItem* IdealButtonBarLayout::takeAt(int index)
-{
- if (index >= 0 && index < _items.count())
- return _items.takeAt(index);
- invalidate();
- return nullptr;
-}
-
-int IdealButtonBarLayout::count() const
-{
- return _items.count();
-}
-
int IdealButtonBarLayout::buttonSpacing() const
{
- auto pw = parentWidget();
- return pw ? pw->style()->pixelMetric(QStyle::PM_ToolBarItemSpacing) : \
0;
-}
-
-
-int IdealButtonBarLayout::doVerticalLayout(const QRect &rect, bool \
updateGeometry) const
-{
- const int buttonSpacing = this->buttonSpacing();
-
- int l, t, r, b;
- getContentsMargins(&l, &t, &r, &b);
- int x = rect.x() + l;
- int y = rect.y() + t;
- int currentLineWidth = 0;
-
- if (_items.empty()) {
- return x + currentLineWidth + r;
- }
-
- const bool shrink = rect.height() < sizeHint().height();
-
- const int maximumHeight = rect.height() / _items.size();
- int shrinkedHeight = -1;
-
- if (shrink) {
- int smallItemCount = 0;
- const int surplus = std::accumulate(_items.begin(), _items.end(), \
0, [maximumHeight, &smallItemCount](int acc, QLayoutItem* \
item) {
- const int itemHeight = item->sizeHint().height();
- if (itemHeight <= maximumHeight) {
- acc += maximumHeight - itemHeight;
- ++smallItemCount;
- }
- return acc;
- });
-
- Q_ASSERT(_items.size() != smallItemCount); // should be true since \
rect.width != sizeHint.width
- // evenly distribute surplus height over large items
- shrinkedHeight = maximumHeight + surplus / (_items.size() - \
smallItemCount); + if (!m_styleParentWidget) {
+ return 0;
}
-
- for (QLayoutItem* item : _items) {
- const QSize itemSizeHint = item->sizeHint();
- const int itemWidth = itemSizeHint.width();
- int itemHeight = itemSizeHint.height();
-
- if (shrink && itemSizeHint.height() > maximumHeight) {
- itemHeight = shrinkedHeight;
- }
-
- if (updateGeometry) {
- item->setGeometry(QRect(x, y, itemWidth, itemHeight));
- }
-
- currentLineWidth = qMax(currentLineWidth, itemWidth);
-
- y += itemHeight + buttonSpacing;
- }
-
- m_layoutDirty = updateGeometry;
-
- return x + currentLineWidth + r;
+ return m_styleParentWidget->style()->pixelMetric(QStyle::PM_ToolBarItemSpacing);
}
-int IdealButtonBarLayout::doHorizontalLayout(const QRect &rect, bool \
updateGeometry) const +bool IdealButtonBarLayout::eventFilter(QObject* \
watched, QEvent* event) {
- const int buttonSpacing = this->buttonSpacing();
-
- int l, t, r, b;
- getContentsMargins(&l, &t, &r, &b);
- int x = rect.x() + l;
- int y = rect.y() + t;
- int currentLineHeight = 0;
-
- if (_items.empty()) {
- return y + currentLineHeight + b;
+ if (event->type() == QEvent::StyleChange) {
+ setSpacing(buttonSpacing());
}
- const bool shrink = rect.width() < sizeHint().width();
-
- const int maximumWidth = rect.width() / _items.size();
- int shrinkedWidth = -1;
-
- if (shrink) {
- int smallItemCount = 0;
- const int surplus = std::accumulate(_items.begin(), _items.end(), \
0, [maximumWidth, &smallItemCount](int acc, QLayoutItem* \
item) {
- const int itemWidth = item->sizeHint().width();
- if (itemWidth <= maximumWidth) {
- acc += maximumWidth - itemWidth;
- ++smallItemCount;
- }
- return acc;
- });
-
- Q_ASSERT(_items.size() != smallItemCount); // should be true since \
rect.width != sizeHint.width
- // evenly distribute surplus width on the large items
- shrinkedWidth = maximumWidth + surplus / (_items.size() - \
smallItemCount);
- }
-
- for (QLayoutItem* item : _items) {
- const QSize itemSizeHint = item->sizeHint();
- int itemWidth = itemSizeHint.width();
- const int itemHeight = itemSizeHint.height();
-
- if (shrink && itemSizeHint.width() > maximumWidth) {
- itemWidth = shrinkedWidth;
- }
-
- if (updateGeometry) {
- item->setGeometry(QRect(x, y, itemWidth, itemHeight));
- }
-
- currentLineHeight = qMax(currentLineHeight, itemHeight);
-
- x += itemWidth + buttonSpacing;
- }
-
- m_layoutDirty = updateGeometry;
-
- return y + currentLineHeight + b;
+ return QBoxLayout::eventFilter(watched, event);
}
-
diff --git a/kdevplatform/sublime/ideallayout.h \
b/kdevplatform/sublime/ideallayout.h index faf2fac077..2983dd6336 100644
--- a/kdevplatform/sublime/ideallayout.h
+++ b/kdevplatform/sublime/ideallayout.h
@@ -22,59 +22,34 @@
#ifndef KDEVPLATFORM_SUBLIME_IDEALLAYOUT_H
#define KDEVPLATFORM_SUBLIME_IDEALLAYOUT_H
-#include <QLayout>
+#include <QBoxLayout>
#include "sublimedefs.h"
namespace Sublime {
-class IdealButtonBarLayout: public QLayout
+class IdealButtonBarLayout: public QBoxLayout
{
Q_OBJECT
public:
- explicit IdealButtonBarLayout(Qt::Orientation orientation, QWidget \
*parent = nullptr); + IdealButtonBarLayout(Qt::Orientation orientation, \
QWidget* styleParent);
~IdealButtonBarLayout() override;
- void setHeight(int height);
-
inline Qt::Orientation orientation() const;
Qt::Orientations expandingDirections() const override;
- QSize minimumSize() const override;
-
- QSize sizeHint() const override;
-
- void setGeometry(const QRect &rect) override;
-
- void addItem(QLayoutItem *item) override;
-
- QLayoutItem* itemAt(int index) const override;
-
- QLayoutItem* takeAt(int index) override;
-
- int count() const override;
-
- void invalidate() override;
-
protected:
- int doVerticalLayout(const QRect &rect, bool updateGeometry = true) \
const;
- int doHorizontalLayout(const QRect &rect, bool updateGeometry = true) \
const; + bool eventFilter(QObject* watched, QEvent* event) override;
int buttonSpacing() const;
private:
- QList<QLayoutItem *> _items;
+ QWidget* const m_styleParentWidget;
const Qt::Orientation _orientation;
- int _height;
- mutable bool m_minSizeDirty : 1;
- mutable bool m_sizeHintDirty : 1;
- mutable bool m_layoutDirty : 1;
- mutable QSize m_min;
- mutable QSize m_hint;
};
}
diff --git a/kdevplatform/sublime/idealtoolbutton.cpp \
b/kdevplatform/sublime/idealtoolbutton.cpp index 01dbfefe24..564042b463 \
100644
--- a/kdevplatform/sublime/idealtoolbutton.cpp
+++ b/kdevplatform/sublime/idealtoolbutton.cpp
@@ -2,6 +2,7 @@
Copyright 2007 Roberto Raggi <roberto@kdevelop.org>
Copyright 2007 Hamish Rodda <rodda@kde.org>
Copyright 2011 Alexander Dymo <adymo@kdevelop.org>
+ Copyright 2018 Amish Naidu <amhndu@gmail.com>
Permission to use, copy, modify, distribute, and sell this software and \
its documentation for any purpose is hereby granted without fee, provided \
that @@ -24,6 +25,7 @@
#include <KAcceleratorManager>
#include <QStyleOption>
#include <QStylePainter>
+#include <QApplication>
IdealToolButton::IdealToolButton(Qt::DockWidgetArea area, QWidget *parent)
: QToolButton(parent), _area(area)
@@ -35,6 +37,14 @@ IdealToolButton::IdealToolButton(Qt::DockWidgetArea \
area, QWidget *parent) setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
setContextMenuPolicy(Qt::CustomContextMenu);
+
+ QSizePolicy sizePolicy = this->sizePolicy();
+ if (orientation() == Qt::Horizontal) {
+ sizePolicy.setHorizontalPolicy(QSizePolicy::Maximum);
+ } else {
+ sizePolicy.setVerticalPolicy(QSizePolicy::Maximum);
+ }
+ setSizePolicy(sizePolicy);
}
Qt::Orientation IdealToolButton::orientation() const
@@ -86,6 +96,36 @@ QSize IdealToolButton::sizeHint() const
}
}
+QSize IdealToolButton::minimumSizeHint() const
+{
+ ensurePolished();
+
+ QStyleOptionToolButton opt;
+ initStyleOption(&opt);
+
+ QSize minimumSize;
+ // if style has icons, minimumSize is the size of the icon
+ if (toolButtonStyle() != Qt::ToolButtonTextOnly && !opt.icon.isNull()) \
{ + minimumSize = opt.iconSize;
+ if (_area == Qt::LeftDockWidgetArea || _area == \
Qt::RightDockWidgetArea) { + minimumSize.transpose();
+ }
+ } else {
+ // if no icon, set an arbitrary minimum size
+ QFontMetrics fm = fontMetrics();
+ minimumSize = fm.size(Qt::TextShowMnemonic, opt.text.left(4));
+ }
+
+ minimumSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, \
minimumSize, this). + \
expandedTo(QApplication::globalStrut()); +
+ if (_area == Qt::TopDockWidgetArea || _area == \
Qt::BottomDockWidgetArea) { + return minimumSize;
+ }
+ return minimumSize.transposed();
+}
+
+
void IdealToolButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
diff --git a/kdevplatform/sublime/idealtoolbutton.h \
b/kdevplatform/sublime/idealtoolbutton.h index 3497e39018..7449172d92 \
100644
--- a/kdevplatform/sublime/idealtoolbutton.h
+++ b/kdevplatform/sublime/idealtoolbutton.h
@@ -36,6 +36,8 @@ public:
QSize sizeHint() const override;
+ QSize minimumSizeHint() const override;
+
protected:
void paintEvent(QPaintEvent *event) override;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic