2
* Copyright 2009 Marco Martin <notmart@gmail.com>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU Library General Public License as
6
* published by the Free Software Foundation; either version 2, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details
14
* You should have received a copy of the GNU Library General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "nettoolbox.h"
22
#include <QGraphicsLinearLayout>
23
#include <QGraphicsSceneMouseEvent>
24
#include <QGraphicsSceneHoverEvent>
28
#include <KIconLoader>
30
#include <Plasma/Animation>
31
#include <Plasma/Containment>
32
#include <Plasma/IconWidget>
33
#include <Plasma/ItemBackground>
34
#include <Plasma/PaintUtils>
38
class ToolContainer : public QGraphicsWidget
41
ToolContainer(QGraphicsWidget *parent)
42
: QGraphicsWidget(parent)
44
m_itemBackground = new Plasma::ItemBackground(this);
45
m_itemBackground->hide();
47
m_background = new Plasma::FrameSvg(this);
48
m_background->setImagePath("widgets/frame");
49
m_background->setElementPrefix("raised");
50
setLocation(Plasma::BottomEdge);
51
setAcceptHoverEvents(true);
58
void setLocation(Plasma::Location location)
60
m_location = location;
63
m_background->setEnabledBorders(Plasma::FrameSvg::BottomBorder);
65
case Plasma::BottomEdge:
66
m_background->setEnabledBorders(Plasma::FrameSvg::TopBorder);
68
case Plasma::LeftEdge:
69
m_background->setEnabledBorders(Plasma::FrameSvg::RightBorder);
71
case Plasma::RightEdge:
72
m_background->setEnabledBorders(Plasma::FrameSvg::LeftBorder);
75
m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
78
qreal left, top, right, bottom;
79
m_background->getMargins(left, top, right, bottom);
80
setContentsMargins(left, top, right, bottom);
83
Plasma::ItemBackground *itemBackground() const
85
return m_itemBackground;
88
Plasma::Location location() const
93
void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
98
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
101
m_itemBackground->hide();
104
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
109
m_background->paintFrame(painter);
113
void resizeEvent(QGraphicsSceneResizeEvent *event)
115
m_background->resizeFrame(event->newSize());
118
void mousePressEvent(QGraphicsSceneMouseEvent *event)
123
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
125
QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
127
if (which == Qt::PreferredSize) {
128
qreal left, top, right, bottom;
129
m_itemBackground->getContentsMargins(&left, &top, &right, &bottom);
131
if (m_location == Plasma::TopEdge) {
132
hint.setHeight(KIconLoader::SizeSmallMedium + m_background->marginSize(Plasma::BottomMargin) + top + bottom);
133
} else if (m_location == Plasma::BottomEdge) {
134
hint.setHeight(KIconLoader::SizeSmallMedium + m_background->marginSize(Plasma::TopMargin) + top + bottom);
141
bool eventFilter(QObject *watched, QEvent *event)
143
Plasma::IconWidget *icon = qobject_cast<Plasma::IconWidget *>(watched);
145
if (event->type() == QEvent::GraphicsSceneHoverEnter) {
146
m_itemBackground->setTargetItem(icon);
147
} else if (event->type() == QEvent::Show) {
148
//force the newly shown icon to have a sensible size
149
icon->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
150
layout()->invalidate();
151
} else if (event->type() == QEvent::Hide) {
152
if (m_location == Plasma::TopEdge || m_location == Plasma::BottomEdge) {
153
icon->setMaximumWidth(0);
155
icon->setMaximumHeight(0);
157
layout()->invalidate();
165
Plasma::FrameSvg *m_background;
166
Plasma::ItemBackground *m_itemBackground;
167
Plasma::Location m_location;
170
NetToolBox::NetToolBox(Plasma::Containment *parent)
171
: Plasma::AbstractToolBox(parent)
176
NetToolBox::NetToolBox(QObject *parent, const QVariantList &args)
177
: AbstractToolBox(parent, args)
182
NetToolBox::~NetToolBox()
186
void NetToolBox::init()
188
m_containment = containment();
189
Q_ASSERT(m_containment);
191
m_icon = KIcon("plasma");
192
m_closeIcon = KIcon("dialog-close");
193
m_iconSize = QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
194
m_animHighlightFrame = 0;
197
m_location = Plasma::BottomEdge;
198
m_newToolsPosition = 0;
201
resize(KIconLoader::SizeMedium, KIconLoader::SizeMedium);
202
setAcceptHoverEvents(true);
204
m_toolContainer = new ToolContainer(this);
205
m_toolContainer->hide();
206
m_toolContainer->setFlag(QGraphicsWidget::ItemStacksBehindParent);
207
m_toolContainerLayout = new QGraphicsLinearLayout(m_toolContainer);
208
m_toolContainerLayout->addStretch();
210
m_background = new Plasma::Svg(this);
211
m_background->setImagePath("widgets/toolbox");
212
m_background->setContainsMultipleImages(true);
213
setLocation(Plasma::BottomEdge);
215
m_containment->installEventFilter(this);
216
connect(m_containment, SIGNAL(geometryChanged()), this, SLOT(containmentGeometryChanged()));
217
containmentGeometryChanged();
219
slideAnim = Plasma::Animator::create(Plasma::Animator::SlideAnimation, this);
220
slideAnim->setProperty("movementDirection", Plasma::Animation::MoveAny);
221
connect(slideAnim, SIGNAL(stateChanged(QAbstractAnimation::State,
222
QAbstractAnimation::State)),
223
this, SLOT(onMovement(QAbstractAnimation::State, QAbstractAnimation::State)));
224
connect(slideAnim, SIGNAL(finished()), this, SLOT(movementFinished()));
226
anim = new QPropertyAnimation(this, "highlight", this);
227
anim->setDuration(250);
228
anim->setStartValue(0);
229
anim->setEndValue(1);
232
bool NetToolBox::isShowing() const
237
void NetToolBox::setShowing(const bool show)
240
if (show != m_toolContainer->isVisible()) {
242
emit visibilityChanged(show);
246
qreal left, top, right, bottom = 0;
248
switch (m_location) {
249
case Plasma::TopEdge:
250
m_toolContainer->setPos(boundingRect().topLeft() - QPoint(0, m_toolContainer->size().height()));
251
slideAnim->setProperty("distancePointF", QPointF(0, m_toolContainer->size().height()));
252
top = m_toolContainer->size().height();
254
case Plasma::LeftEdge:
255
m_toolContainer->setPos(boundingRect().topLeft() - QPoint(m_toolContainer->size().width(), 0));
256
slideAnim->setProperty("distancePointF", QPointF(m_toolContainer->size().width(), 0));
257
left = m_toolContainer->size().width();
259
case Plasma::RightEdge:
260
m_toolContainer->setPos(boundingRect().topRight());
261
slideAnim->setProperty("distancePointF", QPointF(-m_toolContainer->size().width(), 0));
262
right = m_toolContainer->size().width();
264
case Plasma::BottomEdge:
266
m_toolContainer->setPos(boundingRect().bottomLeft());
267
slideAnim->setProperty("distancePointF", QPointF(0, -m_toolContainer->size().height()));
268
bottom = m_toolContainer->size().height();
272
slideAnim->setTargetWidget(m_toolContainer);
273
slideAnim->setDirection(QAbstractAnimation::Forward);
276
if (m_containment->layout()) {
277
m_containment->layout()->setContentsMargins(left, top, right, bottom);
281
slideAnim->setDirection(QAbstractAnimation::Backward);
284
if (m_containment->layout()) {
285
m_containment->layout()->setContentsMargins(0, 0, 0, 0);
291
void NetToolBox::addTool(QAction *action)
293
Plasma::IconWidget *button = new Plasma::IconWidget(this);
294
button->setOrientation(Qt::Horizontal);
295
button->setTextBackgroundColor(QColor());
296
button->installEventFilter(m_toolContainer);
297
button->setAction(action);
299
qreal left, top, right, bottom;
300
m_toolContainer->itemBackground()->getContentsMargins(&left, &top, &right, &bottom);
301
button->setContentsMargins(left, top, right, bottom);
303
if (m_location == Plasma::LeftEdge || m_location == Plasma::RightEdge) {
304
button->setOrientation(Qt::Vertical);
306
button->setOrientation(Qt::Horizontal);
309
m_actionButtons[action] = button;
311
if (action == m_containment->action("remove")) {
312
m_toolContainerLayout->addItem(button);
313
--m_newToolsPosition;
314
} else if (action == m_containment->action("add page")) {
315
m_toolContainerLayout->insertItem(m_newToolsPosition+1, button);
316
--m_newToolsPosition;
317
} else if (action == m_containment->action("add applications")) {
318
m_toolContainerLayout->insertItem(1, button);
319
--m_newToolsPosition;
321
m_toolContainerLayout->insertItem(m_newToolsPosition, button);
323
++m_newToolsPosition;
325
if (m_toolContainerLayout->count() == 1) {
326
m_toolContainer->itemBackground()->setTargetItem(button);
330
void NetToolBox::removeTool(QAction *action)
332
if (m_actionButtons.contains(action)) {
333
Plasma::IconWidget *button = m_actionButtons.value(action);
334
m_toolContainerLayout->removeItem(button);
335
m_actionButtons.remove(action);
336
button->deleteLater();
337
if (action != m_containment->action("remove") ||
338
action != m_containment->action("add page")) {
339
--m_newToolsPosition;
344
QRectF NetToolBox::expandedGeometry() const
346
QRectF containerGeometry = m_toolContainer->boundingRect();
347
containerGeometry.moveBottomLeft(geometry().bottomLeft());
348
return containerGeometry;
351
void NetToolBox::setLocation(Plasma::Location location)
353
m_location = location;
354
m_toolContainer->setLocation(location);
355
if (location == Plasma::LeftEdge || location == Plasma::RightEdge) {
356
m_toolContainerLayout->setOrientation(Qt::Vertical);
357
m_toolContainerLayout->setContentsMargins(0, size().height(), 0, 0);
358
foreach (Plasma::IconWidget *icon, m_actionButtons) {
359
icon->setOrientation(Qt::Vertical);
362
m_toolContainerLayout->setOrientation(Qt::Horizontal);
363
m_toolContainerLayout->setContentsMargins(size().width(), 0, 0, 0);
364
foreach (Plasma::IconWidget *icon, m_actionButtons) {
365
icon->setOrientation(Qt::Horizontal);
368
containmentGeometryChanged();
371
Plasma::Location NetToolBox::location() const
376
void NetToolBox::containmentGeometryChanged()
378
m_toolContainerLayout->invalidate();
379
m_toolContainerLayout->activate();
381
switch (m_location) {
382
case Plasma::TopEdge:
383
m_toolContainer->resize(m_containment->size().width(), m_toolContainer->effectiveSizeHint(Qt::PreferredSize).height());
384
m_toolContainer->setPos(0, 0);
385
setPos(m_containment->contentsRect().topLeft());
387
case Plasma::BottomEdge:
388
m_toolContainer->resize(m_containment->size().width(), m_toolContainer->effectiveSizeHint(Qt::PreferredSize).height());
389
m_toolContainer->setPos(0, size().height()-m_toolContainer->size().height());
390
setPos(m_containment->contentsRect().left(), m_containment->contentsRect().bottom()-size().height()+1);
392
case Plasma::LeftEdge:
393
m_toolContainer->resize(m_toolContainer->effectiveSizeHint(Qt::PreferredSize).width(), m_containment->size().height());
394
m_toolContainer->setPos(0, 0);
395
setPos(m_containment->contentsRect().topLeft());
397
case Plasma::RightEdge:
398
m_toolContainer->resize(m_toolContainer->effectiveSizeHint(Qt::PreferredSize).width(), m_containment->size().height());
399
m_toolContainer->setPos(size().width()-m_toolContainer->size().width(), 0);
400
setPos(m_containment->contentsRect().right()-size().width()+1, m_containment->contentsRect().top());
403
m_toolContainer->resize(m_toolContainer->effectiveSizeHint(Qt::PreferredSize));
404
m_toolContainer->setPos(m_containment->contentsRect().left(), size().height()-m_toolContainer->size().height());
409
void NetToolBox::mousePressEvent(QGraphicsSceneMouseEvent *event)
414
void NetToolBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
417
setShowing(!isShowing());
420
void NetToolBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
427
switch (m_location) {
428
case Plasma::TopEdge:
429
case Plasma::LeftEdge:
430
iconPos = QPoint(2, 2);
431
svgElement = "desktop-northwest";
433
case Plasma::RightEdge:
434
iconPos = QPoint(size().width() - m_iconSize.width() - 2, 2);
435
svgElement = "desktop-northeast";
437
case Plasma::BottomEdge:
439
iconPos = QPoint(2, size().height() - m_iconSize.height() - 2);
440
svgElement = "desktop-southwest";
444
m_background->paint(painter, boundingRect(), svgElement);
453
if (qFuzzyCompare(qreal(1.0), m_animHighlightFrame)) {
454
icon.paint(painter, QRect(iconPos, m_iconSize));
455
} else if (qFuzzyCompare(qreal(1.0), 1 + m_animHighlightFrame)) {
456
icon.paint(painter, QRect(iconPos, m_iconSize),
457
Qt::AlignCenter, QIcon::Disabled, QIcon::Off);
459
QPixmap disabled = icon.pixmap(m_iconSize, QIcon::Disabled, QIcon::Off);
460
QPixmap enabled = icon.pixmap(m_iconSize);
461
QPixmap result = Plasma::PaintUtils::transition(
462
icon.pixmap(m_iconSize, QIcon::Disabled, QIcon::Off),
463
icon.pixmap(m_iconSize), m_animHighlightFrame);
464
painter->drawPixmap(QRect(iconPos, m_iconSize), result);
468
bool NetToolBox::eventFilter(QObject *watched, QEvent *event)
470
if (watched == m_containment && event->type() == QEvent::ContentsRectChange) {
471
qreal left, top, right, bottom;
472
m_containment->getContentsMargins(&left, &top, &right, &bottom);
474
//left preferred over right
475
if (left > top && left > right && left > bottom) {
476
setLocation(Plasma::RightEdge);
477
} else if (right > top && right >= left && right > bottom) {
478
setLocation(Plasma::LeftEdge);
479
} else if (bottom > top && bottom > left && bottom > right) {
480
setLocation(Plasma::TopEdge);
481
//bottom is the default
483
setLocation(Plasma::BottomEdge);
487
return AbstractToolBox::eventFilter(watched, event);
490
void NetToolBox::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
492
if (isShowing() || m_hovering) {
493
QGraphicsWidget::hoverEnterEvent(event);
499
QGraphicsWidget::hoverEnterEvent(event);
502
void NetToolBox::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
504
//kDebug() << event->pos() << event->scenePos()
505
// << d->toolBacker->rect().contains(event->scenePos().toPoint());
506
if (!m_hovering || isShowing()) {
507
QGraphicsWidget::hoverLeaveEvent(event);
513
QGraphicsWidget::hoverLeaveEvent(event);
516
void NetToolBox::highlight(bool highlighting)
518
if (m_hovering == highlighting) {
522
m_hovering = highlighting;
524
if (anim->state() != QAbstractAnimation::Stopped) {
531
void NetToolBox::setHighlight(qreal progress)
534
m_animHighlightFrame = progress;
536
m_animHighlightFrame = 1.0 - progress;
542
qreal NetToolBox::highlight()
544
return m_animHighlightFrame;
547
void NetToolBox::movementFinished()
550
if (slideAnim->property("direction") == QAbstractAnimation::Forward) {
551
slideAnim->setProperty("direction", QAbstractAnimation::Backward);
553
slideAnim->setProperty("direction", QAbstractAnimation::Forward);
556
m_toolContainer->setVisible(m_showing);
559
void NetToolBox::onMovement(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
563
m_toolContainer->show();
566
#include "nettoolbox.moc"