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 <kdebug.h>
00033
00034 #include "corona.h"
00035 #include "theme.h"
00036 #include "widgets/iconwidget.h"
00037
00038 namespace Plasma
00039 {
00040
00041 class ToolBoxPrivate
00042 {
00043 public:
00044 ToolBoxPrivate(Containment *c)
00045 : containment(c),
00046 size(50),
00047 iconSize(32, 32),
00048 corner(ToolBox::TopRight),
00049 hidden(false),
00050 showing(false),
00051 movable(false),
00052 toolbar(false),
00053 dragging(false),
00054 userMoved(false)
00055 {}
00056
00057 Containment *containment;
00058 int size;
00059 QSize iconSize;
00060 ToolBox::Corner corner;
00061 QPoint dragStartRelative;
00062 QTransform viewTransform;
00063 bool hidden : 1;
00064 bool showing : 1;
00065 bool movable : 1;
00066 bool toolbar : 1;
00067 bool dragging : 1;
00068 bool userMoved : 1;
00069 };
00070
00071 ToolBox::ToolBox(Containment *parent)
00072 : QGraphicsItem(parent),
00073 d(new ToolBoxPrivate(parent))
00074 {
00075 d->userMoved = false;
00076 setAcceptsHoverEvents(true);
00077 }
00078
00079 ToolBox::~ToolBox()
00080 {
00081 delete d;
00082 }
00083
00084 QPoint ToolBox::toolPosition(int toolHeight)
00085 {
00086 switch (d->corner) {
00087 case TopRight:
00088 return QPoint(d->size, -toolHeight);
00089 case Top:
00090 return QPoint((int)boundingRect().center().x() - d->iconSize.width(), -toolHeight);
00091 case TopLeft:
00092 return QPoint(-d->size, -toolHeight);
00093 case Left:
00094 return QPoint(-d->size, (int)boundingRect().center().y() - d->iconSize.height());
00095 case Right:
00096 return QPoint(d->size, (int)boundingRect().center().y() - d->iconSize.height());
00097 case BottomLeft:
00098 return QPoint(-d->size, toolHeight);
00099 case Bottom:
00100 return QPoint((int)boundingRect().center().x() - d->iconSize.width(), toolHeight);
00101 case BottomRight:
00102 default:
00103 return QPoint(d->size, toolHeight);
00104 }
00105 }
00106
00107 void ToolBox::addTool(QAction *action)
00108 {
00109 if (!action) {
00110 return;
00111 }
00112
00113 Plasma::IconWidget *tool = new Plasma::IconWidget(this);
00114
00115 tool->setAction(action);
00116 tool->setDrawBackground(true);
00117 tool->setOrientation(Qt::Horizontal);
00118 tool->resize(tool->sizeFromIconSize(22));
00119
00120 tool->hide();
00121 const int height = static_cast<int>(tool->boundingRect().height());
00122 tool->setPos(toolPosition(height));
00123 tool->setZValue(zValue() + 10);
00124 tool->setToolTip(action->text());
00125
00126
00127 connect(tool, SIGNAL(changed()), this, SLOT(updateToolBox()));
00128
00129 }
00130
00131 void ToolBox::updateToolBox()
00132 {
00133 if (d->showing) {
00134 d->showing = false;
00135 showToolBox();
00136 } else if (Plasma::IconWidget *tool = qobject_cast<Plasma::IconWidget *>(sender())) {
00137 tool->hide();
00138 }
00139 }
00140
00141 void ToolBox::removeTool(QAction *action)
00142 {
00143 foreach (QGraphicsItem *child, QGraphicsItem::children()) {
00144
00145 Plasma::IconWidget *tool = dynamic_cast<Plasma::IconWidget*>(child);
00146 if (tool && tool->action() == action) {
00147
00148 delete tool;
00149 break;
00150 }
00151 }
00152 }
00153
00154 int ToolBox::size() const
00155 {
00156 return d->size;
00157 }
00158
00159 void ToolBox::setSize(const int newSize)
00160 {
00161 d->size = newSize;
00162 }
00163
00164 QSize ToolBox::iconSize() const
00165 {
00166 return d->iconSize;
00167 }
00168
00169 void ToolBox::setIconSize(const QSize newSize)
00170 {
00171 d->iconSize = newSize;
00172 }
00173
00174 bool ToolBox::showing() const
00175 {
00176 return d->showing;
00177 }
00178
00179 void ToolBox::setShowing(const bool show)
00180 {
00181 d->showing = show;
00182 }
00183
00184 void ToolBox::setCorner(const Corner corner)
00185 {
00186 d->corner = corner;
00187 }
00188
00189 ToolBox::Corner ToolBox::corner() const
00190 {
00191 return d->corner;
00192 }
00193
00194 void ToolBox::mousePressEvent(QGraphicsSceneMouseEvent *event)
00195 {
00196 event->accept();
00197
00198 d->dragStartRelative = mapToParent(event->pos()).toPoint() - pos().toPoint();
00199 }
00200
00201 void ToolBox::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00202 {
00203 if (!d->movable || (!d->dragging && boundingRect().contains(event->pos())) || isToolbar()) {
00204 return;
00205 }
00206
00207 d->dragging = true;
00208 d->userMoved = true;
00209 const QPoint newPos = mapToParent(event->pos()).toPoint();
00210 const QPoint curPos = pos().toPoint();
00211 const int h = abs((int)boundingRect().height());
00212 const int w = abs((int)boundingRect().width());
00213
00214 const int areaWidth = parentWidget()->size().width();
00215 const int areaHeight = parentWidget()->size().height();
00216
00217 int x = curPos.x();
00218 int y = curPos.y();
00219
00220
00221 int distanceToLeft = newPos.x() - d->dragStartRelative.x();
00222 int distanceToRight = areaWidth - w - distanceToLeft;
00223 int distanceToTop = newPos.y() - d->dragStartRelative.y();
00224 int distanceToBottom = areaHeight - h - distanceToTop;
00225
00226
00227 if (distanceToLeft < distanceToTop && distanceToLeft < distanceToRight &&
00228 distanceToLeft < distanceToBottom ) {
00229 x = 0;
00230 y = (newPos.y() - d->dragStartRelative.y());
00231 }
00232 else if (distanceToRight < distanceToTop && distanceToRight < distanceToLeft &&
00233 distanceToRight < distanceToBottom) {
00234 x = areaWidth - w;
00235 y = (newPos.y() - d->dragStartRelative.y());
00236 }
00237 else if (distanceToTop < distanceToLeft && distanceToTop < distanceToRight &&
00238 distanceToTop < distanceToBottom ) {
00239 y = 0;
00240 x = (newPos.x() - d->dragStartRelative.x());
00241 }
00242 else if (distanceToBottom < distanceToLeft && distanceToBottom < distanceToRight &&
00243 distanceToBottom < distanceToTop) {
00244 y = areaHeight - h;
00245 x = (newPos.x() - d->dragStartRelative.x());
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 x = qBound(0, x, areaWidth - w);
00272 y = qBound(0, y, areaHeight - h);
00273
00274 Corner newCorner = d->corner;
00275 if (x == 0) {
00276 if (y == 0) {
00277 newCorner = TopLeft;
00278 } else if (y + h >= areaHeight) {
00279 newCorner = BottomLeft;
00280 } else {
00281 newCorner = Left;
00282 }
00283 } else if (y == 0) {
00284 if (x + w >= areaWidth) {
00285 newCorner = TopRight;
00286 } else {
00287 newCorner = Top;
00288 }
00289 } else if (x + w >= areaWidth) {
00290 if (y + h >= areaHeight) {
00291 newCorner = BottomRight;
00292 } else {
00293 newCorner = Right;
00294 }
00295 } else {
00296 newCorner = Bottom;
00297 }
00298
00299 if (newCorner != d->corner) {
00300 prepareGeometryChange();
00301 d->corner = newCorner;
00302 }
00303
00304 setPos(x, y);
00305 }
00306
00307 void ToolBox::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00308 {
00309 if (!d->dragging && boundingRect().contains(event->pos())) {
00310 emit toggled();
00311 }
00312
00313 d->dragging = false;
00314 KConfigGroup cg(d->containment->config());
00315 save(cg);
00316 }
00317
00318 bool ToolBox::isMovable() const
00319 {
00320 return d->movable;
00321 }
00322
00323 void ToolBox::setIsMovable(bool movable)
00324 {
00325 d->movable = movable;
00326 }
00327
00328 bool ToolBox::isToolbar() const
00329 {
00330 return d->toolbar;
00331 }
00332
00333 void ToolBox::setIsToolbar(bool toolbar)
00334 {
00335 d->toolbar = toolbar;
00336 }
00337
00338 QTransform ToolBox::viewTransform() const
00339 {
00340 return d->viewTransform;
00341 }
00342
00343 void ToolBox::setViewTransform(QTransform transform)
00344 {
00345 if (transform.isScaling()) {
00346 d->toolbar = true;
00347 showToolBox();
00348 } else {
00349 d->toolbar = false;
00350 if (d->viewTransform != transform) {
00351 hideToolBox();
00352 }
00353 }
00354 d->viewTransform = transform;
00355 }
00356
00357 void ToolBox::save(KConfigGroup &cg) const
00358 {
00359 if (!d->movable) {
00360 return;
00361 }
00362
00363 KConfigGroup group(&cg, "ToolBox");
00364 if (!d->userMoved) {
00365 group.deleteGroup();
00366 return;
00367 }
00368
00369 int offset = 0;
00370 if (d->corner == ToolBox::Left ||
00371 d->corner == ToolBox::Right) {
00372 offset = y();
00373 } else if (d->corner == ToolBox::Left ||
00374 d->corner == ToolBox::Right) {
00375 offset = x();
00376 }
00377
00378 group.writeEntry("corner", int(d->corner));
00379 group.writeEntry("offset", offset);
00380 }
00381
00382 void ToolBox::load()
00383 {
00384 if (!d->movable) {
00385 return;
00386 }
00387
00388 KConfigGroup group = d->containment->config();
00389 group = KConfigGroup(&group, "ToolBox");
00390
00391 if (!group.hasKey("corner")) {
00392 return;
00393 }
00394
00395 d->userMoved = true;
00396 d->corner = Corner(group.readEntry("corner", int(d->corner)));
00397
00398 int offset = group.readEntry("offset", 0);
00399 switch (d->corner) {
00400 case ToolBox::TopLeft:
00401 setPos(0, 0);
00402 break;
00403 case ToolBox::Top:
00404 setPos(offset, 0);
00405 break;
00406 case ToolBox::TopRight:
00407 setPos(d->containment->size().width() - d->size, 0);
00408 break;
00409 case ToolBox::Right:
00410 setPos(d->containment->size().width() - d->size, offset);
00411 break;
00412 case ToolBox::BottomRight:
00413 setPos(d->containment->size().width() - d->size, d->containment->size().height() - d->size);
00414 break;
00415 case ToolBox::Bottom:
00416 setPos(offset, d->containment->size().height() - d->size);
00417 break;
00418 case ToolBox::BottomLeft:
00419 setPos(0, d->containment->size().height() - d->size);
00420 break;
00421 case ToolBox::Left:
00422 setPos(0, offset);
00423 break;
00424 }
00425
00426
00427 }
00428
00429 void ToolBox::reposition()
00430 {
00431 if (d->userMoved) {
00432
00433 load();
00434 return;
00435 }
00436
00437 if (d->containment->containmentType() == Containment::PanelContainment) {
00438 QRectF rect = boundingRect();
00439 if (d->containment->formFactor() == Vertical) {
00440 setCorner(ToolBox::Bottom);
00441 setPos(d->containment->geometry().width() / 2 - rect.width() / 2,
00442 d->containment->geometry().height() - rect.height());
00443 } else {
00444
00445 if (QApplication::layoutDirection() == Qt::RightToLeft) {
00446 setPos(d->containment->geometry().left(),
00447 d->containment->geometry().height() / 2 - rect.height() / 2);
00448 setCorner(ToolBox::Left);
00449 } else {
00450 setPos(d->containment->geometry().width() - rect.width(),
00451 d->containment->geometry().height() / 2 - rect.height() / 2);
00452 setCorner(ToolBox::Right);
00453 }
00454 }
00455
00456 } else if (d->containment->corona()) {
00457
00458
00459 int screen = d->containment->screen();
00460 QRectF avail = d->containment->geometry();
00461 QRectF screenGeom = avail;
00462
00463 if (screen > -1 && screen < d->containment->corona()->numScreens()) {
00464 avail = d->containment->corona()->availableScreenRegion(screen).boundingRect();
00465 screenGeom = d->containment->corona()->screenGeometry(screen);
00466 avail.translate(-screenGeom.topLeft());
00467 }
00468
00469
00470 screenGeom.moveTo(0, 0);
00471
00472 if (!d->containment->view() || !d->containment->view()->transform().isScaling()) {
00473 if (QApplication::layoutDirection() == Qt::RightToLeft) {
00474 if (avail.top() > screenGeom.top()) {
00475 setPos(avail.topLeft() - QPoint(0, d->size));
00476 setCorner(ToolBox::Left);
00477 } else if (avail.left() > screenGeom.left()) {
00478 setPos(avail.topLeft() - QPoint(d->size, 0));
00479 setCorner(ToolBox::Top);
00480 } else {
00481 setPos(avail.topLeft());
00482 setCorner(ToolBox::TopLeft);
00483 }
00484 } else {
00485 if (avail.top() > screenGeom.top()) {
00486 setPos(avail.topRight() - QPoint(0, d->size));
00487 setCorner(ToolBox::Right);
00488 } else if (avail.right() < screenGeom.right()) {
00489 setPos(avail.topRight() - QPoint(d->size, 0));
00490 setCorner(ToolBox::Top);
00491 } else {
00492 setPos(avail.topRight() - QPoint(d->size, 0));
00493 setCorner(ToolBox::TopRight);
00494 }
00495 }
00496 } else {
00497 if (QApplication::layoutDirection() == Qt::RightToLeft) {
00498 setPos(d->containment->mapFromScene(QPointF(d->containment->geometry().topLeft())));
00499 setCorner(ToolBox::TopLeft);
00500 } else {
00501 setPos(d->containment->mapFromScene(QPointF(d->containment->geometry().topRight())));
00502 setCorner(ToolBox::TopRight);
00503 }
00504 }
00505 }
00506 }
00507
00508 }
00509
00510 #include "toolbox_p.moc"
00511