Warning, file /office/calligra/libs/widgets/KoToolBoxScrollArea_p.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2018 Alvin Wong <alvinhochun@gmail.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Library General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Library General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #ifndef KO_TOOLBOX_SCROLL_AREA_H 0021 #define KO_TOOLBOX_SCROLL_AREA_H 0022 0023 #include "KoToolBox_p.h" 0024 #include "KoToolBoxLayout_p.h" 0025 0026 #include <QScrollArea> 0027 #include <QScrollBar> 0028 #include <QScroller> 0029 #include <QStyleOption> 0030 #include <QToolButton> 0031 #include <KoKineticScroller.h> 0032 0033 class KoToolBoxScrollArea : public QScrollArea 0034 { 0035 Q_OBJECT 0036 public: 0037 KoToolBoxScrollArea(KoToolBox *toolBox, QWidget *parent) 0038 : QScrollArea(parent) 0039 , m_toolBox(toolBox) 0040 , m_orientation(Qt::Vertical) 0041 , m_scrollPrev(new QToolButton(this)) 0042 , m_scrollNext(new QToolButton(this)) 0043 { 0044 setFrameShape(QFrame::NoFrame); 0045 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0046 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0047 0048 m_toolBox->setOrientation(m_orientation); 0049 setWidget(m_toolBox); 0050 0051 m_scrollPrev->setAutoRepeat(true); 0052 m_scrollPrev->setAutoFillBackground(true); 0053 m_scrollPrev->setFocusPolicy(Qt::NoFocus); 0054 connect(m_scrollPrev, &QToolButton::clicked, this, &KoToolBoxScrollArea::doScrollPrev); 0055 m_scrollNext->setAutoRepeat(true); 0056 m_scrollNext->setAutoFillBackground(true); 0057 m_scrollNext->setFocusPolicy(Qt::NoFocus); 0058 connect(m_scrollNext, &QToolButton::clicked, this, &KoToolBoxScrollArea::doScrollNext); 0059 0060 QScroller *scroller = KoKineticScroller::createPreconfiguredScroller(this); 0061 if (!scroller) { 0062 QScroller::grabGesture(viewport(), QScroller::MiddleMouseButtonGesture); 0063 QScroller *scroller = QScroller::scroller(viewport()); 0064 QScrollerProperties sp = scroller->scrollerProperties(); 0065 0066 sp.setScrollMetric(QScrollerProperties::MaximumVelocity, 0.0); 0067 sp.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.1); 0068 sp.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.1); 0069 sp.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0); 0070 sp.setScrollMetric(QScrollerProperties::OvershootScrollTime, 0.4); 0071 0072 scroller->setScrollerProperties(sp); 0073 } 0074 connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChange(QScroller::State))); 0075 } 0076 0077 void setOrientation(Qt::Orientation orientation) 0078 { 0079 if (orientation == m_orientation) { 0080 return; 0081 } 0082 m_orientation = orientation; 0083 m_toolBox->setOrientation(orientation); 0084 layoutItems(); 0085 } 0086 0087 Qt::Orientation orientation() const 0088 { 0089 return m_orientation; 0090 } 0091 0092 QSize minimumSizeHint() const override 0093 { 0094 return m_toolBox->minimumSizeHint(); 0095 } 0096 0097 QSize sizeHint() const override 0098 { 0099 return m_toolBox->sizeHint(); 0100 } 0101 0102 public Q_SLOTS: 0103 void slotScrollerStateChange(QScroller::State state){ KoKineticScroller::updateCursor(this, state); } 0104 0105 protected: 0106 bool event(QEvent *event) override 0107 { 0108 if (event->type() == QEvent::LayoutRequest) { 0109 // LayoutRequest can be triggered by icon changes, so resize the toolbox 0110 layoutItems(); 0111 // The toolbox might have changed the sizeHint and minimumSizeHint 0112 updateGeometry(); 0113 } 0114 return QScrollArea::event(event); 0115 } 0116 0117 void resizeEvent(QResizeEvent *event) override 0118 { 0119 layoutItems(); 0120 QScrollArea::resizeEvent(event); 0121 updateScrollButtons(); 0122 } 0123 0124 void wheelEvent(QWheelEvent *event) override 0125 { 0126 if (m_orientation == Qt::Vertical) { 0127 QApplication::sendEvent(verticalScrollBar(), event); 0128 } else { 0129 QApplication::sendEvent(horizontalScrollBar(), event); 0130 } 0131 } 0132 0133 void scrollContentsBy(int dx, int dy) override 0134 { 0135 QScrollArea::scrollContentsBy(dx, dy); 0136 updateScrollButtons(); 0137 } 0138 0139 private Q_SLOTS: 0140 void doScrollPrev() 0141 { 0142 if (m_orientation == Qt::Vertical) { 0143 verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); 0144 } else { 0145 horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub); 0146 } 0147 } 0148 0149 void doScrollNext() 0150 { 0151 if (m_orientation == Qt::Vertical) { 0152 verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); 0153 } else { 0154 horizontalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd); 0155 } 0156 } 0157 0158 private: 0159 int scrollButtonWidth() const 0160 { 0161 QStyleOption opt; 0162 opt.init(this); 0163 return style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, &opt, this); 0164 } 0165 0166 void layoutItems() 0167 { 0168 const KoToolBoxLayout *l = m_toolBox->toolBoxLayout(); 0169 QSize newSize = viewport()->size(); 0170 if (m_orientation == Qt::Vertical) { 0171 newSize.setHeight(l->heightForWidth(newSize.width())); 0172 } else { 0173 newSize.setWidth(l->widthForHeight(newSize.height())); 0174 } 0175 m_toolBox->resize(newSize); 0176 0177 updateScrollButtons(); 0178 } 0179 0180 void updateScrollButtons() 0181 { 0182 // We move the scroll buttons outside the widget rect instead of setting 0183 // the visibility, because setting the visibility triggers a relayout 0184 // of QAbstractScrollArea, which occasionally causes an offset bug when 0185 // QScroller performs the overshoot animation. (Overshoot is done by 0186 // moving the viewport widget, but the viewport position is reset during 0187 // a relayout.) 0188 const int scrollButtonWidth = this->scrollButtonWidth(); 0189 if (m_orientation == Qt::Vertical) { 0190 m_scrollPrev->setArrowType(Qt::UpArrow); 0191 m_scrollPrev->setEnabled(verticalScrollBar()->value() != verticalScrollBar()->minimum()); 0192 if (m_scrollPrev->isEnabled()) { 0193 m_scrollPrev->setGeometry(0, 0, width(), scrollButtonWidth); 0194 } else { 0195 m_scrollPrev->setGeometry(-width(), 0, width(), scrollButtonWidth); 0196 } 0197 m_scrollNext->setArrowType(Qt::DownArrow); 0198 m_scrollNext->setEnabled(verticalScrollBar()->value() != verticalScrollBar()->maximum()); 0199 if (m_scrollNext->isEnabled()) { 0200 m_scrollNext->setGeometry(0, height() - scrollButtonWidth, width(), scrollButtonWidth); 0201 } else { 0202 m_scrollNext->setGeometry(-width(), height() - scrollButtonWidth, width(), scrollButtonWidth); 0203 } 0204 } else { 0205 m_scrollPrev->setArrowType(Qt::LeftArrow); 0206 m_scrollPrev->setEnabled(horizontalScrollBar()->value() != horizontalScrollBar()->minimum()); 0207 if (m_scrollPrev->isEnabled()) { 0208 m_scrollPrev->setGeometry(0, 0, scrollButtonWidth, height()); 0209 } else { 0210 m_scrollPrev->setGeometry(0, -height(), scrollButtonWidth, height()); 0211 } 0212 m_scrollNext->setArrowType(Qt::RightArrow); 0213 m_scrollNext->setEnabled(horizontalScrollBar()->value() != horizontalScrollBar()->maximum()); 0214 if (m_scrollNext->isEnabled()) { 0215 m_scrollNext->setGeometry(width() - scrollButtonWidth, 0, scrollButtonWidth, height()); 0216 } else { 0217 m_scrollNext->setGeometry(width() - scrollButtonWidth, -height(), scrollButtonWidth, height()); 0218 } 0219 } 0220 } 0221 0222 KoToolBox *m_toolBox; 0223 Qt::Orientation m_orientation; 0224 0225 QToolButton *m_scrollPrev; 0226 QToolButton *m_scrollNext; 0227 }; 0228 0229 #endif // KO_TOOLBOX_SCROLL_AREA_H