• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Plasma

toolbox.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2007 by Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2008 by Marco Martin <notmart@gmail.com>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License as
00007  *   published by the Free Software Foundation; either version 2, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "toolbox_p.h"
00022 
00023 #include <QAction>
00024 #include <QApplication>
00025 #include <QGraphicsSceneHoverEvent>
00026 #include <QGraphicsView>
00027 #include <QPainter>
00028 #include <QRadialGradient>
00029 
00030 #include <kcolorscheme.h>
00031 #include <kconfiggroup.h>
00032 #include <kiconloader.h>
00033 #include <kdebug.h>
00034 
00035 #include "corona.h"
00036 #include "theme.h"
00037 #include "widgets/iconwidget.h"
00038 
00039 namespace Plasma
00040 {
00041 
00042 class ToolBoxPrivate
00043 {
00044 public:
00045     ToolBoxPrivate(Containment *c)
00046       : containment(c),
00047         size(50),
00048         iconSize(KIconLoader::SizeMedium, KIconLoader::SizeMedium),
00049         corner(ToolBox::TopRight),
00050         hidden(false),
00051         showing(false),
00052         movable(false),
00053         toolbar(false),
00054         dragging(false),
00055         userMoved(false)
00056     {}
00057 
00058     Containment *containment;
00059     int size;
00060     QSize iconSize;
00061     ToolBox::Corner corner;
00062     QPoint dragStartRelative;
00063     QTransform viewTransform;
00064     bool hidden : 1;
00065     bool showing : 1;
00066     bool movable : 1;
00067     bool toolbar : 1;
00068     bool dragging : 1;
00069     bool userMoved : 1;
00070 };
00071 
00072 ToolBox::ToolBox(Containment *parent)
00073     : QGraphicsItem(parent),
00074       d(new ToolBoxPrivate(parent))
00075 {
00076     d->userMoved = false;
00077     setAcceptsHoverEvents(true);
00078 }
00079 
00080 ToolBox::~ToolBox()
00081 {
00082     delete d;
00083 }
00084 
00085 QPoint ToolBox::toolPosition(int toolHeight)
00086 {
00087     switch (d->corner) {
00088     case TopRight:
00089         return QPoint(boundingRect().width(), -toolHeight);
00090     case Top:
00091         return QPoint((int)boundingRect().center().x() - boundingRect().width(), -toolHeight);
00092     case TopLeft:
00093         return QPoint(-boundingRect().width(), -toolHeight);
00094     case Left:
00095         return QPoint(-boundingRect().width(), (int)boundingRect().center().y() - boundingRect().height());
00096     case Right:
00097         return QPoint(boundingRect().width(), (int)boundingRect().center().y() - boundingRect().height());
00098     case BottomLeft:
00099         return QPoint(-boundingRect().width(), toolHeight);
00100     case Bottom:
00101         return QPoint((int)boundingRect().center().x() - d->iconSize.width(), toolHeight);
00102     case BottomRight:
00103     default:
00104         return QPoint(boundingRect().width(), toolHeight);
00105     }
00106 }
00107 
00108 void ToolBox::addTool(QAction *action)
00109 {
00110     if (!action) {
00111         return;
00112     }
00113 
00114     foreach (QGraphicsItem *child, QGraphicsItem::children()) {
00115         //kDebug() << "checking tool" << child << child->data(ToolName);
00116         Plasma::IconWidget *tool = dynamic_cast<Plasma::IconWidget*>(child);
00117         if (tool && tool->action() == action) {
00118             return;
00119         }
00120     }
00121 
00122     Plasma::IconWidget *tool = new Plasma::IconWidget(this);
00123 
00124     tool->setTextBackgroundColor(QColor());
00125     tool->setAction(action);
00126     tool->setDrawBackground(true);
00127     tool->setOrientation(Qt::Horizontal);
00128     tool->resize(tool->sizeFromIconSize(KIconLoader::SizeSmallMedium));
00129 
00130     tool->hide();
00131     const int height = static_cast<int>(tool->boundingRect().height());
00132     tool->setPos(toolPosition(height));
00133     tool->setZValue(zValue() + 10);
00134     tool->setToolTip(action->text());
00135 
00136     //make enabled/disabled tools appear/disappear instantly
00137     connect(tool, SIGNAL(changed()), this, SLOT(updateToolBox()));
00138     connect(action, SIGNAL(triggered(bool)), this, SLOT(toolTriggered(bool)));
00139     //kDebug() << "added tool" << action->text() << (QGraphicsItem*)tool;
00140 }
00141 
00142 void ToolBox::updateToolBox()
00143 {
00144     Plasma::IconWidget *tool = qobject_cast<Plasma::IconWidget *>(sender());
00145     if (tool && tool->action() == 0) {
00146         tool->deleteLater();
00147         tool = 0;
00148     }
00149 
00150     if (d->showing) {
00151         d->showing = false;
00152         showToolBox();
00153     } else if (tool && !tool->isEnabled()) {
00154         tool->hide();
00155     }
00156 }
00157 
00158 void ToolBox::toolTriggered(bool)
00159 {
00160 }
00161 
00162 void ToolBox::removeTool(QAction *action)
00163 {
00164     foreach (QGraphicsItem *child, QGraphicsItem::children()) {
00165         //kDebug() << "checking tool" << child << child->data(ToolName);
00166         Plasma::IconWidget *tool = dynamic_cast<Plasma::IconWidget*>(child);
00167         if (tool && tool->action() == action) {
00168             //kDebug() << "tool found!";
00169             tool->deleteLater();
00170             break;
00171         }
00172     }
00173 }
00174 
00175 int ToolBox::size() const
00176 {
00177     return  d->size;
00178 }
00179 
00180 void ToolBox::setSize(const int newSize)
00181 {
00182     d->size = newSize;
00183 }
00184 
00185 QSize ToolBox::iconSize() const
00186 {
00187     return d->iconSize;
00188 }
00189 
00190 void ToolBox::setIconSize(const QSize newSize)
00191 {
00192     d->iconSize = newSize;
00193 }
00194 
00195 bool ToolBox::showing() const
00196 {
00197     return d->showing;
00198 }
00199 
00200 void ToolBox::setShowing(const bool show)
00201 {
00202     d->showing = show;
00203 }
00204 
00205 void ToolBox::setCorner(const Corner corner)
00206 {
00207     d->corner = corner;
00208 }
00209 
00210 ToolBox::Corner ToolBox::corner() const
00211 {
00212     return d->corner;
00213 }
00214 
00215 void ToolBox::mousePressEvent(QGraphicsSceneMouseEvent *event)
00216 {
00217     event->accept();
00218     // set grab position relative to toolbox
00219     d->dragStartRelative = mapToParent(event->pos()).toPoint() - pos().toPoint();
00220 }
00221 
00222 QSize ToolBox::cornerSize() const
00223 {
00224     return boundingRect().size().toSize();
00225 }
00226 
00227 QSize ToolBox::fullWidth() const
00228 {
00229     return boundingRect().size().toSize();
00230 }
00231 
00232 QSize  ToolBox::fullHeight() const
00233 {
00234     return boundingRect().size().toSize();
00235 }
00236 
00237 void ToolBox::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00238 {
00239     if (!d->movable || (!d->dragging && boundingRect().contains(event->pos())) || isToolbar()) {
00240         return;
00241     }
00242 
00243     d->dragging = true;
00244     d->userMoved = true;
00245     const QPoint newPos = mapToParent(event->pos()).toPoint();
00246     const QPoint curPos = pos().toPoint();
00247 
00248     const QSize cSize = cornerSize();
00249     const QSize fHeight = fullHeight();
00250     const QSize fWidth = fullWidth();
00251     const int h = fHeight.height();
00252     const int w = fWidth.width();
00253 
00254     const int areaWidth = parentWidget()->size().width();
00255     const int areaHeight = parentWidget()->size().height();
00256 
00257     int x = curPos.x();
00258     int y = curPos.y();
00259 
00260     // jump to the nearest desktop border
00261     int distanceToLeft = newPos.x() - d->dragStartRelative.x();
00262     int distanceToRight = areaWidth - w - distanceToLeft;
00263     int distanceToTop = newPos.y() - d->dragStartRelative.y();
00264     int distanceToBottom = areaHeight - h - distanceToTop;
00265 
00266     int distancetoHorizontalMiddle = qAbs(newPos.x() - areaWidth/2);
00267     int distancetoVerticalMiddle = qAbs(newPos.y() - areaHeight/2);
00268 
00269     // decide which border is the nearest
00270     if (distanceToLeft < distanceToTop && distanceToLeft < distanceToRight &&
00271         distanceToLeft < distanceToBottom ) {
00272         x = 0;
00273         y = (newPos.y() - d->dragStartRelative.y());
00274     } else if (distanceToRight < distanceToTop && distanceToRight < distanceToLeft &&
00275                distanceToRight < distanceToBottom) {
00276         x = areaWidth - w;
00277         y = (newPos.y() - d->dragStartRelative.y());
00278     } else if (distanceToTop < distanceToLeft && distanceToTop < distanceToRight &&
00279                distanceToTop < distanceToBottom ) {
00280         y = 0;
00281         x = (newPos.x() - d->dragStartRelative.x());
00282     } else if (distanceToBottom < distanceToLeft && distanceToBottom < distanceToRight &&
00283                distanceToBottom < distanceToTop) {
00284         y = areaHeight - h;
00285         x = (newPos.x() - d->dragStartRelative.x());
00286     }
00287 
00288     if (distancetoHorizontalMiddle < 10) {
00289         x = areaWidth/2 - d->dragStartRelative.x();
00290     } else if (distancetoVerticalMiddle < 10) {
00291         y = areaHeight/2 - d->dragStartRelative.y();
00292     }
00293 
00294     x = qBound(0, x, areaWidth - w);
00295     y = qBound(0, y, areaHeight - h);
00296 
00297     Corner newCorner = d->corner;
00298     if (x == 0) {
00299         if (y == 0) {
00300             newCorner = TopLeft;
00301         } else if (areaHeight - cSize.height() < newPos.y()) {
00302             y = areaHeight - cSize.height();
00303             newCorner = BottomLeft;
00304         } else {
00305             newCorner = Left;
00306         }
00307     } else if (y == 0) {
00308         if (areaWidth - cSize.width() < newPos.x()) {
00309             x = areaWidth - cSize.width();
00310             newCorner = TopRight;
00311         } else {
00312             newCorner = Top;
00313         }
00314     } else if (x + w >= areaWidth) {
00315         if (areaHeight - cSize.height() < newPos.y()) {
00316             y = areaHeight - cSize.height();
00317             x = areaWidth - cSize.width();
00318             newCorner = BottomRight;
00319         } else {
00320             x = areaWidth - fHeight.width();
00321             newCorner = Right;
00322         }
00323     } else {
00324         y = areaHeight - fWidth.height();
00325         newCorner = Bottom;
00326     }
00327 
00328     if (newCorner != d->corner) {
00329         prepareGeometryChange();
00330         d->corner = newCorner;
00331     }
00332 
00333     setPos(x, y);
00334 }
00335 
00336 void ToolBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00337 {
00338     if (!d->dragging && boundingRect().contains(event->pos())) {
00339         emit toggled();
00340     }
00341 
00342     d->dragging = false;
00343     KConfigGroup cg(d->containment->config());
00344     save(cg);
00345 }
00346 
00347 bool ToolBox::isMovable() const
00348 {
00349     return d->movable;
00350 }
00351 
00352 void ToolBox::setIsMovable(bool movable)
00353 {
00354     d->movable = movable;
00355 }
00356 
00357 bool ToolBox::isToolbar() const
00358 {
00359     return d->toolbar;
00360 }
00361 
00362 void ToolBox::setIsToolbar(bool toolbar)
00363 {
00364     d->toolbar = toolbar;
00365 }
00366 
00367 QTransform ToolBox::viewTransform() const
00368 {
00369     return d->viewTransform;
00370 }
00371 
00372 void ToolBox::setViewTransform(const QTransform &transform)
00373 {
00374     if (transform.isScaling()) {
00375         d->toolbar = true;
00376         showToolBox();
00377     } else {
00378         d->toolbar = false;
00379         if (d->viewTransform != transform) {
00380             hideToolBox();
00381         }
00382     }
00383     d->viewTransform = transform;
00384 }
00385 
00386 void ToolBox::save(KConfigGroup &cg) const
00387 {
00388     if (!d->movable) {
00389         return;
00390     }
00391 
00392     KConfigGroup group(&cg, "ToolBox");
00393     if (!d->userMoved) {
00394         group.deleteGroup();
00395         return;
00396     }
00397 
00398     int offset = 0;
00399     if (d->corner == ToolBox::Left ||
00400         d->corner == ToolBox::Right) {
00401         offset = y();
00402     } else if (d->corner == ToolBox::Top ||
00403                d->corner == ToolBox::Bottom) {
00404         offset = x();
00405     }
00406 
00407     group.writeEntry("corner", int(d->corner));
00408     group.writeEntry("offset", offset);
00409 }
00410 
00411 void ToolBox::load(const KConfigGroup &containmentGroup)
00412 {
00413     if (!d->movable) {
00414         return;
00415     }
00416 
00417     KConfigGroup group;
00418     if (containmentGroup.isValid()) {
00419         group = containmentGroup;
00420     } else {
00421         group = d->containment->config();
00422     }
00423 
00424     group = KConfigGroup(&group, "ToolBox");
00425 
00426     if (!group.hasKey("corner")) {
00427         return;
00428     }
00429 
00430     d->userMoved = true;
00431     d->corner = Corner(group.readEntry("corner", int(d->corner)));
00432 
00433     int offset = group.readEntry("offset", 0);
00434     switch (d->corner) {
00435         case ToolBox::TopLeft:
00436             setPos(0, 0);
00437             break;
00438         case ToolBox::Top:
00439             setPos(offset, 0);
00440             break;
00441         case ToolBox::TopRight:
00442             setPos(d->containment->size().width() - boundingRect().width(), 0);
00443             break;
00444         case ToolBox::Right:
00445             setPos(d->containment->size().width() - boundingRect().width(), offset);
00446             break;
00447         case ToolBox::BottomRight:
00448             setPos(d->containment->size().width() - boundingRect().width(), d->containment->size().height() - boundingRect().height());
00449             break;
00450         case ToolBox::Bottom:
00451             setPos(offset, d->containment->size().height() - boundingRect().height());
00452             break;
00453         case ToolBox::BottomLeft:
00454             setPos(0, d->containment->size().height() - boundingRect().height());
00455             break;
00456         case ToolBox::Left:
00457             setPos(0, offset);
00458             break;
00459     }
00460     //kDebug() << "marked as user moved" << pos()
00461     //         << (d->containment->containmentType() == Containment::PanelContainment);
00462 }
00463 
00464 void ToolBox::reposition()
00465 {
00466     if (d->userMoved) {
00467         //FIXME: adjust for situations like changing of the available space
00468         load();
00469         return;
00470     }
00471 
00472     if (d->containment->containmentType() == Containment::PanelContainment ||
00473         d->containment->containmentType() == Containment::CustomPanelContainment) {
00474         QRectF rect = boundingRect();
00475         if (d->containment->formFactor() == Vertical) {
00476             setCorner(ToolBox::Bottom);
00477             setPos(d->containment->geometry().width() / 2 - rect.width() / 2,
00478                    d->containment->geometry().height() - rect.height());
00479         } else {
00480             //defaulting to Horizontal right now
00481             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00482                 setPos(d->containment->geometry().left(),
00483                        d->containment->geometry().height() / 2 - rect.height() / 2);
00484                 setCorner(ToolBox::Left);
00485             } else {
00486                 setPos(d->containment->geometry().width() - rect.width(),
00487                        d->containment->geometry().height() / 2 - rect.height() / 2);
00488                 setCorner(ToolBox::Right);
00489             }
00490         }
00491 
00492         //kDebug() << "got ourselves a panel containment, moving to" << pos();
00493     } else if (d->containment->corona()) {
00494         //kDebug() << "desktop";
00495 
00496         int screen = d->containment->screen();
00497         QRectF avail = d->containment->geometry();
00498         QRectF screenGeom = avail;
00499 
00500         if (screen > -1 && screen < d->containment->corona()->numScreens()) {
00501             avail = d->containment->corona()->availableScreenRegion(screen).boundingRect();
00502             screenGeom = d->containment->corona()->screenGeometry(screen);
00503             avail.translate(-screenGeom.topLeft());
00504         }
00505 
00506         // Transform to the containment's coordinate system.
00507         screenGeom.moveTo(0, 0);
00508 
00509         if (!d->containment->view() || !d->containment->view()->transform().isScaling()) {
00510             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00511                 if (avail.top() > screenGeom.top()) {
00512                     setPos(avail.topLeft() - QPoint(0, avail.top()));
00513                     setCorner(ToolBox::Left);
00514                 } else if (avail.left() > screenGeom.left()) {
00515                     setPos(avail.topLeft() - QPoint(boundingRect().width(), 0));
00516                     setCorner(ToolBox::Top);
00517                 } else {
00518                     setPos(avail.topLeft());
00519                     setCorner(ToolBox::TopLeft);
00520                 }
00521             } else {
00522                 if (avail.top() > screenGeom.top()) {
00523                     setPos(avail.topRight() - QPoint(boundingRect().width(), -avail.top()));
00524                     setCorner(ToolBox::Right);
00525                 } else if (avail.right() < screenGeom.right()) {
00526                     setPos(avail.topRight() - QPoint(boundingRect().width(), 0));
00527                     setCorner(ToolBox::Top);
00528                 } else {
00529                     setPos(avail.topRight() - QPoint(boundingRect().width(), 0));
00530                     setCorner(ToolBox::TopRight);
00531                 }
00532             }
00533         } else {
00534             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00535                 setPos(d->containment->mapFromScene(QPointF(d->containment->geometry().topLeft())));
00536                 setCorner(ToolBox::TopLeft);
00537             } else {
00538                 setPos(d->containment->mapFromScene(QPointF(d->containment->geometry().topRight())));
00539                 setCorner(ToolBox::TopRight);
00540             }
00541         }
00542     }
00543 }
00544 
00545 } // plasma namespace
00546 
00547 #include "toolbox_p.moc"
00548 

Plasma

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal