Krita Source Code Documentation
Loading...
Searching...
No Matches
KoDockWidgetTitleBar.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2007 Marijn Kruisselbrink <mkruisselbrink@kde.org>
3 SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
4 SPDX-FileCopyrightText: 2021 Alvin Wong <alvin@alvinhc.com>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
12
13#include <KoIcon.h>
14#include <kis_icon_utils.h>
15
16#include <WidgetsDebug.h>
17#include <klocalizedstring.h>
18
19#include <QAbstractButton>
20#include <QAction>
21#include <QHBoxLayout>
22#include <QLabel>
23#include <QStyle>
24#include <QStylePainter>
25#include <QStyleOptionFrame>
26
27#include <KSqueezedTextLabel>
28
29static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
30{
31 return (dockwidget->features() & feature) == feature;
32}
33
34constexpr int SPACING = 6;
35
37 : QWidget(dockWidget), d(new Private(this))
38{
39 d->floatIcon = kisIcon("docker_float");
40 d->floatButton = new KoDockWidgetTitleBarButton(this);
41 d->floatButton->setIcon(d->floatIcon);
42 connect(d->floatButton, SIGNAL(clicked()), SLOT(toggleFloating()));
43 d->floatButton->setVisible(true);
44 d->floatButton->setToolTip(i18nc("@info:tooltip", "Float Docker"));
45 d->floatButton->setStyleSheet("border: 0");
46
47 d->removeIcon = kisIcon("docker_close");
48 d->closeButton = new KoDockWidgetTitleBarButton(this);
49 d->closeButton->setIcon(d->removeIcon);
50 connect(d->closeButton, SIGNAL(clicked()), dockWidget, SLOT(close()));
51 d->closeButton->setVisible(true);
52 d->closeButton->setToolTip(i18nc("@info:tooltip", "Close Docker"));
53 d->closeButton->setStyleSheet("border: 0"); // border makes the header busy looking (appears on some OSs)
54
55 d->lockIcon = kisIcon("docker_lock_a");
56 d->lockButton = new KoDockWidgetTitleBarButton(this);
57 d->lockButton->setCheckable(true);
58 d->lockButton->setIcon(d->lockIcon);
59 connect(d->lockButton, SIGNAL(toggled(bool)), SLOT(setLocked(bool)));
60 d->lockButton->setVisible(true);
61 d->lockButton->setToolTip(i18nc("@info:tooltip", "Lock Docker"));
62 d->lockButton->setStyleSheet("border: 0");
63
64 d->updateButtonSizes();
65
66 d->titleLabel = new KSqueezedTextLabel(this);
67 d->titleLabel->setTextElideMode(Qt::ElideRight);
68 d->titleLabel->setText(dockWidget->windowTitle());
69
70 QHBoxLayout *layout = new QHBoxLayout(this);
71 layout->setContentsMargins(2, 0, 2, 0);
72 layout->setSpacing(SPACING);
73 layout->addWidget(d->lockButton);
74 layout->addWidget(d->titleLabel, 1);
75 layout->addWidget(d->floatButton);
76 layout->addWidget(d->closeButton);
77
78 connect(dockWidget, SIGNAL(featuresChanged(QDockWidget::DockWidgetFeatures)), SLOT(featuresChanged(QDockWidget::DockWidgetFeatures)));
79 connect(dockWidget, SIGNAL(topLevelChanged(bool)), SLOT(topLevelChanged(bool)));
80 connect(dockWidget, SIGNAL(windowTitleChanged(const QString &)), SLOT(dockWidgetTitleChanged(const QString &)));
81
82 d->featuresChanged(QDockWidget::NoDockWidgetFeatures);
83}
84
89
91{
92 QStylePainter p(this);
93
94 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget());
95
96 int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) : 0;
97 int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q);
98
99 QStyleOptionDockWidget titleOpt;
100 titleOpt.initFrom(q);
101
102 QSize lockButtonSize(0,0);
103 if (d->lockButton->isVisible()) {
104 lockButtonSize = d->lockButton->size();
105 }
106
107 // To improve the look with Fusion which has weird 13x15 button sizes
108 int fusionTextOffset = 0;
109 QRect styleTestRect = q->style()->subElementRect(QStyle::SE_DockWidgetFloatButton, &titleOpt, q);
110 if (styleTestRect.width() < 16) {
111 fusionTextOffset = d->lockButton->x();
112 }
113
114 titleOpt.rect = QRect(QPoint(fw + mw + lockButtonSize.width() + fusionTextOffset, 0),
115 QSize(geometry().width() - (fw * 2) - mw - lockButtonSize.width(), geometry().height()));
116 // We don't print the title text here. Instead, we have a QLabel.
117 // titleOpt.title = q->windowTitle();
118 // FIXME: Maybe we just shouldn't use a QStylePainter at all?
119 titleOpt.title = QString();
120 titleOpt.closable = hasFeature(q, QDockWidget::DockWidgetClosable);
121 titleOpt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable);
122 p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt);
123}
124
126{
127 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget());
128
129 if (q->isFloating() || (width() < (d->closeButton->width() + d->floatButton->width() + d->lockButton->width()) + 32)) {
130 d->lockButton->setVisible(false);
131 } else {
132 d->lockButton->setVisible(true);
133 }
134}
135
137{
138 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget());
139
140 d->locked = locked;
141 d->lockButton->blockSignals(true);
142 d->lockButton->setChecked(locked);
143 d->lockButton->blockSignals(false);
144
145 if (locked) {
146 d->features = q->features();
147 q->setFeatures(QDockWidget::NoDockWidgetFeatures);
148 }
149 else {
150 q->setFeatures(d->features);
151 }
152
153 q->toggleViewAction()->setEnabled(!locked);
154 d->closeButton->setEnabled(!locked);
155 d->floatButton->setEnabled(!locked);
156 d->floatButton->setVisible(!locked);
157
158 d->updateIcons();
159 q->setProperty("Locked", locked);
160}
161
163{
164 d->updateIcons();
165}
166
167void KoDockWidgetTitleBar::Private::toggleFloating()
168{
169 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget());
170
171 q->setFloating(!q->isFloating());
172 updateIcons();
173}
174
175void KoDockWidgetTitleBar::Private::topLevelChanged(bool topLevel)
176{
177 lockButton->setEnabled(!topLevel);
178 updateIcons();
179}
180
181void KoDockWidgetTitleBar::Private::featuresChanged(QDockWidget::DockWidgetFeatures)
182{
183 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget());
184
185 closeButton->setVisible(hasFeature(q, QDockWidget::DockWidgetClosable));
186 floatButton->setVisible(hasFeature(q, QDockWidget::DockWidgetFloatable));
187
188 updateButtonSizes();
189 thePublic->resizeEvent(0);
190}
191
192void KoDockWidgetTitleBar::Private::dockWidgetTitleChanged(const QString &title)
193{
194 titleLabel->setText(title);
195}
196
197
198void KoDockWidgetTitleBar::Private::updateIcons()
199{
200 lockIcon = (!locked) ? kisIcon("docker_lock_a") : kisIcon("docker_lock_b");
201 lockButton->setIcon(lockIcon);
202
203 // this method gets called when switching themes, so update all of the themed icons now
204 floatButton->setIcon(kisIcon("docker_float"));
205 closeButton->setIcon(kisIcon("docker_close"));
206
207 thePublic->resizeEvent(0);
208}
209
210void KoDockWidgetTitleBar::Private::updateButtonSizes()
211{
212 const QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget());
213
214 const int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q) : 0;
215
216 QStyleOptionDockWidget opt;
217 opt.initFrom(q);
218 opt.rect = QRect(QPoint(fw, fw), QSize(thePublic->geometry().width() - (fw * 2), thePublic->geometry().height() - (fw * 2)));
219 opt.title = q->windowTitle();
220 // Originally it was:
221 // opt.closable = hasFeature(q, QDockWidget::DockWidgetClosable);
222 // but I think we better just always pretend the close button is visible to
223 // get the button size.
224 opt.closable = true;
225 opt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable);
226
227 // Again, we just always use the size of the close button, so we don't
228 // need to get the size of the float button...
229 // QRect floatRect = q->style()->subElementRect(QStyle::SE_DockWidgetFloatButton, &opt, q);
230 const QRect closeRect = q->style()->subElementRect(QStyle::SE_DockWidgetCloseButton, &opt, q);
231 QSize buttonSize = closeRect.size();
232 if (buttonSize.width() < 16) {
233 // To improve the look with Fusion which has weird 13x15 button sizes
234 buttonSize = QSize(16, 16);
235 } else if (buttonSize.width() != buttonSize.height()) {
236 // Just make sure the button is square...
237 buttonSize.setHeight(buttonSize.width());
238 }
239
240 floatButton->setFixedSize(buttonSize);
241 closeButton->setFixedSize(buttonSize);
242 lockButton->setFixedSize(buttonSize);
243}
244
245//have to include this because of Q_PRIVATE_SLOT
246#include "moc_KoDockWidgetTitleBar.cpp"
const Params2D p
static bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
constexpr int SPACING
static int buttonSize(int screen)
Definition KoToolBox.cpp:41
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
A custom title bar button for dock widgets.
void paintEvent(QPaintEvent *event) override
reimplemented from QWidget
void featuresChanged(QDockWidget::DockWidgetFeatures features)
void resizeEvent(QResizeEvent *event) override
reimplemented from QWidget
void dockWidgetTitleChanged(const QString &title)
void topLevelChanged(bool topLevel)
KoDockWidgetTitleBar(QDockWidget *dockWidget)
#define kisIcon(name)
Definition kis_icon.h:26