00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00137 connect(tool, SIGNAL(changed()), this, SLOT(updateToolBox()));
00138 connect(action, SIGNAL(triggered(bool)), this, SLOT(toolTriggered(bool)));
00139
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
00166 Plasma::IconWidget *tool = dynamic_cast<Plasma::IconWidget*>(child);
00167 if (tool && tool->action() == action) {
00168
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
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
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
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
00461
00462 }
00463
00464 void ToolBox::reposition()
00465 {
00466 if (d->userMoved) {
00467
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
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
00493 } else if (d->containment->corona()) {
00494
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
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 }
00546
00547 #include "toolbox_p.moc"
00548