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

Plasma

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

Skip menu "kdelibs-4.9.4 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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