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

Plasma

  • sources
  • kde-4.12
  • kdelibs
  • plasma
dialog.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 by Alessandro Diaferia <alediaferia@gmail.com>
3  * Copyright 2007 by Alexis Ménard <darktears31@gmail.com>
4  * Copyright 2007 Sebastian Kuegler <sebas@kde.org>
5  * Copyright 2006 Aaron Seigo <aseigo@kde.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library 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 GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301 USA
21  */
22 
23 #include "dialog.h"
24 #include "private/dialog_p.h"
25 
26 #include <QPainter>
27 #include <QSvgRenderer>
28 #include <QResizeEvent>
29 #include <QMouseEvent>
30 #ifdef Q_WS_X11
31 #include <QX11Info>
32 #endif
33 #include <QBitmap>
34 #include <QTimer>
35 #include <QtGui/QVBoxLayout>
36 #include <QtGui/QGraphicsSceneEvent>
37 #include <QtGui/QGraphicsView>
38 #include <QtGui/QGraphicsWidget>
39 #include <QApplication>
40 #include <QDesktopWidget>
41 #include <QVarLengthArray>
42 #include <QGraphicsLayout>
43 
44 #include <kdebug.h>
45 #include <kwindowsystem.h>
46 #include <netwm.h>
47 
48 #include "plasma/applet.h"
49 #include "plasma/animator.h"
50 #include "plasma/containment.h"
51 #include "plasma/corona.h"
52 #include "plasma/extenders/extender.h"
53 #include "plasma/private/extender_p.h"
54 #include "plasma/private/dialogshadows_p.h"
55 #include "plasma/framesvg.h"
56 #include "plasma/theme.h"
57 #include "plasma/widgets/scrollwidget.h"
58 #include "plasma/windoweffects.h"
59 
60 #ifdef Q_WS_X11
61 #include <X11/Xlib.h>
62 #endif
63 
64 namespace Plasma
65 {
66 
67 void DialogPrivate::scheduleBorderCheck(bool triggeredByResize)
68 {
69  //kDebug();
70  if (triggeredByResize) {
71  resizeChecksWithBorderCheck = true;
72 
73  // to keep the UI as fluid as possible, we call checkBorders
74  // immediately when there is a resize, and therefore stop any
75  // move-triggered scheduled calls to it. this keeps things
76  // looking reasonable during resize while avoiding as many
77  // calls to checkBorders as possible
78  if (moveTimer) {
79  moveTimer->stop();
80  }
81 
82  checkBorders();
83  return;
84  }
85 
86  if (!moveTimer) {
87  moveTimer = new QTimer(q);
88  moveTimer->setSingleShot(true);
89  QObject::connect(moveTimer, SIGNAL(timeout()), q, SLOT(checkBorders()));
90  }
91 
92  moveTimer->start(0);
93 }
94 
95 void DialogPrivate::themeChanged()
96 {
97  checkBorders(false);
98 
99  const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
100  // WA_NoSystemBackground is going to fail combined with sliding popups, but is needed
101  // when we aren't compositing
102  q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
103  WindowEffects::overrideShadow(q->winId(), !DialogShadows::self()->enabled());
104  updateMask();
105  q->update();
106 }
107 
108 void DialogPrivate::updateMask()
109 {
110  const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
111  WindowEffects::enableBlurBehind(q->winId(), translucency,
112  translucency ? background->mask() : QRegion());
113  if (translucency) {
114  q->clearMask();
115  } else {
116  q->setMask(background->mask());
117  }
118 }
119 
120 void DialogPrivate::checkBorders()
121 {
122  checkBorders(true);
123 }
124 
125 void DialogPrivate::delayedAdjustSize()
126 {
127  q->syncToGraphicsWidget();
128 }
129 
130 void DialogPrivate::checkBorders(bool updateMaskIfNeeded)
131 {
132  if (resizeChecksWithBorderCheck) {
133  background->resizeFrame(q->size());
134  }
135 
136  QGraphicsWidget *graphicsWidget = graphicsWidgetPtr.data();
137  const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
138  FrameSvg::EnabledBorders borders = FrameSvg::AllBorders;
139 
140  Extender *extender = qobject_cast<Extender*>(graphicsWidget);
141  Plasma::Applet *applet = appletPtr.data();
142 
143  //used to remove borders at the edge of the desktop
144  QRegion avail;
145  QRect screenGeom;
146  QDesktopWidget *desktop = QApplication::desktop();
147  Plasma::Corona *c = 0;
148  if (applet) {
149  c = qobject_cast<Plasma::Corona *>(applet->scene());
150  } else if (graphicsWidget) {
151  c = qobject_cast<Plasma::Corona *>(graphicsWidget->scene());
152  }
153  if (c) {
154  avail = c->availableScreenRegion(desktop->screenNumber(q));
155  screenGeom = c->screenGeometry(desktop->screenNumber(q));
156  } else {
157  avail = QRegion(desktop->availableGeometry(desktop->screenNumber(q)));
158  screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
159  }
160 
161  QRect dialogGeom = q->geometry();
162 
163  qreal topHeight(0);
164  qreal leftWidth(0);
165  qreal rightWidth(0);
166  qreal bottomHeight(0);
167 
168  //decide about disabling the border attached to the panel
169  //don't cut borders on tooltips
170  if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
171  background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
172 
173  switch (applet->location()) {
174  case BottomEdge:
175  if (applet->containment() &&
176  dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
177  dialogGeom.width() <= applet->containment()->size().width()) {
178  borders &= ~FrameSvg::BottomBorder;
179  leftWidth = 0;
180  rightWidth = 0;
181  bottomHeight = 0;
182  }
183  break;
184 
185  case TopEdge:
186  if (applet->containment() &&
187  dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
188  dialogGeom.width() <= applet->containment()->size().width()) {
189  borders &= ~FrameSvg::TopBorder;
190  topHeight = 0;
191  leftWidth = 0;
192  rightWidth = 0;
193  }
194  break;
195 
196  case LeftEdge:
197  if (applet->containment() &&
198  dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
199  dialogGeom.height() <= applet->containment()->size().height()) {
200  borders &= ~FrameSvg::LeftBorder;
201  leftWidth = 0;
202  rightWidth = 0;
203  }
204  break;
205 
206  case RightEdge:
207  if (applet->containment() &&
208  dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
209  dialogGeom.height() <= applet->containment()->size().height()) {
210  borders &= ~FrameSvg::RightBorder;
211  leftWidth = 0;
212  rightWidth = 0;
213  }
214  break;
215 
216  default:
217  break;
218  }
219  }
220 
221  //decide if to disable the other borders
222  if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
223  if (!avail.contains(QPoint(dialogGeom.left()-1, dialogGeom.center().y()))) {
224  borders &= ~FrameSvg::LeftBorder;
225  }
226  if (!avail.contains(QPoint(dialogGeom.center().x(), dialogGeom.top()-1))) {
227  borders &= ~FrameSvg::TopBorder;
228  }
229  //FIXME: that 2 pixels offset has probably something to do with kwin
230  if (!avail.contains(QPoint(dialogGeom.right()+1, dialogGeom.center().y()))) {
231  borders &= ~FrameSvg::RightBorder;
232  }
233  if (!avail.contains(QPoint(dialogGeom.center().x(), dialogGeom.bottom()+1))) {
234  borders &= ~FrameSvg::BottomBorder;
235  }
236  }
237 
238  background->setEnabledBorders(borders);
239  DialogShadows::self()->addWindow(q, borders);
240 
241  if (extender) {
242  FrameSvg::EnabledBorders disabledBorders = FrameSvg::NoBorder;
243  if (!(borders & FrameSvg::LeftBorder)) {
244  disabledBorders |= FrameSvg::LeftBorder;
245  }
246  if (!(borders & FrameSvg::RightBorder)) {
247  disabledBorders |= FrameSvg::RightBorder;
248  }
249  extender->d->setDisabledBordersHint(disabledBorders);
250 
251  //if there is a scrollbar, reserve a margin to not draw it over the shadow
252  qreal left, top, right, bottom;
253  background->getMargins(left, top, right, bottom);
254  if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
255  if (QApplication::layoutDirection() == Qt::RightToLeft) {
256  leftWidth = left;
257  } else {
258  rightWidth = right;
259  }
260  }
261  } else {
262  background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
263  }
264 
265  //kDebug() << leftWidth << topHeight << rightWidth << bottomHeight;
266  q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
267 
268  if (resizeChecksWithBorderCheck) {
269  updateResizeCorners();
270  updateMask();
271  q->update();
272  } else if (currentBorders != borders) {
273  if (updateMaskIfNeeded) {
274  updateMask();
275  }
276 
277  q->update();
278  }
279 
280  resizeChecksWithBorderCheck = false;
281 }
282 
283 void Dialog::syncToGraphicsWidget()
284 {
285  d->adjustViewTimer->stop();
286  QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
287  if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
288  const int prevStartCorner = d->resizeStartCorner;
289  d->resizeStartCorner = -1;
290  QSize prevSize = size();
291  /*
292  kDebug() << "Widget size:" << graphicsWidget->size()
293  << "| Widget size hint:" << graphicsWidget->effectiveSizeHint(Qt::PreferredSize)
294  << "| Widget minsize hint:" << graphicsWidget->minimumSize()
295  << "| Widget maxsize hint:" << graphicsWidget->maximumSize()
296  << "| Widget bounding rect:" << graphicsWidget->sceneBoundingRect();
297  */
298  //set the sizehints correctly:
299  int left, top, right, bottom;
300  getContentsMargins(&left, &top, &right, &bottom);
301 
302  QDesktopWidget *desktop = QApplication::desktop();
303  QSize maxSize = desktop->availableGeometry(desktop->screenNumber(this)).size();
304 
305  setMinimumSize(0, 0);
306  setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
307 
308  QSize newSize(qMin(int(graphicsWidget->size().width()) + left + right, maxSize.width()),
309  qMin(int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
310 
311  const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
312  QSize newMinimumSize(qMin(int(minimum.width()) + left + right, maxSize.width()),
313  qMin(int(minimum.height()) + top + bottom, maxSize.height()));
314 
315 
316  QSize newMaximumSize(qMin(int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
317  qMin(int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
318 
319 
320  Plasma::Applet *applet = d->appletPtr.data();
321  if (applet) {
322  QRect currentGeometry(geometry());
323  currentGeometry.setSize(newSize);
324  if (applet->location() == Plasma::TopEdge ||
325  applet->location() == Plasma::LeftEdge) {
326  currentGeometry.setSize(newSize);
327  } else if (applet->location() == Plasma::RightEdge) {
328  currentGeometry.moveTopRight(geometry().topRight());
329  //BottomEdge and floating
330  } else {
331  currentGeometry.moveBottomLeft(geometry().bottomLeft());
332  }
333  setGeometry(currentGeometry);
334  } else {
335  resize(newSize);
336  }
337 
338  setMinimumSize(newMinimumSize);
339  setMaximumSize(newMaximumSize);
340 
341 
342  updateGeometry();
343 
344  //reposition and resize the view.
345  //force a valid rect, otherwise it will take up the whole scene
346  QRectF sceneRect(graphicsWidget->sceneBoundingRect());
347 
348  sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
349  sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
350  d->view->setSceneRect(sceneRect);
351 
352  //d->view->resize(graphicsWidget->size().toSize());
353  d->view->centerOn(graphicsWidget);
354 
355  if (size() != prevSize) {
356  //the size of the dialog has changed, emit the signal:
357  emit dialogResized();
358  }
359 
360  d->resizeStartCorner = prevStartCorner;
361  }
362 }
363 
364 int DialogPrivate::calculateWidthForHeightAndRatio(int height, qreal ratio)
365 {
366  switch (aspectRatioMode) {
367  case KeepAspectRatio:
368  return qRound(height * ratio);
369  break;
370  case Square:
371  return height;
372  break;
373  case ConstrainedSquare:
374  return height;
375  break;
376  default:
377  return -1;
378  }
379 }
380 
381 Dialog::Dialog(QWidget *parent, Qt::WindowFlags f)
382  : QWidget(parent, f | Qt::FramelessWindowHint),
383  d(new DialogPrivate(this))
384 {
385  setMouseTracking(true);
386  setAttribute(Qt::WA_TranslucentBackground);
387  d->background = new FrameSvg(this);
388  d->background->setImagePath("dialogs/background");
389  d->background->setEnabledBorders(FrameSvg::AllBorders);
390  d->background->resizeFrame(size());
391  connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(themeChanged()));
392 
393  QPalette pal = palette();
394  pal.setColor(backgroundRole(), Qt::transparent);
395  setPalette(pal);
396  WindowEffects::overrideShadow(winId(), !DialogShadows::self()->enabled());
397 
398  d->adjustViewTimer = new QTimer(this);
399  d->adjustViewTimer->setSingleShot(true);
400  connect(d->adjustViewTimer, SIGNAL(timeout()), this, SLOT(syncToGraphicsWidget()));
401 
402  d->adjustSizeTimer = new QTimer(this);
403  d->adjustSizeTimer->setSingleShot(true);
404  connect(d->adjustSizeTimer, SIGNAL(timeout()), this, SLOT(delayedAdjustSize()));
405 
406  d->themeChanged();
407 }
408 
409 Dialog::~Dialog()
410 {
411  DialogShadows::self()->removeWindow(this);
412  delete d;
413 }
414 
415 void Dialog::paintEvent(QPaintEvent *e)
416 {
417  QPainter p(this);
418  p.setCompositionMode(QPainter::CompositionMode_Source);
419  d->background->paintFrame(&p, e->rect(), e->rect());
420 }
421 
422 void Dialog::mouseMoveEvent(QMouseEvent *event)
423 {
424  if (event->modifiers() == Qt::AltModifier) {
425  unsetCursor();
426  } else if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
427  setCursor(Qt::SizeBDiagCursor);
428  } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
429  setCursor(Qt::SizeFDiagCursor);
430  } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
431  setCursor(Qt::SizeFDiagCursor);
432  } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
433  setCursor(Qt::SizeBDiagCursor);
434  } else if (!(event->buttons() & Qt::LeftButton)) {
435  unsetCursor();
436  }
437 
438  // here we take care of resize..
439  if (d->resizeStartCorner != Dialog::NoCorner) {
440  int newWidth;
441  int newHeight;
442  QPoint position;
443 
444  qreal aspectRatio = (qreal)width() / (qreal)height();
445 
446  switch(d->resizeStartCorner) {
447  case Dialog::NorthEast:
448  newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
449  newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
450  if (newWidth == -1) {
451  newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
452  }
453  position = QPoint(x(), y() + height() - newHeight);
454  break;
455  case Dialog::NorthWest:
456  newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
457  newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
458  if (newWidth == -1) {
459  newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
460  }
461  position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
462  break;
463  case Dialog::SouthWest:
464  newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
465  newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
466  if (newWidth == -1) {
467  newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
468  }
469  position = QPoint(x() + width() - newWidth, y());
470  break;
471  case Dialog::SouthEast:
472  newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
473  newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
474  if (newWidth == -1) {
475  newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
476  }
477  position = QPoint(x(), y());
478  break;
479  default:
480  newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
481  newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
482  if (newWidth == -1) {
483  newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
484  }
485  position = QPoint(x(), y());
486  break;
487  }
488 
489  QRect newGeom(position, QSize(newWidth, newHeight));
490 
491  // now sanity check the resize results again min constraints, if any
492  if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
493  newGeom.setLeft(d->leftResizeMin);
494  }
495 
496  if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
497  newGeom.setTop(d->topResizeMin);
498  }
499 
500  if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
501  newGeom.setRight(d->rightResizeMin);
502  }
503 
504  if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
505  newGeom.setBottom(d->bottomResizeMin);
506  }
507 
508  if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
509  setGeometry(newGeom);
510  }
511  }
512 
513  QWidget::mouseMoveEvent(event);
514 }
515 
516 void Dialog::mousePressEvent(QMouseEvent *event)
517 {
518  if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
519  d->resizeStartCorner = Dialog::NorthEast;
520  } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
521  d->resizeStartCorner = Dialog::NorthWest;
522  } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
523  d->resizeStartCorner = Dialog::SouthEast;
524  } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
525  d->resizeStartCorner = Dialog::SouthWest;
526  } else {
527  d->resizeStartCorner = Dialog::NoCorner;
528  }
529 
530  QWidget::mousePressEvent(event);
531 }
532 
533 void Dialog::mouseReleaseEvent(QMouseEvent *event)
534 {
535  if (d->resizeStartCorner != Dialog::NoCorner) {
536  emit dialogResized();
537  d->resizeStartCorner = Dialog::NoCorner;
538  unsetCursor();
539  }
540 
541  QWidget::mouseReleaseEvent(event);
542 }
543 
544 void Dialog::keyPressEvent(QKeyEvent *event)
545 {
546  if (event->key() == Qt::Key_Escape) {
547  hide();
548  }
549 }
550 
551 bool Dialog::event(QEvent *event)
552 {
553  return QWidget::event(event);
554 }
555 
556 void Dialog::resizeEvent(QResizeEvent *event)
557 {
558  Q_UNUSED(event)
559  //kDebug();
560  d->scheduleBorderCheck(true);
561 
562  if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
563  QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
564  graphicsWidget->resize(d->view->size());
565 
566  QRectF sceneRect(graphicsWidget->sceneBoundingRect());
567  sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
568  sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
569  d->view->setSceneRect(sceneRect);
570  d->view->centerOn(graphicsWidget);
571  }
572 }
573 
574 void DialogPrivate::updateResizeCorners()
575 {
576  const int resizeAreaMargin = 20;
577  const QRect r = q->rect();
578  const FrameSvg::EnabledBorders borders = background->enabledBorders();
579 
580  // IMPLEMENTATION NOTE: we set resize corners for the corners set, but also
581  // for the complimentary corners if we've cut out an edge of our SVG background
582  // which implies we are up against an immovable edge (e.g. a screen edge)
583 
584  resizeAreas.clear();
585  if (resizeCorners & Dialog::NorthEast ||
586  (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
587  (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
588  resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
589  resizeAreaMargin, resizeAreaMargin);
590  }
591 
592  if (resizeCorners & Dialog::NorthWest ||
593  (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
594  (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
595  resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
596  }
597 
598  if (resizeCorners & Dialog::SouthEast ||
599  (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
600  (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
601  resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
602  r.bottom() - resizeAreaMargin,
603  resizeAreaMargin, resizeAreaMargin);
604  }
605 
606  if (resizeCorners & Dialog::SouthWest ||
607  (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
608  (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
609  resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
610  resizeAreaMargin, resizeAreaMargin);
611  }
612 }
613 
614 void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
615 {
616  if (d->graphicsWidgetPtr) {
617  d->graphicsWidgetPtr.data()->removeEventFilter(this);
618  }
619 
620  d->graphicsWidgetPtr = widget;
621 
622  if (widget) {
623  Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
624  if (c) {
625  c->addOffscreenWidget(widget);
626  }
627 
628  if (!layout()) {
629  QVBoxLayout *lay = new QVBoxLayout(this);
630  lay->setMargin(0);
631  lay->setSpacing(0);
632  }
633 
634  d->checkBorders();
635 
636  if (!d->view) {
637  d->view = new QGraphicsView(this);
638  d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
639  d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
640  d->view->setFrameShape(QFrame::NoFrame);
641  d->view->viewport()->setAutoFillBackground(false);
642  layout()->addWidget(d->view);
643  }
644 
645  d->view->setScene(widget->scene());
646 
647  //try to have the proper size -before- showing the dialog
648  d->view->centerOn(widget);
649  if (widget->layout()) {
650  widget->layout()->activate();
651  }
652  static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
653  widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
654 
655  syncToGraphicsWidget();
656 
657  //d->adjustSizeTimer->start(150);
658 
659  widget->installEventFilter(this);
660  d->view->installEventFilter(this);
661  } else {
662  delete d->view;
663  d->view = 0;
664  }
665 }
666 
667 //KDE5 FIXME: should be const
668 QGraphicsWidget *Dialog::graphicsWidget()
669 {
670  return d->graphicsWidgetPtr.data();
671 }
672 
673 bool Dialog::eventFilter(QObject *watched, QEvent *event)
674 {
675  if (d->resizeStartCorner == Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
676  (event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
677  d->adjustViewTimer->start(150);
678  }
679 
680  // when moving the cursor with a 45° angle from the outside
681  // to the inside passing over a resize angle the cursor changes its
682  // shape to a resize cursor. As a side effect this is the only case
683  // when the cursor immediately enters the view without giving
684  // the dialog the chance to restore the original cursor shape.
685  if (event->type() == QEvent::Enter && watched == d->view) {
686  unsetCursor();
687  }
688 
689  return QWidget::eventFilter(watched, event);
690 }
691 
692 void Dialog::hideEvent(QHideEvent * event)
693 {
694  Q_UNUSED(event);
695  emit dialogVisible(false);
696 }
697 
698 void Dialog::showEvent(QShowEvent * event)
699 {
700  Q_UNUSED(event);
701 
702  //check if the widget size is still synced with the view
703  d->checkBorders();
704  d->updateResizeCorners();
705 
706  QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
707  if (graphicsWidget &&
708  ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
709  d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
710  d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
711  //here have to be done immediately, ideally should have to be done -before- shwing, but is not possible to catch show() so early
712  syncToGraphicsWidget();
713  d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
714  d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
715  }
716 
717  if (d->view) {
718  d->view->setFocus();
719  }
720 
721  if (graphicsWidget) {
722  graphicsWidget->setFocus();
723  }
724 
725  emit dialogVisible(true);
726  WindowEffects::overrideShadow(winId(), !DialogShadows::self()->enabled());
727  DialogShadows::self()->addWindow(this, d->background->enabledBorders());
728 }
729 
730 void Dialog::focusInEvent(QFocusEvent *event)
731 {
732  Q_UNUSED(event)
733 
734  if (d->view) {
735  d->view->setFocus();
736  }
737 
738  QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
739  if (graphicsWidget) {
740  graphicsWidget->setFocus();
741  }
742 }
743 
744 void Dialog::moveEvent(QMoveEvent *event)
745 {
746  Q_UNUSED(event)
747  //kDebug();
748  d->scheduleBorderCheck();
749 }
750 
751 void Dialog::setResizeHandleCorners(ResizeCorners corners)
752 {
753  if ((d->resizeCorners != corners) && (aspectRatioMode() != FixedSize)) {
754  d->resizeCorners = corners;
755  d->updateResizeCorners();
756  }
757 }
758 
759 Dialog::ResizeCorners Dialog::resizeCorners() const
760 {
761  return d->resizeCorners;
762 }
763 
764 bool Dialog::isUserResizing() const
765 {
766  return d->resizeStartCorner > NoCorner;
767 }
768 
769 void Dialog::setMinimumResizeLimits(int left, int top, int right, int bottom)
770 {
771  d->leftResizeMin = left;
772  d->topResizeMin = top;
773  d->rightResizeMin = right;
774  d->bottomResizeMin = bottom;
775 }
776 
777 void Dialog::getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
778 {
779  if (left) {
780  *left = d->leftResizeMin;
781  }
782 
783  if (top) {
784  *top = d->topResizeMin;
785  }
786 
787  if (right) {
788  *right = d->rightResizeMin;
789  }
790 
791  if (bottom) {
792  *bottom = d->bottomResizeMin;
793  }
794 }
795 
796 void Dialog::animatedHide(Plasma::Direction direction)
797 {
798  if (!isVisible()) {
799  return;
800  }
801 
802  if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
803  hide();
804  return;
805  }
806 
807  Location location = Desktop;
808  switch (direction) {
809  case Down:
810  location = BottomEdge;
811  break;
812  case Right:
813  location = RightEdge;
814  break;
815  case Left:
816  location = LeftEdge;
817  break;
818  case Up:
819  location = TopEdge;
820  break;
821  default:
822  break;
823  }
824 
825  Plasma::WindowEffects::slideWindow(this, location);
826  hide();
827 }
828 
829 void Dialog::animatedShow(Plasma::Direction direction)
830 {
831  if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
832  show();
833  return;
834  }
835 
836  //copied to not add new api
837  Location location = Desktop;
838  switch (direction) {
839  case Up:
840  location = BottomEdge;
841  break;
842  case Left:
843  location = RightEdge;
844  break;
845  case Right:
846  location = LeftEdge;
847  break;
848  case Down:
849  location = TopEdge;
850  break;
851  default:
852  break;
853  }
854 
855  if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
856  Plasma::WindowEffects::slideWindow(this, location);
857  }
858 
859  show();
860 }
861 
862 bool Dialog::inControlArea(const QPoint &point)
863 {
864  foreach (const QRect &r, d->resizeAreas) {
865  if (r.contains(point)) {
866  return true;
867  }
868  }
869  return false;
870 }
871 
872 Plasma::AspectRatioMode Dialog::aspectRatioMode() const
873 {
874  return d->aspectRatioMode;
875 }
876 
877 void Dialog::setAspectRatioMode(Plasma::AspectRatioMode mode)
878 {
879  if (mode == FixedSize) {
880  setResizeHandleCorners(NoCorner);
881  }
882 
883  d->aspectRatioMode = mode;
884 }
885 
886 }
887 #include "dialog.moc"
Plasma::Up
Display upwards.
Definition: plasma.h:91
Plasma::FrameSvg::LeftBorder
Definition: framesvg.h:91
Plasma::Corona::screenGeometry
virtual QRect screenGeometry(int id) const
Returns the geometry of a given screen.
Definition: corona.cpp:441
Plasma::Dialog::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *event)
Definition: dialog.cpp:533
windoweffects.h
Plasma::Dialog::dialogVisible
void dialogVisible(bool status)
Emit a signal when the dialog become visible/invisible.
Plasma::WindowEffects::enableBlurBehind
void enableBlurBehind(WId window, bool enable, const QRegion &region)
Instructs the window manager to blur the background in the specified region behind the given window...
Definition: windoweffects.cpp:310
Plasma::FrameSvg::NoBorder
Definition: framesvg.h:88
Plasma::WindowEffects::overrideShadow
void overrideShadow(WId window, bool override)
Forbid te windowmanager to automatically generate a shadow for this window.
Definition: windoweffects.cpp:294
Plasma::FrameSvg::AllBorders
Definition: framesvg.h:93
Plasma::Dialog::eventFilter
bool eventFilter(QObject *watched, QEvent *event)
Definition: dialog.cpp:673
Plasma::Dialog::animatedShow
void animatedShow(Plasma::Direction direction)
Causes an animated show; requires compositing to work, otherwise the dialog will simply show...
Definition: dialog.cpp:829
extender.h
Plasma::Applet::location
virtual Location location() const
Returns the location of the scene which is displaying applet.
Definition: applet.cpp:1618
Plasma::ConstrainedSquare
The applet is no wider (in horizontal formfactors) or no higher (in vertical ones) than a square...
Definition: plasma.h:215
Plasma::Dialog::aspectRatioMode
Plasma::AspectRatioMode aspectRatioMode() const
Definition: dialog.cpp:872
Plasma::Corona::availableScreenRegion
virtual QRegion availableScreenRegion(int id) const
Returns the available region for a given screen.
Definition: corona.cpp:454
QWidget
Plasma::Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
Definition: plasma.h:111
theme.h
Plasma::Dialog::isUserResizing
bool isUserResizing() const
Definition: dialog.cpp:764
containment.h
Plasma::FrameSvg
Provides an SVG with borders.
Definition: framesvg.h:76
QObject
Plasma::Square
The applet is always a square.
Definition: plasma.h:214
Plasma::Dialog::syncToGraphicsWidget
void syncToGraphicsWidget()
Adjusts the dialog to the associated QGraphicsWidget's geometry Should not normally need to be called...
Definition: dialog.cpp:283
Plasma::Dialog::hideEvent
void hideEvent(QHideEvent *event)
Definition: dialog.cpp:692
Plasma::Dialog::graphicsWidget
QGraphicsWidget * graphicsWidget()
Definition: dialog.cpp:668
Plasma::Dialog::resizeEvent
void resizeEvent(QResizeEvent *e)
Definition: dialog.cpp:556
Plasma::Dialog::focusInEvent
void focusInEvent(QFocusEvent *event)
Definition: dialog.cpp:730
Plasma::Dialog::setGraphicsWidget
void setGraphicsWidget(QGraphicsWidget *widget)
Sets a QGraphicsWidget to be shown as the content in this dialog.
Definition: dialog.cpp:614
Plasma::Dialog::moveEvent
void moveEvent(QMoveEvent *event)
Definition: dialog.cpp:744
Plasma::Applet
The base Applet class.
Definition: applet.h:77
Plasma::Location
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
Definition: plasma.h:108
Plasma::FrameSvg::TopBorder
Definition: framesvg.h:89
Plasma::Dialog::keyPressEvent
void keyPressEvent(QKeyEvent *event)
Definition: dialog.cpp:544
applet.h
Plasma::Dialog::inControlArea
bool inControlArea(const QPoint &point)
Convenience method to know whether the point is in a control area (e.g.
Definition: dialog.cpp:862
Plasma::KeepAspectRatio
The applet keeps a fixed aspect ratio.
Definition: plasma.h:213
Plasma::WindowEffects::slideWindow
void slideWindow(WId id, Plasma::Location location, int offset)
Mark a window as sliding from screen edge.
Definition: windoweffects.cpp:97
Plasma::Dialog::setMinimumResizeLimits
void setMinimumResizeLimits(int left, int top, int right, int bottom)
Sets the minimum values that each of four sides of the rect may expand to or from.
Definition: dialog.cpp:769
Plasma::Dialog::mousePressEvent
void mousePressEvent(QMouseEvent *event)
Definition: dialog.cpp:516
Plasma::Theme::windowTranslucencyEnabled
Q_INVOKABLE bool windowTranslucencyEnabled() const
Definition: theme.cpp:998
Plasma::TopEdge
Along the top of the screen.
Definition: plasma.h:114
Plasma::Dialog::animatedHide
void animatedHide(Plasma::Direction direction)
Causes an animated hide; requires compositing to work, otherwise the dialog will simply hide...
Definition: dialog.cpp:796
Plasma::Dialog::setAspectRatioMode
void setAspectRatioMode(Plasma::AspectRatioMode mode)
Sets the preferred aspect ratio mode for placement and resizing.
Definition: dialog.cpp:877
scrollwidget.h
Plasma::Dialog::SouthEast
Definition: dialog.h:61
Plasma::FrameSvg::BottomBorder
Definition: framesvg.h:90
Plasma::Dialog::NorthEast
Definition: dialog.h:60
Plasma::Dialog::event
bool event(QEvent *event)
Definition: dialog.cpp:551
Plasma::Down
Display downards.
Definition: plasma.h:90
Plasma::BottomEdge
Along the bottom of the screen.
Definition: plasma.h:115
Plasma::Dialog::Dialog
Dialog(QWidget *parent=0, Qt::WindowFlags f=Qt::Window)
Definition: dialog.cpp:381
dialog.h
Plasma::Dialog::getMinimumResizeLimits
void getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
Retrives the minimum resize limits for the dialog.
Definition: dialog.cpp:777
Plasma::Dialog::SouthWest
Definition: dialog.h:63
Plasma::Theme::defaultTheme
static Theme * defaultTheme()
Singleton pattern accessor.
Definition: theme.cpp:544
Plasma::FrameSvg::RightBorder
Definition: framesvg.h:92
corona.h
framesvg.h
Plasma::Dialog::~Dialog
virtual ~Dialog()
Definition: dialog.cpp:409
Plasma::Dialog::resizeCorners
ResizeCorners resizeCorners() const
Convenience method to get the enabled resize corners.
Definition: dialog.cpp:759
QGraphicsView
Plasma::Dialog::NorthWest
Definition: dialog.h:62
Plasma::RightEdge
Along the right side of the screen.
Definition: plasma.h:117
Plasma::Dialog::setResizeHandleCorners
void setResizeHandleCorners(ResizeCorners corners)
Definition: dialog.cpp:751
Plasma::Direction
Direction
The Direction enumeration describes in which direction, relative to the Applet (and its managing cont...
Definition: plasma.h:89
Plasma::Dialog::showEvent
void showEvent(QShowEvent *event)
Definition: dialog.cpp:698
animator.h
Plasma::Corona::addOffscreenWidget
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
Definition: corona.cpp:377
Plasma::Dialog::paintEvent
void paintEvent(QPaintEvent *e)
Reimplemented from QWidget.
Definition: dialog.cpp:415
Plasma::Right
Display to the right.
Definition: plasma.h:93
Plasma::LeftEdge
Along the left side of the screen.
Definition: plasma.h:116
Plasma::Dialog::dialogResized
void dialogResized()
Fires when the dialog automatically resizes.
Plasma::Dialog::NoCorner
Definition: dialog.h:59
Plasma::Left
Display to the left.
Definition: plasma.h:92
Plasma::Dialog::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event)
Definition: dialog.cpp:422
Plasma::FixedSize
Definition: plasma.h:218
Plasma::Corona
A QGraphicsScene for Plasma::Applets.
Definition: corona.h:48
Plasma::AspectRatioMode
AspectRatioMode
Defines the aspect ratio used when scaling an applet.
Definition: plasma.h:208
QGraphicsWidget
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:33 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Plasma

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

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