• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegraphics API Reference
  • KDE Home
  • Contact Us
 

libs/libksane/src

  • kde-4.x
  • kdegraphics
  • libs
  • libksane
  • src
splittercollapser.cpp
Go to the documentation of this file.
1 /*
2 Gwenview: an image viewer
3 Copyright 2009 Aurélien Gâteau <[email protected]>
4 Copyright 2009 Kåre Sårs <[email protected]>
5 Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks
6 
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) version 3, or any
11 later version accepted by the membership of KDE e.V. (or its
12 successor approved by the membership of KDE e.V.), which shall
13 act as a proxy defined in Section 6 of version 3 of the license.
14 
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public
21 License along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "splittercollapser.h"
25 
26 #include <QApplication>
27 #include <QEvent>
28 #include <QMouseEvent>
29 #include <QSplitter>
30 #include <QStyleOptionToolButton>
31 #include <QStylePainter>
32 #include <QTimeLine>
33 
34 #include <QDebug>
35 
36 namespace KSaneIface
37 {
38 
39 enum Direction {
40  LTR = 1 << 0,
41  RTL = 1 << 1,
42  Vertical = 1 << 2,
43  TTB = Vertical + (1 << 0),
44  BTT = Vertical + (1 << 1)
45 };
46 
47 const int TIMELINE_DURATION = 500;
48 
49 const qreal MINIMUM_OPACITY = 0.3;
50 
51 struct ArrowTypes {
52  ArrowTypes()
53  : visible(Qt::NoArrow), notVisible(Qt::NoArrow) {}
54 
55  ArrowTypes(Qt::ArrowType t1, Qt::ArrowType t2)
56  : visible(t1), notVisible(t2) {}
57 
58  Qt::ArrowType visible,
59  notVisible;
60 
61  Qt::ArrowType get(bool isVisible)
62  {
63  return isVisible ? visible : notVisible;
64  }
65 };
66 
67 struct SplitterCollapserPrivate {
68  SplitterCollapser *q;
69  QSplitter *mSplitter;
70  QWidget *mWidget;
71  Direction mDirection;
72  QTimeLine *mOpacityTimeLine;
73  int mSizeAtCollaps;
74 
75  bool isVertical() const
76  {
77  return mDirection & Vertical;
78  }
79 
80  bool isVisible() const
81  {
82  bool isVisible = mWidget->isVisible();
83  QRect widgetRect = mWidget->geometry();
84  if (isVisible) {
85  QPoint br = widgetRect.bottomRight();
86  if ((br.x() <= 0) || (br.y() <= 0)) {
87  isVisible = false;
88  }
89  }
90  return isVisible;
91  }
92 
93  void updatePosition()
94  {
95  int x, y;
96  QRect widgetRect = mWidget->geometry();
97  int splitterWidth = mSplitter->width();
98  int handleWidth = mSplitter->handleWidth();
99  int width = q->width();
100 
101  if (!isVertical()) {
102  // FIXME: Make this configurable
103  y = 30;
104  if (mDirection == LTR) {
105  if (isVisible()) {
106  x = widgetRect.right() + handleWidth;
107  } else {
108  x = 0;
109  }
110  } else { // RTL
111  if (isVisible()) {
112  x = widgetRect.left() - handleWidth - width;
113  } else {
114  x = splitterWidth - handleWidth - width;
115  }
116  }
117  } else {
118  // FIXME
119  x = 0;
120  y = 0;
121  }
122  q->move(x, y);
123  }
124 
125  void updateArrow()
126  {
127  static QMap<Direction, ArrowTypes> arrowForDirection;
128  if (arrowForDirection.isEmpty()) {
129  arrowForDirection[LTR] = ArrowTypes(Qt::LeftArrow, Qt::RightArrow);
130  arrowForDirection[RTL] = ArrowTypes(Qt::RightArrow, Qt::LeftArrow);
131  arrowForDirection[TTB] = ArrowTypes(Qt::UpArrow, Qt::DownArrow);
132  arrowForDirection[BTT] = ArrowTypes(Qt::DownArrow, Qt::UpArrow);
133  }
134  q->setArrowType(arrowForDirection[mDirection].get(isVisible()));
135  }
136 
137  void widgetEventFilter(QEvent *event)
138  {
139  switch (event->type()) {
140  case QEvent::Resize:
141  updatePosition();
142  updateOpacity();
143  break;
144 
145  case QEvent::Move:
146  case QEvent::Show:
147  case QEvent::Hide:
148  updatePosition();
149  updateOpacity();
150  updateArrow();
151  break;
152 
153  default:
154  break;
155  }
156  }
157 
158  void updateOpacity()
159  {
160  QPoint pos = q->parentWidget()->mapFromGlobal(QCursor::pos());
161  QRect opaqueRect = q->geometry();
162  bool opaqueCollapser = opaqueRect.contains(pos);
163  int frame = mOpacityTimeLine->currentFrame();
164  if (opaqueCollapser && frame == mOpacityTimeLine->startFrame()) {
165  mOpacityTimeLine->setDirection(QTimeLine::Forward);
166  startTimeLine();
167  } else if (!opaqueCollapser && frame == mOpacityTimeLine->endFrame()) {
168  mOpacityTimeLine->setDirection(QTimeLine::Backward);
169  startTimeLine();
170  }
171  }
172 
173  void startTimeLine()
174  {
175  if (mOpacityTimeLine->state() != QTimeLine::Running) {
176  mOpacityTimeLine->start();
177  }
178  }
179 };
180 
181 SplitterCollapser::SplitterCollapser(QSplitter *splitter, QWidget *widget)
182  : QToolButton(),
183  d(new SplitterCollapserPrivate)
184 {
185  d->q = this;
186 
187  // We do not want our collapser to be added as a regular widget in the
188  // splitter!
189  setAttribute(Qt::WA_NoChildEventsForParent);
190 
191  d->mOpacityTimeLine = new QTimeLine(TIMELINE_DURATION, this);
192  d->mOpacityTimeLine->setFrameRange(int(MINIMUM_OPACITY * 1000), 1000);
193  connect(d->mOpacityTimeLine, SIGNAL(valueChanged(qreal)), SLOT(update()));
194 
195  d->mWidget = widget;
196  d->mWidget->installEventFilter(this);
197 
198  qApp->installEventFilter(this);
199 
200  d->mSplitter = splitter;
201  setParent(d->mSplitter);
202 
203  if (splitter->indexOf(widget) < splitter->count() / 2) {
204  d->mDirection = LTR;
205  } else {
206  d->mDirection = RTL;
207  }
208  if (splitter->orientation() == Qt::Vertical) {
209  // FIXME: Ugly!
210  d->mDirection = static_cast<Direction>(int(d->mDirection) + int(TTB));
211  }
212 
213  connect(this, SIGNAL(clicked()), SLOT(slotClicked()));
214 
215  show();
216 }
217 
218 SplitterCollapser::~SplitterCollapser()
219 {
220  delete d;
221 }
222 
223 bool SplitterCollapser::eventFilter(QObject *object, QEvent *event)
224 {
225  if (object == d->mWidget) {
226  d->widgetEventFilter(event);
227  } else { /* app */
228  if (event->type() == QEvent::MouseMove) {
229  d->updateOpacity();
230  }
231  }
232  return false;
233 }
234 
235 QSize SplitterCollapser::sizeHint() const
236 {
237  int extent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
238  QSize sh(extent * 3 / 4, extent * 240 / 100);
239  if (d->isVertical()) {
240  sh.transpose();
241  }
242  return sh;
243 }
244 
245 void SplitterCollapser::slotClicked()
246 {
247  QList<int> sizes = d->mSplitter->sizes();
248  int index = d->mSplitter->indexOf(d->mWidget);
249  if (d->isVisible()) {
250  d->mSizeAtCollaps = sizes[index];
251  sizes[index] = 0;
252  } else {
253  if (d->mSizeAtCollaps != 0) {
254  sizes[index] = d->mSizeAtCollaps;
255  } else {
256  if (d->isVertical()) {
257  sizes[index] = d->mWidget->sizeHint().height();
258  } else {
259  sizes[index] = d->mWidget->sizeHint().width();
260  }
261  }
262  }
263  d->mSplitter->setSizes(sizes);
264 }
265 
266 void SplitterCollapser::slotCollapse()
267 {
268  if (d->isVisible()) {
269  slotClicked();
270  }
271  // else do nothing
272 }
273 
274 void SplitterCollapser::slotRestore()
275 {
276  if (!d->isVisible()) {
277  slotClicked();
278  }
279  // else do nothing
280 }
281 
282 void SplitterCollapser::slotSetCollapsed(bool collapse)
283 {
284  if (collapse == d->isVisible()) {
285  slotClicked();
286  }
287  // else do nothing
288 }
289 
290 void SplitterCollapser::paintEvent(QPaintEvent *)
291 {
292  QStylePainter painter(this);
293  qreal opacity = d->mOpacityTimeLine->currentFrame() / 1000.;
294  painter.setOpacity(opacity);
295 
296  QStyleOptionToolButton opt;
297  initStyleOption(&opt);
298  if (d->mDirection == LTR) {
299  opt.rect.setLeft(-width());
300  } else {
301  opt.rect.setWidth(width() * 2);
302  }
303  painter.drawPrimitive(QStyle::PE_PanelButtonTool, opt);
304 
305  QStyleOptionToolButton opt2;
306  initStyleOption(&opt2);
307  painter.drawControl(QStyle::CE_ToolButtonLabel, opt2);
308 }
309 
310 } // namespace
QStylePainter
QPainter::setOpacity
void setOpacity(qreal opacity)
QEvent
QWidget
QEvent::type
Type type() const
QSplitter::indexOf
int indexOf(QWidget *widget) const
QRect::right
int right() const
QWidget::style
QStyle * style() const
QStyle::pixelMetric
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const =0
QMap
QRect::bottomRight
QPoint bottomRight() const
KSaneIface::TIMELINE_DURATION
const int TIMELINE_DURATION
Definition: splittercollapser.cpp:47
QWidget::setAttribute
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QSize::transpose
void transpose()
QStyleOptionToolButton
QPoint
KSaneIface::LTR
Definition: splittercollapser.cpp:40
QWidget::setParent
void setParent(QWidget *parent)
QToolButton::initStyleOption
void initStyleOption(QStyleOptionToolButton *option) const
QWidget::update
void update()
QStylePainter::drawControl
void drawControl(QStyle::ControlElement ce, const QStyleOption &option)
QStylePainter::drawPrimitive
void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption &option)
QPoint::x
int x() const
QPoint::y
int y() const
QSplitter::count
int count() const
QSplitter::orientation
orientation
KSaneIface::SplitterCollapser::paintEvent
void paintEvent(QPaintEvent *) override
Definition: splittercollapser.cpp:290
QWidget::width
int width() const
QRect
KSaneIface::TTB
Definition: splittercollapser.cpp:43
KSaneIface::SplitterCollapser::slotRestore
void slotRestore()
Definition: splittercollapser.cpp:274
KSaneIface::SplitterCollapser::eventFilter
bool eventFilter(QObject *, QEvent *) override
Definition: splittercollapser.cpp:223
QObject
QRect::left
int left() const
QAbstractButton::clicked
void clicked(bool checked)
KSaneIface::SplitterCollapser::SplitterCollapser
SplitterCollapser(QSplitter *, QWidget *widget)
Definition: splittercollapser.cpp:181
QRect::contains
bool contains(const QPoint &point, bool proper) const
QList
KSaneIface::MINIMUM_OPACITY
const qreal MINIMUM_OPACITY
Definition: splittercollapser.cpp:49
KSaneIface::RTL
Definition: splittercollapser.cpp:41
QToolButton
QSize
QSplitter
QRect::width
int width() const
QCursor::pos
QPoint pos()
KSaneIface::SplitterCollapser::slotCollapse
void slotCollapse()
Definition: splittercollapser.cpp:266
splittercollapser.h
KSaneIface::BTT
Definition: splittercollapser.cpp:44
QTimeLine
KSaneIface::SplitterCollapser::~SplitterCollapser
~SplitterCollapser()
Definition: splittercollapser.cpp:218
KSaneIface::SplitterCollapser::slotSetCollapsed
void slotSetCollapsed(bool collapsed)
Definition: splittercollapser.cpp:282
KSaneIface::Vertical
Definition: splittercollapser.cpp:42
QWidget::show
void show()
QMap::isEmpty
bool isEmpty() const
QPaintEvent
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KSaneIface::Direction
Direction
Definition: splittercollapser.cpp:39
KSaneIface::SplitterCollapser::sizeHint
QSize sizeHint() const override
Definition: splittercollapser.cpp:235
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Fri Dec 13 2019 02:04:48 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libs/libksane/src

Skip menu "libs/libksane/src"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdegraphics API Reference

Skip menu "kdegraphics API Reference"
  •     libkipiplugins
  •     src
  •     src
  •     src
  •     src
  •     src
  • okular

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal