Warning, file /office/calligra/libs/widgets/KoDockWidgetTitleBar.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (c) 2007 Marijn Kruisselbrink <mkruisselbrink@kde.org> 0003 Copyright (C) 2007 Thomas Zander <zander@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KoDockWidgetTitleBar.h" 0022 #include "KoDockWidgetTitleBar_p.h" 0023 #include "KoDockWidgetTitleBarButton.h" 0024 0025 #include <KoIcon.h> 0026 0027 #include <WidgetsDebug.h> 0028 #include <klocalizedstring.h> 0029 0030 #include <QAbstractButton> 0031 #include <QAction> 0032 #include <QLabel> 0033 #include <QLayout> 0034 #include <QStyle> 0035 #include <QStylePainter> 0036 #include <QStyleOptionFrame> 0037 0038 static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature) 0039 { 0040 return (dockwidget->features() & feature) == feature; 0041 } 0042 0043 static QIcon openIcon(QDockWidget *q) 0044 { 0045 QIcon icon = q->style()->standardIcon(QStyle::SP_TitleBarShadeButton); 0046 return icon.isNull() ? koIcon("arrow-down") : icon; 0047 } 0048 0049 static QIcon closeIcon(QDockWidget *q) 0050 { 0051 QIcon icon = q->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton); 0052 return icon.isNull() ? koIcon("arrow-right") : icon; 0053 } 0054 0055 0056 KoDockWidgetTitleBar::KoDockWidgetTitleBar(QDockWidget* dockWidget) 0057 : QWidget(dockWidget), d(new Private(this)) 0058 { 0059 QDockWidget *q = dockWidget; 0060 0061 d->floatButton = new KoDockWidgetTitleBarButton(this); 0062 d->floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, nullptr, q)); 0063 connect(d->floatButton, SIGNAL(clicked()), SLOT(toggleFloating())); 0064 d->floatButton->setVisible(true); 0065 d->floatButton->setToolTip(i18nc("@info:tooltip", "Float Docker")); 0066 d->floatButton->setStyleSheet("border: 0"); 0067 0068 d->closeButton = new KoDockWidgetTitleBarButton(this); 0069 d->closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, nullptr, q)); 0070 connect(d->closeButton, SIGNAL(clicked()), q, SLOT(close())); 0071 d->closeButton->setVisible(true); 0072 d->closeButton->setToolTip(i18nc("@info:tooltip", "Close Docker")); 0073 d->closeButton->setStyleSheet("border: 0"); // border makes the header busy looking (appears on some OSs) 0074 0075 d->collapseButton = new KoDockWidgetTitleBarButton(this); 0076 d->collapseButton->setIcon(openIcon(q)); 0077 connect(d->collapseButton, SIGNAL(clicked()), SLOT(toggleCollapsed())); 0078 d->collapseButton->setVisible(true); 0079 d->collapsable = true; 0080 d->collapseButton->setToolTip(i18nc("@info:tooltip", "Collapse Docker")); 0081 d->collapseButton->setStyleSheet("border: 0"); 0082 0083 d->lockButton = new KoDockWidgetTitleBarButton(this); 0084 d->lockButton->setCheckable(true); 0085 d->lockButton->setIcon(koIcon("object-unlocked")); 0086 connect(d->lockButton, SIGNAL(toggled(bool)), SLOT(setLocked(bool))); 0087 d->lockButton->setVisible(true); 0088 d->lockable = true; 0089 d->lockButton->setToolTip(i18nc("@info:tooltip", "Lock Docker")); 0090 d->lockButton->setStyleSheet("border: 0"); 0091 0092 connect(dockWidget, SIGNAL(featuresChanged(QDockWidget::DockWidgetFeatures)), SLOT(featuresChanged(QDockWidget::DockWidgetFeatures))); 0093 connect(dockWidget, SIGNAL(topLevelChanged(bool)), SLOT(topLevelChanged(bool))); 0094 0095 d->featuresChanged(0); 0096 } 0097 0098 KoDockWidgetTitleBar::~KoDockWidgetTitleBar() 0099 { 0100 delete d; 0101 } 0102 0103 QSize KoDockWidgetTitleBar::minimumSizeHint() const 0104 { 0105 return sizeHint(); 0106 } 0107 0108 QSize KoDockWidgetTitleBar::sizeHint() const 0109 { 0110 if (isHidden()) { 0111 return QSize(0, 0); 0112 } 0113 0114 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget()); 0115 0116 int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); 0117 int fw = q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, q); 0118 0119 // get size of buttons... 0120 QSize closeSize(0, 0); 0121 if (d->closeButton && hasFeature(q, QDockWidget::DockWidgetClosable)) { 0122 closeSize = d->closeButton->sizeHint(); 0123 } 0124 0125 QSize floatSize(0, 0); 0126 if (d->floatButton && hasFeature(q, QDockWidget::DockWidgetFloatable)) { 0127 floatSize = d->floatButton->sizeHint(); 0128 } 0129 0130 QSize hideSize(0, 0); 0131 if (d->collapseButton && d->collapsable) { 0132 hideSize = d->collapseButton->sizeHint(); 0133 } 0134 0135 QSize lockSize(0, 0); 0136 if (d->lockButton && d->lockable) { 0137 lockSize = d->lockButton->sizeHint(); 0138 } 0139 0140 int buttonHeight = qMax(qMax(qMax(closeSize.height(), floatSize.height()), hideSize.height()), lockSize.height()) + 2; 0141 int buttonWidth = closeSize.width() + floatSize.width() + hideSize.width() + lockSize.width(); 0142 0143 int height = buttonHeight; 0144 if (d->textVisibilityMode == FullTextAlwaysVisible) { 0145 // get font size 0146 QFontMetrics titleFontMetrics = q->fontMetrics(); 0147 int fontHeight = titleFontMetrics.lineSpacing() + 2 * mw; 0148 0149 height = qMax(height, fontHeight); 0150 } 0151 0152 /* 0153 * Calculate the width of title and add to the total width of the docker window when collapsed. 0154 */ 0155 const int titleWidth = 0156 (d->textVisibilityMode == FullTextAlwaysVisible) ? (q->fontMetrics().width(q->windowTitle()) + 2*mw) : 0157 0; 0158 0159 if (d->preCollapsedWidth > 0) { 0160 return QSize(d->preCollapsedWidth, height); 0161 } 0162 else { 0163 if (d->textVisibilityMode == FullTextAlwaysVisible) { 0164 return QSize(buttonWidth /*+ height*/ + 2*mw + 2*fw + titleWidth, height); 0165 } 0166 else { 0167 if (q->widget()) { 0168 return QSize(qMin(q->widget()->sizeHint().width(), buttonWidth), height); 0169 } 0170 else { 0171 return QSize(buttonWidth, height); 0172 } 0173 } 0174 } 0175 } 0176 0177 void KoDockWidgetTitleBar::paintEvent(QPaintEvent*) 0178 { 0179 QStylePainter p(this); 0180 0181 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget()); 0182 0183 int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, nullptr, q) : 0; 0184 int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, nullptr, q); 0185 0186 QStyleOptionDockWidget titleOpt; 0187 titleOpt.initFrom(q); 0188 0189 QSize collapseButtonSize(0,0); 0190 if (d->collapsable) { 0191 collapseButtonSize = d->collapseButton->size(); 0192 } 0193 0194 QSize lockButtonSize(0,0); 0195 if (d->lockable) { 0196 lockButtonSize = d->lockButton->size(); 0197 } 0198 0199 titleOpt.rect = QRect(QPoint(fw + mw + collapseButtonSize.width() + lockButtonSize.width(), 0), 0200 QSize(geometry().width() - (fw * 2) - mw - collapseButtonSize.width() - lockButtonSize.width(), geometry().height())); 0201 titleOpt.title = q->windowTitle(); 0202 titleOpt.closable = hasFeature(q, QDockWidget::DockWidgetClosable); 0203 titleOpt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable); 0204 p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt); 0205 } 0206 0207 void KoDockWidgetTitleBar::resizeEvent(QResizeEvent*) 0208 { 0209 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget()); 0210 0211 int fw = q->isFloating() ? q->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, nullptr, q) : 0; 0212 0213 QStyleOptionDockWidget opt; 0214 opt.initFrom(q); 0215 opt.rect = QRect(QPoint(fw, fw), QSize(geometry().width() - (fw * 2), geometry().height() - (fw * 2))); 0216 opt.title = q->windowTitle(); 0217 opt.closable = hasFeature(q, QDockWidget::DockWidgetClosable); 0218 opt.floatable = hasFeature(q, QDockWidget::DockWidgetFloatable); 0219 0220 QRect floatRect = q->style()->subElementRect(QStyle::SE_DockWidgetFloatButton, &opt, q); 0221 if (!floatRect.isNull()) 0222 d->floatButton->setGeometry(floatRect); 0223 0224 QRect closeRect = q->style()->subElementRect(QStyle::SE_DockWidgetCloseButton, &opt, q); 0225 if (!closeRect.isNull()) 0226 d->closeButton->setGeometry(closeRect); 0227 0228 int top = fw; 0229 if (!floatRect.isNull()) 0230 top = floatRect.y(); 0231 else if (!closeRect.isNull()) 0232 top = closeRect.y(); 0233 0234 QSize size = d->collapseButton->size(); 0235 if (!closeRect.isNull()) { 0236 size = d->closeButton->size(); 0237 } else if (!floatRect.isNull()) { 0238 size = d->floatButton->size(); 0239 } 0240 QRect collapseRect = QRect(QPoint(fw, top), size); 0241 d->collapseButton->setGeometry(collapseRect); 0242 0243 size = d->lockButton->size(); 0244 0245 if (!closeRect.isNull()) { 0246 size = d->closeButton->size(); 0247 } else if (!floatRect.isNull()) { 0248 size = d->floatButton->size(); 0249 } 0250 0251 int offset = 0; 0252 0253 if (d->collapsable) { 0254 offset = collapseRect.width(); 0255 } 0256 QRect lockRect = QRect(QPoint(fw + 2 + offset, top), size); 0257 d->lockButton->setGeometry(lockRect); 0258 0259 if (width() < (closeRect.width() + lockRect.width()) + 50) { 0260 d->collapsable = false; 0261 d->collapseButton->setVisible(false); 0262 d->lockButton->setVisible(false); 0263 d->lockable = false; 0264 } else { 0265 d->collapsable = d->collapsableSet; 0266 d->collapseButton->setVisible(d->collapsableSet); 0267 d->lockButton->setVisible(true); 0268 d->lockable = true; 0269 } 0270 } 0271 0272 void KoDockWidgetTitleBar::setCollapsed(bool collapsed) 0273 { 0274 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget()); 0275 if (q && q->widget() && q->widget()->isHidden() != collapsed) 0276 d->toggleCollapsed(); 0277 } 0278 0279 void KoDockWidgetTitleBar::setLocked(bool locked) 0280 { 0281 QDockWidget *q = qobject_cast<QDockWidget*>(parentWidget()); 0282 0283 d->locked = locked; 0284 d->lockButton->blockSignals(true); 0285 d->lockButton->setChecked(locked); 0286 d->lockButton->blockSignals(false); 0287 0288 //qDebug() << "setlocked" << q << d->locked << locked; 0289 0290 if (locked) { 0291 d->features = q->features(); 0292 q->setFeatures(QDockWidget::NoDockWidgetFeatures); 0293 } 0294 else { 0295 q->setFeatures(d->features); 0296 } 0297 0298 q->toggleViewAction()->setEnabled(!locked); 0299 d->closeButton->setEnabled(!locked); 0300 d->floatButton->setEnabled(!locked); 0301 d->collapseButton->setEnabled(!locked); 0302 0303 d->updateIcons(); 0304 q->setProperty("Locked", locked); 0305 resizeEvent(nullptr); 0306 } 0307 0308 0309 void KoDockWidgetTitleBar::setCollapsable(bool collapsable) 0310 { 0311 d->collapsableSet = collapsable; 0312 d->collapsable = collapsable; 0313 d->collapseButton->setVisible(collapsable); 0314 } 0315 0316 void KoDockWidgetTitleBar::setTextVisibilityMode(TextVisibilityMode textVisibilityMode) 0317 { 0318 d->textVisibilityMode = textVisibilityMode; 0319 } 0320 0321 void KoDockWidgetTitleBar::updateIcons() 0322 { 0323 d->updateIcons(); 0324 } 0325 0326 void KoDockWidgetTitleBar::Private::toggleFloating() 0327 { 0328 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget()); 0329 0330 q->setFloating(!q->isFloating()); 0331 } 0332 0333 void KoDockWidgetTitleBar::Private::topLevelChanged(bool topLevel) 0334 { 0335 lockButton->setEnabled(!topLevel); 0336 } 0337 0338 void KoDockWidgetTitleBar::Private::toggleCollapsed() 0339 { 0340 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget()); 0341 if (q == nullptr) // there does not *have* to be anything on the dockwidget. 0342 return; 0343 0344 preCollapsedWidth = q->widget()->isHidden() ? -1 : thePublic->width(); 0345 q->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // will be overwritten again next 0346 if (q->widget()) { 0347 q->widget()->setVisible(q->widget()->isHidden()); 0348 collapseButton->setIcon(q->widget()->isHidden() ? closeIcon(q) : openIcon(q)); 0349 } 0350 } 0351 0352 void KoDockWidgetTitleBar::Private::featuresChanged(QDockWidget::DockWidgetFeatures) 0353 { 0354 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget()); 0355 0356 closeButton->setVisible(hasFeature(q, QDockWidget::DockWidgetClosable)); 0357 floatButton->setVisible(hasFeature(q, QDockWidget::DockWidgetFloatable)); 0358 0359 thePublic->resizeEvent(nullptr); 0360 } 0361 0362 // QT5TODO: this is not yet triggered by theme changes it seems 0363 void KoDockWidgetTitleBar::Private::updateIcons() 0364 { 0365 QDockWidget *q = qobject_cast<QDockWidget*>(thePublic->parentWidget()); 0366 0367 lockButton->setIcon((!locked) ? koIcon("object-unlocked") : koIcon("object-locked")); 0368 0369 // this method gets called when switching themes, so update all of the themed icons now 0370 floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, 0, q)); 0371 closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, 0, q)); 0372 0373 if (q->widget()) { 0374 collapseButton->setIcon(q->widget()->isHidden() ? closeIcon(q) : openIcon(q)); 0375 } 0376 thePublic->resizeEvent(nullptr); 0377 0378 } 0379 0380 //have to include this because of Q_PRIVATE_SLOT 0381 #include "moc_KoDockWidgetTitleBar.cpp"