File indexing completed on 2024-05-12 16:02:12
0001 /* This file is part of the KDE project 0002 * 0003 * SPDX-FileCopyrightText: 2010-2011 C. Boemann <cbo@boemann.dk> 0004 * SPDX-FileCopyrightText: 2005-2006 Boudewijn Rempt <boud@valdyas.org> 0005 * SPDX-FileCopyrightText: 2006 Thomas Zander <zander@kde.org> 0006 * 0007 * SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 #include "KoToolDocker.h" 0010 0011 #include <klocalizedstring.h> 0012 0013 #include <QApplication> 0014 #include <QBoxLayout> 0015 #include <QGridLayout> 0016 #include <QLabel> 0017 #include <QScrollArea> 0018 #include <QScroller> 0019 0020 class Q_DECL_HIDDEN KoToolDocker::Private 0021 { 0022 public: 0023 Private(KoToolDocker *dock) 0024 : q(dock) 0025 { 0026 } 0027 0028 ~Private() { 0029 /// Hider widget is not part of any widget hierarchy (which is intentional 0030 /// due to bug 447522), so we need to delete it manually 0031 delete hiderWidget; 0032 } 0033 0034 QList<QPointer<QWidget> > currentWidgetList; 0035 QSet<QWidget *> currentAuxWidgets; 0036 QScrollArea *scrollArea {nullptr}; 0037 QWidget *hiderWidget {nullptr}; // non current widgets are hidden by being children of this 0038 QWidget *housekeeperWidget {nullptr}; 0039 QGridLayout *housekeeperLayout {nullptr}; 0040 QBoxLayout *housekeeperMainLayout{nullptr}; 0041 KoToolDocker *q {nullptr}; 0042 Qt::DockWidgetArea dockingArea; 0043 0044 void resetWidgets() 0045 { 0046 currentWidgetList.clear(); 0047 qDeleteAll(currentAuxWidgets); 0048 currentAuxWidgets.clear(); 0049 } 0050 0051 void recreateLayout(const QList<QPointer<QWidget> > &optionWidgetList) 0052 { 0053 Q_FOREACH (QPointer<QWidget> widget, currentWidgetList) { 0054 if (!widget.isNull() && widget && hiderWidget) { 0055 widget->setParent(hiderWidget); 0056 } 0057 } 0058 qDeleteAll(currentAuxWidgets); 0059 currentAuxWidgets.clear(); 0060 0061 currentWidgetList = optionWidgetList; 0062 0063 // need to unstretch row that have previously been stretched 0064 housekeeperLayout->setRowStretch(housekeeperLayout->rowCount()-1, 0); 0065 0066 int cnt = 0; 0067 QFrame *s; 0068 QLabel *l; 0069 switch (dockingArea) { 0070 case Qt::TopDockWidgetArea: 0071 case Qt::BottomDockWidgetArea: 0072 housekeeperMainLayout->setDirection(QBoxLayout::LeftToRight); 0073 housekeeperMainLayout->setStretch(0, 1); 0074 housekeeperMainLayout->setStretch(1, 0); 0075 housekeeperLayout->setHorizontalSpacing(2); 0076 housekeeperLayout->setVerticalSpacing(0); 0077 Q_FOREACH (QPointer<QWidget> widget, currentWidgetList) { 0078 if (widget.isNull() || widget->objectName().isEmpty()) { 0079 continue; 0080 } 0081 if (!widget->windowTitle().isEmpty()) { 0082 housekeeperLayout->addWidget( 0083 l = new QLabel(widget->windowTitle()), 0084 0, 0085 2 * cnt); 0086 currentAuxWidgets.insert(l); 0087 } 0088 housekeeperLayout->addWidget(widget, 1, 2 * cnt); 0089 widget->show(); 0090 if (widget != currentWidgetList.last()) { 0091 housekeeperLayout->addWidget(s = new QFrame(), 0092 0, 0093 2 * cnt + 1, 0094 2, 0095 1); 0096 s->setFrameShape(QFrame::VLine); 0097 currentAuxWidgets.insert(s); 0098 } 0099 cnt++; 0100 } 0101 break; 0102 case Qt::NoDockWidgetArea: 0103 case Qt::LeftDockWidgetArea: 0104 case Qt::RightDockWidgetArea: { 0105 housekeeperMainLayout->setDirection(QBoxLayout::TopToBottom); 0106 housekeeperMainLayout->setStretch(0, 0); 0107 housekeeperMainLayout->setStretch(1, 1); 0108 housekeeperLayout->setHorizontalSpacing(0); 0109 housekeeperLayout->setVerticalSpacing(2); 0110 Q_FOREACH (QPointer<QWidget> widget, currentWidgetList) { 0111 if (widget.isNull() || widget->objectName().isEmpty()) { 0112 continue; 0113 } 0114 if (!widget->windowTitle().isEmpty()) { 0115 housekeeperLayout->addWidget( 0116 l = new QLabel(widget->windowTitle()), 0117 cnt++, 0118 0); 0119 currentAuxWidgets.insert(l); 0120 } 0121 housekeeperLayout->addWidget(widget, cnt++, 0); 0122 widget->show(); 0123 if (widget != currentWidgetList.last()) { 0124 housekeeperLayout->addWidget(s = new QFrame(), cnt++, 0); 0125 s->setFrameStyle(QFrame::HLine | QFrame::Sunken); 0126 currentAuxWidgets.insert(s); 0127 } 0128 } 0129 break; 0130 } 0131 default: 0132 break; 0133 } 0134 0135 housekeeperLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); 0136 housekeeperLayout->invalidate(); 0137 } 0138 0139 void locationChanged(Qt::DockWidgetArea area) 0140 { 0141 dockingArea = area; 0142 recreateLayout(currentWidgetList); 0143 } 0144 0145 }; 0146 0147 KoToolDocker::KoToolDocker(QWidget *parent) 0148 : QDockWidget(i18n("Tool Options"), parent), 0149 d(new Private(this)) 0150 { 0151 connect(this, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(locationChanged(Qt::DockWidgetArea))); 0152 0153 d->housekeeperWidget = new QWidget(); 0154 d->housekeeperLayout = new QGridLayout; 0155 d->housekeeperLayout->setContentsMargins(4,4,4,0); 0156 d->housekeeperLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); 0157 d->housekeeperMainLayout = 0158 new QBoxLayout(QBoxLayout::TopToBottom, d->housekeeperWidget); 0159 d->housekeeperMainLayout->setContentsMargins(0, 0, 0, 0); 0160 d->housekeeperMainLayout->setSpacing(0); 0161 d->housekeeperMainLayout->addLayout(d->housekeeperLayout, 0); 0162 d->housekeeperMainLayout->addStretch(1); 0163 0164 d->hiderWidget = new QWidget(); 0165 d->hiderWidget->setVisible(false); 0166 0167 d->scrollArea = new QScrollArea(); 0168 d->scrollArea->setWidget(d->housekeeperWidget); 0169 d->scrollArea->setFrameShape(QFrame::NoFrame); 0170 d->scrollArea->setWidgetResizable(true); 0171 d->scrollArea->setFocusPolicy(Qt::NoFocus); 0172 0173 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(d->scrollArea); 0174 if( scroller ) { 0175 connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); 0176 } 0177 0178 setWidget(d->scrollArea); 0179 } 0180 0181 KoToolDocker::~KoToolDocker() 0182 { 0183 delete d; 0184 } 0185 0186 bool KoToolDocker::hasOptionWidget() 0187 { 0188 return !d->currentWidgetList.isEmpty(); 0189 } 0190 0191 void KoToolDocker::setOptionWidgets(const QList<QPointer<QWidget> > &optionWidgetList) 0192 { 0193 d->recreateLayout(optionWidgetList); 0194 } 0195 0196 void KoToolDocker::slotScrollerStateChange(QScroller::State state) 0197 { 0198 KisKineticScroller::updateCursor(d->scrollArea, state); 0199 } 0200 0201 void KoToolDocker::resetWidgets() 0202 { 0203 d->resetWidgets(); 0204 } 0205 0206 0207 void KoToolDocker::setCanvas(KoCanvasBase *canvas) 0208 { 0209 setEnabled(canvas != 0); 0210 } 0211 0212 void KoToolDocker::unsetCanvas() 0213 { 0214 setEnabled(false); 0215 } 0216 0217 //have to include this because of Q_PRIVATE_SLOT 0218 #include <moc_KoToolDocker.cpp>