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

Skip menu "kdelibs-4.8.5 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