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

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