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

GroupingDesktop

  • sources
  • kde-4.14
  • workspace
  • kdeplasma-addons
  • containments
  • groupingdesktop
  • lib
  • groupexplorer
groupiconlist.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 by Ana CecĂ­lia Martins <anaceciliamb@gmail.com>
3  * Copyright (C) 2009 by Ivan Cukic <ivan.cukic+kde@gmail.com>
4  * Copyright (C) 2010 by Chani Armitage <chani@kde.org>
5  * Copyright 2010 by Giulio Camuffo <giuliocamuffo@gmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Library/Lesser General Public License
9  * version 2, or (at your option) any later version, as published by the
10  * Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details
16  *
17  * You should have received a copy of the GNU Library/Lesser General Public
18  * License along with this program; if not, write to the
19  * Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #include "groupiconlist.h"
24 
25 #include <cmath>
26 
27 #include <QGraphicsSceneWheelEvent>
28 #include <QGraphicsView>
29 #include <QHash>
30 #include <QToolButton>
31 #include <QGraphicsLinearLayout>
32 #include <QTimer>
33 
34 #include <KIconLoader>
35 #include <KIcon>
36 #include <KPushButton>
37 
38 #include <Plasma/Animation>
39 #include <Plasma/Animator>
40 #include <Plasma/Containment>
41 #include <Plasma/Corona>
42 #include <Plasma/ItemBackground>
43 #include <Plasma/Theme>
44 #include <Plasma/ToolButton>
45 
46 #include "abstractgroup.h"
47 #include "groupicon.h"
48 
49 const int ICON_SIZE = 70;
50 const int SEARCH_DELAY = 300;
51 const int SCROLL_STEP_DURATION = 300;
52 
53 GroupIconList::GroupIconList(Plasma::Location loc, QGraphicsItem *parent)
54  : QGraphicsWidget(parent),
55  m_arrowsSvg(new Plasma::Svg(this)),
56  m_location(Plasma::Floating),
57  m_iconSize(16),
58  m_scrollingDueToWheel(false)
59 {
60  m_scrollStep = 0;
61  m_firstItemIndex = 0;
62 
63  // init svg objects
64  m_arrowsSvg->setImagePath("widgets/arrows");
65  m_arrowsSvg->setContainsMultipleImages(true);
66  m_arrowsSvg->resize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
67 
68  m_slide = Plasma::Animator::create(Plasma::Animator::SlideAnimation);
69  m_slide->setEasingCurve(QEasingCurve::Linear);
70  connect(m_slide, SIGNAL(finished()), this, SLOT(scrollStepFinished()));
71 
72  //init arrows
73  m_upLeftArrow = new Plasma::ToolButton(this);
74  m_upLeftArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
75  m_upLeftArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
76  m_downRightArrow = new Plasma::ToolButton(this);
77  m_downRightArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
78  m_downRightArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
79 
80  connect(m_downRightArrow, SIGNAL(pressed()), this, SLOT(scrollDownRight()));
81  connect(m_upLeftArrow, SIGNAL(pressed()), this, SLOT(scrollUpLeft()));
82 
83  m_scrollWidget = new QGraphicsWidget(this);
84  m_scrollWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
85  m_scrollWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
86  m_listWidget = new QGraphicsWidget(m_scrollWidget);
87  m_listWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
88  m_listLayout = new QGraphicsLinearLayout(m_listWidget);
89 
90  m_slide->setTargetWidget(m_listWidget);
91 
92  m_listWidget->installEventFilter(this);
93  m_scrollWidget->installEventFilter(this);
94 
95  m_arrowsLayout = new QGraphicsLinearLayout();
96  m_arrowsLayout->addItem(m_scrollWidget);
97  m_arrowsLayout->addItem(m_upLeftArrow);
98  m_arrowsLayout->addItem(m_downRightArrow);
99  m_arrowsLayout->setAlignment(m_downRightArrow, Qt::AlignVCenter | Qt::AlignHCenter);
100  m_arrowsLayout->setAlignment(m_upLeftArrow, Qt::AlignVCenter | Qt::AlignHCenter);
101  m_arrowsLayout->setAlignment(m_scrollWidget, Qt::AlignVCenter | Qt::AlignHCenter);
102 
103  m_hoverIndicator = new Plasma::ItemBackground(m_listWidget);
104 
105  setLayout(m_arrowsLayout);
106  setLocation(loc);
107 
108  QStringList groups = AbstractGroup::availableGroups();
109  foreach (const QString &group, groups) {
110  GroupIcon *icon = new GroupIcon(group);
111  addIcon(icon);
112  }
113 
114  updateList();
115 }
116 
117 GroupIconList::~GroupIconList()
118 {
119  delete m_slide;
120 }
121 
122 bool GroupIconList::eventFilter(QObject *obj, QEvent *event)
123 {
124  if (event->type() == QEvent::GraphicsSceneResize) {
125  QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget *>(obj);
126 
127  if (widget == m_listWidget) {
128  //the resize occurred with the list widget
129  if (m_orientation == Qt::Horizontal) {
130  m_scrollWidget->setMinimumSize(0, m_listWidget->minimumHeight());
131  } else {
132  m_scrollWidget->setMinimumSize(m_listWidget->minimumWidth(), 0);
133  }
134 
135  manageArrows();
136  } else if (widget == m_scrollWidget) {
137  // the resize occurred with the window widget
138  // FIXME rename this too, eew.
139  int maxVisibleIconsOnList = maximumAproxVisibleIconsOnList();
140  m_scrollStep = ceil((float)maxVisibleIconsOnList/2);
141  if (m_orientation == Qt::Vertical) {
142  m_listWidget->setMinimumSize(m_scrollWidget->size().width(), 0);
143  }
144  }
145  }
146 
147  return QObject::eventFilter(obj, event);
148 }
149 
150 Plasma::Location GroupIconList::location()
151 {
152  return m_location;
153 }
154 
155 void GroupIconList::setLocation(Plasma::Location location)
156 {
157  if (m_location == location) {
158  return;
159  }
160 
161  m_orientation = ((location == Plasma::LeftEdge || location == Plasma::RightEdge)?Qt::Vertical:Qt::Horizontal);
162 
163  m_listLayout->invalidate();
164  m_listLayout->setOrientation(m_orientation);
165  m_arrowsLayout->setOrientation(m_orientation);
166 
167  if(m_orientation == Qt::Horizontal) {
168  m_upLeftArrow->nativeWidget()->setIcon(KIcon(QIcon(m_arrowsSvg->pixmap("left-arrow"))));
169  m_downRightArrow->nativeWidget()->setIcon(KIcon(QIcon(m_arrowsSvg->pixmap("right-arrow"))));
170  m_upLeftArrow->setMaximumSize(IconSize(KIconLoader::Panel), -1);
171  m_downRightArrow->setMaximumSize(IconSize(KIconLoader::Panel), -1);
172  } else {
173  m_upLeftArrow->nativeWidget()->setIcon(KIcon(QIcon(m_arrowsSvg->pixmap("up-arrow"))));
174  m_downRightArrow->nativeWidget()->setIcon(KIcon(QIcon(m_arrowsSvg->pixmap("down-arrow"))));
175  m_upLeftArrow->setMaximumSize(-1, IconSize(KIconLoader::Panel));
176  m_downRightArrow->setMaximumSize(-1, IconSize(KIconLoader::Panel));
177  }
178 
179  m_listLayout->activate();
180 }
181 
182 void GroupIconList::iconHoverEnter(GroupIcon *icon)
183 {
184  if (icon) {
185  m_hoverIndicator->setTargetItem(icon);
186  if (!m_hoverIndicator->isVisible()) {
187  m_hoverIndicator->setGeometry(icon->geometry());
188  m_hoverIndicator->show();
189  }
190  } else {
191  m_hoverIndicator->hide();
192  }
193 }
194 
195 //uses the average icon size to guess how many will fit
196 int GroupIconList::maximumAproxVisibleIconsOnList()
197 {
198  qreal windowSize;
199  qreal listTotalSize;
200  qreal iconAverageSize;
201  qreal maxVisibleIconsOnList;
202 
203  if (m_orientation == Qt::Horizontal) {
204  windowSize = m_scrollWidget->geometry().width();
205  listTotalSize = m_listLayout->preferredSize().width();
206  } else {
207  windowSize = m_scrollWidget->geometry().height();
208  listTotalSize = m_listLayout->preferredSize().height();
209  }
210 
211  iconAverageSize = listTotalSize/
212  (m_items.count()) +
213  m_listLayout->spacing();
214 // approximatelly
215  maxVisibleIconsOnList = floor(windowSize/iconAverageSize);
216 
217  return maxVisibleIconsOnList;
218 }
219 
220 void GroupIconList::addIcon(GroupIcon *icon)
221 {
222  icon->setParent(m_listWidget);
223  qreal l, t, r, b;
224  m_hoverIndicator->getContentsMargins(&l, &t, &r, &b);
225  icon->setContentsMargins(l, t, r, b);
226 
227  //FIXME surely this should be checked in the setter :P
228  if (m_iconSize != GroupIcon::DEFAULT_ICON_SIZE) {
229  icon->setIconSize(m_iconSize);
230  }
231 
232  m_listLayout->addItem(icon);
233  m_listLayout->setAlignment(icon, Qt::AlignHCenter);
234  icon->show();
235  m_items.append(icon);
236 
237  connect(icon, SIGNAL(hoverEnter(GroupIcon*)), this, SLOT(iconHoverEnter(GroupIcon*)));
238 }
239 
240 void GroupIconList::updateList()
241 {
242  updateGeometry();
243  m_hoverIndicator->hide();
244  QTimer::singleShot(0, this, SLOT(resetScroll()));
245 }
246 
247 void GroupIconList::wheelEvent(QGraphicsSceneWheelEvent *event)
248 {
249  bool isDownRight = event->delta() < 0;
250  m_scrollingDueToWheel = true;
251 
252  if (isDownRight) {
253  if (m_downRightArrow->isEnabled()) {
254  scrollDownRight();
255  }
256  } else {
257  if (m_upLeftArrow->isEnabled()) {
258  scrollUpLeft();
259  }
260  }
261 }
262 
263 void GroupIconList::scrollDownRight()
264 {
265  int nextFirstItemIndex = m_firstItemIndex + m_scrollStep;
266  if (nextFirstItemIndex > m_items.count() - 1) {
267  nextFirstItemIndex = m_items.count() - 1;
268  }
269 
270  if (nextFirstItemIndex < 0) {
271  manageArrows();
272  return;
273  }
274 
275  qreal startPosition = itemPosition(nextFirstItemIndex);
276  qreal endPosition = startPosition + (visibleEndPosition() - visibleStartPosition());
277 
278  // would we show empty space at the end?
279  if (endPosition > listSize()) {
280  // find a better first item
281  qreal searchPosition = startPosition - (endPosition - listSize());
282  for (int i = 0; i < m_items.count(); i++) {
283  if (itemPosition(i) >= searchPosition) {
284  nextFirstItemIndex = i;
285  break;
286  }
287  }
288  }
289 
290  scrollTo(nextFirstItemIndex);
291 }
292 
293 void GroupIconList::scrollUpLeft()
294 {
295  int nextFirstItemIndex = m_firstItemIndex - m_scrollStep;
296  if (nextFirstItemIndex < 0) {
297  nextFirstItemIndex = 0;
298  }
299 
300  if (nextFirstItemIndex > m_items.count() - 1) {
301  manageArrows();
302  return;
303  }
304 
305  scrollTo(nextFirstItemIndex);
306 }
307 
308 void GroupIconList::scrollTo(int index)
309 {
310  qreal startPosition = itemPosition(index);
311  qreal move = startPosition - visibleStartPosition();
312 
313  m_firstItemIndex = index;
314 
315  m_slide->stop();
316 
317  if (m_orientation == Qt::Horizontal) {
318  m_slide->setProperty("movementDirection", Plasma::Animation::MoveLeft);
319  } else {
320  m_slide->setProperty("movementDirection", Plasma::Animation::MoveUp);
321  }
322 
323  m_slide->setProperty("distance", move);
324  m_slide->start();
325 
326  manageArrows();
327 }
328 
329 void GroupIconList::scrollStepFinished()
330 {
331  manageArrows();
332 
333  if (m_scrollingDueToWheel && m_hoverIndicator->isVisible() && scene()) {
334  QGraphicsView *view = Plasma::viewFor(this);
335  if (view) {
336  GroupIcon *icon = dynamic_cast<GroupIcon *>(scene()->itemAt(view->mapToScene(view->mapFromGlobal(QCursor::pos()))));
337  if (icon) {
338  // m_hoverIndicator->setGeometry(icon->geometry());
339  }
340  iconHoverEnter(icon);
341  }
342  }
343  m_scrollingDueToWheel = false;
344 
345  //keep scrolling if the button is held down
346  bool movingLeftUp = m_slide->property("distance").value<qreal>() < 0;
347  if (movingLeftUp) {
348  if (m_upLeftArrow->isEnabled() && m_upLeftArrow->isDown()) {
349  scrollUpLeft();
350  }
351  } else if (m_downRightArrow->isEnabled() && m_downRightArrow->isDown()) {
352  scrollDownRight();
353  }
354 }
355 
356 void GroupIconList::resetScroll()
357 {
358  m_listWidget->setPos(0,0);
359  m_firstItemIndex = 0;
360  manageArrows();
361  m_listWidget->resize(m_listLayout->geometry().size());
362 }
363 
364 void GroupIconList::manageArrows()
365 {
366  qreal list_size = listSize();
367  qreal window_size = windowSize();
368 
369  if (list_size <= window_size || m_items.isEmpty()) {
370  m_upLeftArrow->setEnabled(false);
371  m_downRightArrow->setEnabled(false);
372  m_upLeftArrow->setVisible(false);
373  m_downRightArrow->setVisible(false);
374  } else {
375  qreal endPosition = itemPosition(m_firstItemIndex) + window_size;
376  m_upLeftArrow->setVisible(true);
377  m_downRightArrow->setVisible(true);
378  m_upLeftArrow->setEnabled(m_firstItemIndex > 0);
379  m_downRightArrow->setEnabled(endPosition < list_size);
380  }
381 }
382 
383 QRectF GroupIconList::visibleListRect()
384 {
385  QRectF visibleRect = m_scrollWidget->mapRectToItem(m_listWidget, m_scrollWidget->boundingRect());
386 
387  return visibleRect;
388 }
389 
390 qreal GroupIconList::visibleStartPosition()
391 {
392  if (m_orientation == Qt::Horizontal) {
393  return m_scrollWidget->mapToItem(m_listWidget, m_scrollWidget->boundingRect().left(), 0).x();
394  } else {
395  return m_scrollWidget->mapToItem(m_listWidget, 0, m_scrollWidget->boundingRect().top()).y();
396  }
397 }
398 
399 qreal GroupIconList::visibleEndPosition()
400 {
401  if (m_orientation == Qt::Horizontal) {
402  return m_scrollWidget->mapToItem(m_listWidget, m_scrollWidget->boundingRect().right(), 0).x();
403  } else {
404  return m_scrollWidget->mapToItem(m_listWidget, 0, m_scrollWidget->boundingRect().bottom()).y();
405  }
406 }
407 
408 qreal GroupIconList::listSize()
409 {
410  if (m_orientation == Qt::Horizontal) {
411  return m_listWidget->boundingRect().size().width();
412  } else {
413  return m_listWidget->boundingRect().size().height();
414  }
415 }
416 
417 qreal GroupIconList::windowSize()
418 {
419  return (visibleEndPosition() - visibleStartPosition());
420 }
421 
422 qreal GroupIconList::itemPosition(int i)
423 {
424  GroupIcon *applet = m_items.at(i);
425  if (!applet) {
426  return 0;
427  }
428 
429  if (m_orientation == Qt::Horizontal) {
430  return applet->pos().x();
431  } else {
432  return applet->pos().y();
433  }
434 }
435 
436 void GroupIconList::setIconSize(int size)
437 {
438  if (m_iconSize == size || size < 16) {
439  return;
440  }
441 
442  m_iconSize = size;
443 
444  foreach (GroupIcon *applet, m_items) {
445  applet->setIconSize(size);
446  }
447 
448  adjustSize();
449 }
450 
451 int GroupIconList::iconSize() const
452 {
453  return m_iconSize;
454 }
455 
456 #include "groupiconlist.moc"
QGraphicsWidget::updateGeometry
virtual void updateGeometry()
QGraphicsLayoutItem::minimumHeight
qreal minimumHeight() const
QEvent
GroupIconList::updateList
void updateList()
Definition: groupiconlist.cpp:240
QGraphicsItem::x
qreal x() const
QGraphicsItem::y
qreal y() const
QEvent::type
Type type() const
QGraphicsLayoutItem::minimumWidth
qreal minimumWidth() const
QGraphicsLinearLayout
QGraphicsItem::mapToItem
QPointF mapToItem(const QGraphicsItem *item, const QPointF &point) const
QGraphicsScene::itemAt
QGraphicsItem * itemAt(const QPointF &position) const
GroupIconList::GroupIconList
GroupIconList(Plasma::Location location=Plasma::BottomEdge, QGraphicsItem *parent=0)
Definition: groupiconlist.cpp:53
QGraphicsObject::pos
pos
QGraphicsLayoutItem::setMinimumSize
void setMinimumSize(const QSizeF &size)
QGraphicsItem::setFlag
void setFlag(GraphicsItemFlag flag, bool enabled)
QGraphicsLayout::activate
void activate()
SEARCH_DELAY
const int SEARCH_DELAY
Definition: groupiconlist.cpp:50
QGraphicsLayoutItem::geometry
QRectF geometry() const
QGraphicsSceneWheelEvent
GroupIconList::setLocation
void setLocation(Plasma::Location location)
Definition: groupiconlist.cpp:155
GroupIcon
Definition: groupicon.h:33
QGraphicsView::mapToScene
QPointF mapToScene(const QPoint &point) const
QRectF::size
QSizeF size() const
QList::at
const T & at(int i) const
QGraphicsLinearLayout::invalidate
virtual void invalidate()
QRectF::top
qreal top() const
QGraphicsItem
GroupIconList::iconSize
int iconSize() const
Definition: groupiconlist.cpp:451
QGraphicsItem::scene
QGraphicsScene * scene() const
groupiconlist.h
abstractgroup.h
GroupIcon::setIconSize
void setIconSize(int height)
Definition: groupicon.cpp:85
QRectF::left
qreal left() const
QGraphicsLinearLayout::setAlignment
void setAlignment(QGraphicsLayoutItem *item, QFlags< Qt::AlignmentFlag > alignment)
QGraphicsLinearLayout::setOrientation
void setOrientation(Qt::Orientation orientation)
QGraphicsWidget::setContentsMargins
void setContentsMargins(qreal left, qreal top, qreal right, qreal bottom)
QGraphicsWidget::size
size
QRectF::bottom
qreal bottom() const
QGraphicsItem::group
QGraphicsItemGroup * group() const
QList::count
int count(const T &value) const
GroupIconList::eventFilter
bool eventFilter(QObject *obj, QEvent *event)
Definition: groupiconlist.cpp:122
QList::append
void append(const T &value)
GroupIcon::DEFAULT_ICON_SIZE
static const int DEFAULT_ICON_SIZE
Definition: groupicon.h:44
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QObject
AbstractGroup::availableGroups
static QStringList availableGroups()
Returns a list of all identifiers of the available Groups.
Definition: abstractgroup.cpp:844
QGraphicsLayoutItem::preferredSize
QSizeF preferredSize() const
QGraphicsItem::setPos
void setPos(const QPointF &pos)
ICON_SIZE
const int ICON_SIZE
Definition: groupiconlist.cpp:49
QList::isEmpty
bool isEmpty() const
QGraphicsWidget
GroupIconList::~GroupIconList
~GroupIconList()
Definition: groupiconlist.cpp:117
QObject::eventFilter
virtual bool eventFilter(QObject *watched, QEvent *event)
QGraphicsWidget::adjustSize
void adjustSize()
QString
GroupIconList::wheelEvent
void wheelEvent(QGraphicsSceneWheelEvent *event)
Definition: groupiconlist.cpp:247
QGraphicsItem::mapRectToItem
QRectF mapRectToItem(const QGraphicsItem *item, const QRectF &rect) const
GroupIconList::setIconSize
void setIconSize(int size)
Definition: groupiconlist.cpp:436
QStringList
QGraphicsLayoutItem::setSizePolicy
void setSizePolicy(const QSizePolicy &policy)
QRectF::right
qreal right() const
groupicon.h
QObject::setParent
void setParent(QObject *parent)
QGraphicsLinearLayout::spacing
qreal spacing() const
QGraphicsLinearLayout::addItem
void addItem(QGraphicsLayoutItem *item)
QCursor::pos
QPoint pos()
GroupIconList::location
Plasma::Location location()
Definition: groupiconlist.cpp:150
QRectF
QWidget::mapFromGlobal
QPoint mapFromGlobal(const QPoint &pos) const
QGraphicsWidget::QGraphicsWidget
QGraphicsWidget(QGraphicsItem *parent, QFlags< Qt::WindowType > wFlags)
QGraphicsWidget::setLayout
void setLayout(QGraphicsLayout *layout)
QGraphicsItem::show
void show()
SCROLL_STEP_DURATION
const int SCROLL_STEP_DURATION
Definition: groupiconlist.cpp:51
QSizeF::height
qreal height() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QGraphicsWidget::geometry
geometry
QGraphicsView
QGraphicsWidget::boundingRect
virtual QRectF boundingRect() const
QSizeF::width
qreal width() const
QIcon
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:57 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

GroupingDesktop

Skip menu "GroupingDesktop"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

workspace API Reference

Skip menu "workspace API Reference"
  • kdeplasma-addons
  •       GroupingDesktop
  •     liblancelot

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