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

libs/libksane/libksane

  • sources
  • kde-4.14
  • kdegraphics
  • libs
  • libksane
  • libksane
splittercollapser.cpp
Go to the documentation of this file.
1 // vim: set tabstop=4 shiftwidth=4 noexpandtab:
2 /*
3 Gwenview: an image viewer
4 Copyright 2009 Aurélien Gâteau <agateau@kde.org>
5 Copyright 2009 Kåre Sårs <kare.sars@iki.fi>
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 // Self
25 #include "splittercollapser.moc"
26 
27 // Qt
28 #include <QApplication>
29 #include <QEvent>
30 #include <QMouseEvent>
31 #include <QSplitter>
32 #include <QStyleOptionToolButton>
33 #include <QStylePainter>
34 #include <QTimeLine>
35 
36 // KDE
37 #include <kdebug.h>
38 
39 // Local
40 
41 namespace KSaneIface {
42 
43 
44 enum Direction {
45  LTR = 1 << 0,
46  RTL = 1 << 1,
47  Vertical = 1 << 2,
48  TTB = Vertical + (1 << 0),
49  BTT = Vertical + (1 << 1)
50 };
51 
52 const int TIMELINE_DURATION = 500;
53 
54 const qreal MINIMUM_OPACITY = 0.3;
55 
56 struct ArrowTypes {
57  ArrowTypes()
58  : visible(Qt::NoArrow), notVisible(Qt::NoArrow){}
59 
60  ArrowTypes(Qt::ArrowType t1, Qt::ArrowType t2)
61  : visible(t1), notVisible(t2) {}
62 
63  Qt::ArrowType visible,
64  notVisible;
65 
66  Qt::ArrowType get(bool isVisible) {
67  return isVisible ? visible : notVisible;
68  }
69 };
70 
71 
72 struct SplitterCollapserPrivate {
73  SplitterCollapser* q;
74  QSplitter* mSplitter;
75  QWidget* mWidget;
76  Direction mDirection;
77  QTimeLine* mOpacityTimeLine;
78  int mSizeAtCollaps;
79 
80  bool isVertical() const {
81  return mDirection & Vertical;
82  }
83 
84  bool isVisible() const {
85  bool isVisible = mWidget->isVisible();
86  QRect widgetRect = mWidget->geometry();
87  if (isVisible) {
88  QPoint br = widgetRect.bottomRight();
89  if ((br.x() <= 0) || (br.y() <=0)) {
90  isVisible = false;
91  }
92  }
93  return isVisible;
94  }
95 
96  void updatePosition() {
97  int x, y;
98  QRect widgetRect = mWidget->geometry();
99  int splitterWidth = mSplitter->width();
100  int handleWidth = mSplitter->handleWidth();
101  int width = q->width();
102 
103  if (!isVertical()) {
104  // FIXME: Make this configurable
105  y = 30;
106  if (mDirection == LTR) {
107  if (isVisible()) {
108  x = widgetRect.right() + handleWidth;
109  } else {
110  x = 0;
111  }
112  } else { // RTL
113  if (isVisible()) {
114  x = widgetRect.left() - handleWidth - width;
115  } else {
116  x = splitterWidth - handleWidth - width;
117  }
118  }
119  } else {
120  // FIXME
121  x = 0;
122  y = 0;
123  }
124  q->move(x, y);
125  }
126 
127 
128  void updateArrow() {
129  static QMap<Direction, ArrowTypes> arrowForDirection;
130  if (arrowForDirection.isEmpty()) {
131  arrowForDirection[LTR] = ArrowTypes(Qt::LeftArrow, Qt::RightArrow);
132  arrowForDirection[RTL] = ArrowTypes(Qt::RightArrow, Qt::LeftArrow);
133  arrowForDirection[TTB] = ArrowTypes(Qt::UpArrow, Qt::DownArrow);
134  arrowForDirection[BTT] = ArrowTypes(Qt::DownArrow, Qt::UpArrow);
135  }
136  q->setArrowType(arrowForDirection[mDirection].get(isVisible()));
137  }
138 
139 
140  void widgetEventFilter(QEvent* event) {
141  switch (event->type()) {
142  case QEvent::Resize:
143  updatePosition();
144  updateOpacity();
145  break;
146 
147  case QEvent::Move:
148  case QEvent::Show:
149  case QEvent::Hide:
150  updatePosition();
151  updateOpacity();
152  updateArrow();
153  break;
154 
155  default:
156  break;
157  }
158  }
159 
160 
161  void updateOpacity() {
162  QPoint pos = q->parentWidget()->mapFromGlobal(QCursor::pos());
163  QRect opaqueRect = q->geometry();
164  bool opaqueCollapser = opaqueRect.contains(pos);
165  int frame = mOpacityTimeLine->currentFrame();
166  if (opaqueCollapser && frame == mOpacityTimeLine->startFrame()) {
167  mOpacityTimeLine->setDirection(QTimeLine::Forward);
168  startTimeLine();
169  } else if (!opaqueCollapser && frame == mOpacityTimeLine->endFrame()) {
170  mOpacityTimeLine->setDirection(QTimeLine::Backward);
171  startTimeLine();
172  }
173  }
174 
175 
176  void startTimeLine() {
177  if (mOpacityTimeLine->state() != QTimeLine::Running) {
178  mOpacityTimeLine->start();
179  }
180  }
181 };
182 
183 
184 SplitterCollapser::SplitterCollapser(QSplitter* splitter, QWidget* widget)
185 : QToolButton(),
186 d(new SplitterCollapserPrivate)
187 {
188  d->q = this;
189 
190  // We do not want our collapser to be added as a regular widget in the
191  // splitter!
192  setAttribute(Qt::WA_NoChildEventsForParent);
193 
194  d->mOpacityTimeLine = new QTimeLine(TIMELINE_DURATION, this);
195  d->mOpacityTimeLine->setFrameRange(int(MINIMUM_OPACITY * 1000), 1000);
196  connect(d->mOpacityTimeLine, SIGNAL(valueChanged(qreal)), SLOT(update()));
197 
198  d->mWidget = widget;
199  d->mWidget->installEventFilter(this);
200 
201  qApp->installEventFilter(this);
202 
203  d->mSplitter = splitter;
204  setParent(d->mSplitter);
205 
206  if (splitter->indexOf(widget) < splitter->count() / 2) {
207  d->mDirection = LTR;
208  } else {
209  d->mDirection = RTL;
210  }
211  if (splitter->orientation() == Qt::Vertical) {
212  // FIXME: Ugly!
213  d->mDirection = static_cast<Direction>(int(d->mDirection) + int(TTB));
214  }
215 
216  connect(this, SIGNAL(clicked()), SLOT(slotClicked()));
217 
218  show();
219 }
220 
221 
222 SplitterCollapser::~SplitterCollapser() {
223  delete d;
224 }
225 
226 
227 bool SplitterCollapser::eventFilter(QObject* object, QEvent* event) {
228  if (object == d->mWidget) {
229  d->widgetEventFilter(event);
230  } else { /* app */
231  if (event->type() == QEvent::MouseMove) {
232  d->updateOpacity();
233  }
234  }
235  return false;
236 }
237 
238 
239 QSize SplitterCollapser::sizeHint() const {
240  int extent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
241  QSize sh(extent * 3 / 4, extent * 240 / 100);
242  if (d->isVertical()) {
243  sh.transpose();
244  }
245  return sh;
246 }
247 
248 
249 void SplitterCollapser::slotClicked() {
250  QList<int> sizes = d->mSplitter->sizes();
251  int index = d->mSplitter->indexOf(d->mWidget);
252  if (d->isVisible()) {
253  d->mSizeAtCollaps = sizes[index];
254  sizes[index] = 0;
255  }
256  else {
257  if (d->mSizeAtCollaps != 0) {
258  sizes[index] = d->mSizeAtCollaps;
259  }
260  else {
261  if (d->isVertical()) {
262  sizes[index] = d->mWidget->sizeHint().height();
263  }
264  else {
265  sizes[index] = d->mWidget->sizeHint().width();
266  }
267  }
268  }
269  d->mSplitter->setSizes(sizes);
270 }
271 
272 void SplitterCollapser::slotCollapse() {
273  if (d->isVisible()) slotClicked();
274  // else do nothing
275 }
276 
277 void SplitterCollapser::slotRestore() {
278  if (!d->isVisible()) slotClicked();
279  // else do nothing
280 }
281 
282 void SplitterCollapser::slotSetCollapsed(bool collapse) {
283  if (collapse == d->isVisible()) slotClicked();
284  // else do nothing
285 }
286 
287 void SplitterCollapser::paintEvent(QPaintEvent*) {
288  QStylePainter painter(this);
289  qreal opacity = d->mOpacityTimeLine->currentFrame() / 1000.;
290  painter.setOpacity(opacity);
291 
292  QStyleOptionToolButton opt;
293  initStyleOption(&opt);
294  if (d->mDirection == LTR) {
295  opt.rect.setLeft(-width());
296  } else {
297  opt.rect.setWidth(width() * 2);
298  }
299  painter.drawPrimitive(QStyle::PE_PanelButtonTool, opt);
300 
301  QStyleOptionToolButton opt2;
302  initStyleOption(&opt2);
303  painter.drawControl(QStyle::CE_ToolButtonLabel, opt2);
304 }
305 
306 
307 } // namespace
QStylePainter
QPainter::setOpacity
void setOpacity(qreal opacity)
QEvent
QWidget
QEvent::type
Type type() const
KSaneIface::SplitterCollapser::paintEvent
virtual void paintEvent(QPaintEvent *)
Definition: splittercollapser.cpp:287
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:52
QWidget::setAttribute
void setAttribute(Qt::WidgetAttribute attribute, bool on)
KSaneIface::SplitterCollapser::sizeHint
virtual QSize sizeHint() const
Definition: splittercollapser.cpp:239
QSize::transpose
void transpose()
QStyleOptionToolButton
QPoint
KSaneIface::LTR
Definition: splittercollapser.cpp:45
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
QWidget::width
int width() const
QRect
KSaneIface::TTB
Definition: splittercollapser.cpp:48
KSaneIface::SplitterCollapser::slotRestore
void slotRestore()
Definition: splittercollapser.cpp:277
QObject
QRect::left
int left() const
QAbstractButton::clicked
void clicked(bool checked)
KSaneIface::SplitterCollapser::SplitterCollapser
SplitterCollapser(QSplitter *, QWidget *widget)
Definition: splittercollapser.cpp:184
QRect::contains
bool contains(const QPoint &point, bool proper) const
QList
KSaneIface::MINIMUM_OPACITY
const qreal MINIMUM_OPACITY
Definition: splittercollapser.cpp:54
KSaneIface::SplitterCollapser::eventFilter
virtual bool eventFilter(QObject *, QEvent *)
Definition: splittercollapser.cpp:227
KSaneIface::RTL
Definition: splittercollapser.cpp:46
QToolButton
QSize
QSplitter
QRect::width
int width() const
QCursor::pos
QPoint pos()
KSaneIface::SplitterCollapser::slotCollapse
void slotCollapse()
Definition: splittercollapser.cpp:272
KSaneIface::BTT
Definition: splittercollapser.cpp:49
QTimeLine
KSaneIface::SplitterCollapser::~SplitterCollapser
~SplitterCollapser()
Definition: splittercollapser.cpp:222
KSaneIface::SplitterCollapser::slotSetCollapsed
void slotSetCollapsed(bool collapsed)
Definition: splittercollapser.cpp:282
KSaneIface::Vertical
Definition: splittercollapser.cpp:47
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:44
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:19:47 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libs/libksane/libksane

Skip menu "libs/libksane/libksane"
  • 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"
  •     libkdcraw
  •     libkexiv2
  •     libkipi
  •     libksane
  • 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