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

Plasma

dialog.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 by Alessandro Diaferia <alediaferia@gmail.com>
00003  * Copyright 2007 by Alexis Ménard <darktears31@gmail.com>
00004  * Copyright 2007 Sebastian Kuegler <sebas@kde.org>
00005  * Copyright 2006 Aaron Seigo <aseigo@kde.org>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor,
00020  * Boston, MA  02110-1301  USA
00021  */
00022 
00023 #include "dialog.h"
00024 #include "private/dialog_p.h"
00025 
00026 #include <QPainter>
00027 #include <QSvgRenderer>
00028 #include <QResizeEvent>
00029 #include <QMouseEvent>
00030 #ifdef Q_WS_X11
00031 #include <QX11Info>
00032 #endif
00033 #include <QBitmap>
00034 #include <QTimer>
00035 #include <QtGui/QVBoxLayout>
00036 #include <QtGui/QGraphicsSceneEvent>
00037 #include <QtGui/QGraphicsView>
00038 #include <QtGui/QGraphicsWidget>
00039 #include <QApplication>
00040 #include <QDesktopWidget>
00041 #include <QVarLengthArray>
00042 #include <QGraphicsLayout>
00043 
00044 #include <kdebug.h>
00045 #include <kwindowsystem.h>
00046 #include <netwm.h>
00047 
00048 #include "plasma/applet.h"
00049 #include "plasma/animator.h"
00050 #include "plasma/containment.h"
00051 #include "plasma/corona.h"
00052 #include "plasma/extenders/extender.h"
00053 #include "plasma/private/extender_p.h"
00054 #include "plasma/framesvg.h"
00055 #include "plasma/theme.h"
00056 #include "plasma/widgets/scrollwidget.h"
00057 #include "plasma/windoweffects.h"
00058 
00059 #ifdef Q_WS_X11
00060 #include <X11/Xlib.h>
00061 #endif
00062 
00063 namespace Plasma
00064 {
00065 
00066 void DialogPrivate::scheduleBorderCheck(bool triggeredByResize)
00067 {
00068     //kDebug();
00069     if (triggeredByResize) {
00070         resizeChecksWithBorderCheck = true;
00071 
00072         // to keep the UI as fluid as possible, we call checkBorders
00073         // immediately when there is a resize, and therefore stop any
00074         // move-triggered scheduled calls to it. this keeps things
00075         // looking reasonable during resize while avoiding as many
00076         // calls to checkBorders as possible
00077         if (moveTimer) {
00078             moveTimer->stop();
00079         }
00080 
00081         checkBorders();
00082         return;
00083     }
00084 
00085     if (!moveTimer) {
00086         moveTimer = new QTimer(q);
00087         moveTimer->setSingleShot(true);
00088         QObject::connect(moveTimer, SIGNAL(timeout()), q, SLOT(checkBorders()));
00089     }
00090 
00091     moveTimer->start(0);
00092 }
00093 
00094 void DialogPrivate::themeChanged()
00095 {
00096     checkBorders(false);
00097 
00098     const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
00099     // WA_NoSystemBackground is going to fail combined with sliding popups, but is needed
00100     // when we aren't compositing
00101     q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
00102     updateMask();
00103     q->update();
00104 }
00105 
00106 void DialogPrivate::updateMask()
00107 {
00108     const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled();
00109     WindowEffects::enableBlurBehind(q->winId(), translucency,
00110                                     translucency ? background->mask() : QRegion());
00111     if (translucency) {
00112         q->clearMask();
00113     } else {
00114         q->setMask(background->mask());
00115     }
00116 }
00117 
00118 void DialogPrivate::checkBorders()
00119 {
00120     checkBorders(true);
00121 }
00122 
00123 void DialogPrivate::delayedAdjustSize()
00124 {
00125     q->syncToGraphicsWidget();
00126 }
00127 
00128 void DialogPrivate::checkBorders(bool updateMaskIfNeeded)
00129 {
00130     if (resizeChecksWithBorderCheck) {
00131         background->resizeFrame(q->size());
00132     }
00133 
00134     QGraphicsWidget *graphicsWidget = graphicsWidgetPtr.data();
00135     const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
00136     FrameSvg::EnabledBorders borders = FrameSvg::AllBorders;
00137 
00138     Extender *extender = qobject_cast<Extender*>(graphicsWidget);
00139     Plasma::Applet *applet = appletPtr.data();
00140 
00141     //used to remove borders at the edge of the desktop
00142     QRect avail;
00143     QRect screenGeom;
00144     QDesktopWidget *desktop = QApplication::desktop();
00145     Plasma::Corona *c = 0;
00146     if (applet) {
00147         c = qobject_cast<Plasma::Corona *>(applet->scene());
00148     } else if (graphicsWidget) {
00149         c = qobject_cast<Plasma::Corona *>(graphicsWidget->scene());
00150     }
00151     if (c) {
00152         QRegion r = c->availableScreenRegion(desktop->screenNumber(q));
00153         QRect maxRect;
00154         foreach (QRect rect, r.rects()) {
00155             if (rect.width() > maxRect.width() && rect.height() > maxRect.height()) {
00156                 maxRect = rect;
00157             }
00158         }
00159         avail = maxRect;
00160         screenGeom = c->screenGeometry(desktop->screenNumber(q));
00161     } else {
00162         avail = desktop->availableGeometry(desktop->screenNumber(q));
00163         screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
00164     }
00165 
00166     QRect dialogGeom = q->geometry();
00167 
00168     qreal topHeight(0);
00169     qreal leftWidth(0);
00170     qreal rightWidth(0);
00171     qreal bottomHeight(0);
00172 
00173     //decide about disabling the border attached to the panel
00174     //don't cut borders on tooltips
00175     if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
00176         background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00177 
00178         switch (applet->location()) {
00179         case BottomEdge:
00180             if (applet->containment() &&
00181                 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
00182                 dialogGeom.width() <= applet->containment()->size().width()) {
00183                 borders &= ~FrameSvg::BottomBorder;
00184                 leftWidth = 0;
00185                 rightWidth = 0;
00186                 bottomHeight = 0;
00187             }
00188         break;
00189 
00190         case TopEdge:
00191             if (applet->containment() &&
00192                 dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
00193                 dialogGeom.width() <= applet->containment()->size().width()) {
00194                 borders &= ~FrameSvg::TopBorder;
00195                 topHeight = 0;
00196                 leftWidth = 0;
00197                 rightWidth = 0;
00198             }
00199         break;
00200 
00201         case LeftEdge:
00202             if (applet->containment() &&
00203                 dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
00204                 dialogGeom.height() <= applet->containment()->size().height()) {
00205                 borders &= ~FrameSvg::LeftBorder;
00206                 leftWidth = 0;
00207                 rightWidth = 0;
00208             }
00209         break;
00210 
00211         case RightEdge:
00212             if (applet->containment() &&
00213                 dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
00214                 dialogGeom.height() <= applet->containment()->size().height()) {
00215                 borders &= ~FrameSvg::RightBorder;
00216                 leftWidth = 0;
00217                 rightWidth = 0;
00218             }
00219         break;
00220 
00221         default:
00222         break;
00223         }
00224     }
00225 
00226     //decide if to disable the other borders
00227     if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
00228         if (dialogGeom.left() <= avail.left()) {
00229             borders &= ~FrameSvg::LeftBorder;
00230         }
00231         if (dialogGeom.top() <= avail.top()) {
00232             borders &= ~FrameSvg::TopBorder;
00233         }
00234         //FIXME: that 2 pixels offset has probably something to do with kwin
00235         if (dialogGeom.right() + 2 > avail.right()) {
00236             borders &= ~FrameSvg::RightBorder;
00237         }
00238         if (dialogGeom.bottom() + 2 > avail.bottom()) {
00239             borders &= ~FrameSvg::BottomBorder;
00240         }
00241     }
00242 
00243     background->setEnabledBorders(borders);
00244 
00245     if (extender)  {
00246         FrameSvg::EnabledBorders disabledBorders = FrameSvg::NoBorder;
00247         if (!(borders & FrameSvg::LeftBorder)) {
00248             disabledBorders |= FrameSvg::LeftBorder;
00249         }
00250         if (!(borders & FrameSvg::RightBorder)) {
00251             disabledBorders |= FrameSvg::RightBorder;
00252         }
00253         extender->d->setDisabledBordersHint(disabledBorders);
00254 
00255         //if there is a scrollbar, reserve a margin to not draw it over the shadow
00256         qreal left, top, right, bottom;
00257         background->getMargins(left, top, right, bottom);
00258         if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
00259             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00260                 leftWidth = left;
00261             } else {
00262                 rightWidth = right;
00263             }
00264         }
00265     } else {
00266         background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00267     }
00268 
00269     //kDebug() << leftWidth << topHeight << rightWidth << bottomHeight;
00270     q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00271 
00272     if (resizeChecksWithBorderCheck) {
00273         updateResizeCorners();
00274         updateMask();
00275         q->update();
00276     } else if (currentBorders != borders) {
00277         if (updateMaskIfNeeded) {
00278             updateMask();
00279         }
00280 
00281         q->update();
00282     }
00283 
00284     resizeChecksWithBorderCheck = false;
00285 }
00286 
00287 void Dialog::syncToGraphicsWidget()
00288 {
00289     d->adjustViewTimer->stop();
00290     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00291     if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
00292         const int prevStartCorner = d->resizeStartCorner;
00293         d->resizeStartCorner = -1;
00294         QSize prevSize = size();
00295         /*
00296         kDebug() << "Widget size:" << graphicsWidget->size()
00297                  << "| Widget size hint:" << graphicsWidget->effectiveSizeHint(Qt::PreferredSize)
00298                  << "| Widget minsize hint:" << graphicsWidget->minimumSize()
00299                  << "| Widget maxsize hint:" << graphicsWidget->maximumSize()
00300                  << "| Widget bounding rect:" << graphicsWidget->sceneBoundingRect();
00301         */
00302         //set the sizehints correctly:
00303         int left, top, right, bottom;
00304         getContentsMargins(&left, &top, &right, &bottom);
00305 
00306         QDesktopWidget *desktop = QApplication::desktop();
00307         QSize maxSize = desktop->availableGeometry(desktop->screenNumber(this)).size();
00308 
00309         setMinimumSize(0, 0);
00310         setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00311 
00312         QSize newSize(qMin(int(graphicsWidget->size().width()) + left + right, maxSize.width()),
00313                qMin(int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
00314 
00315         const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
00316         QSize newMinimumSize(qMin(int(minimum.width()) + left + right, maxSize.width()),
00317                        qMin(int(minimum.height()) + top + bottom, maxSize.height()));
00318 
00319 
00320         QSize newMaximumSize(qMin(int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
00321                        qMin(int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
00322 
00323 
00324         Plasma::Applet *applet = d->appletPtr.data();
00325         if (applet) {
00326             QRect currentGeometry(geometry());
00327             currentGeometry.setSize(newSize);
00328             if (applet->location() == Plasma::TopEdge ||
00329                 applet->location() == Plasma::LeftEdge) {
00330                 currentGeometry.setSize(newSize);
00331             } else if (applet->location() == Plasma::RightEdge) {
00332                 currentGeometry.moveTopRight(geometry().topRight());
00333             //BottomEdge and floating
00334             } else {
00335                 currentGeometry.moveBottomLeft(geometry().bottomLeft());
00336             }
00337             setGeometry(currentGeometry);
00338         } else {
00339             resize(newSize);
00340         }
00341 
00342         setMinimumSize(newMinimumSize);
00343         setMaximumSize(newMaximumSize);
00344 
00345 
00346         updateGeometry();
00347 
00348         //reposition and resize the view.
00349         //force a valid rect, otherwise it will take up the whole scene
00350         QRectF sceneRect(graphicsWidget->sceneBoundingRect());
00351 
00352         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00353         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00354         d->view->setSceneRect(sceneRect);
00355 
00356         //d->view->resize(graphicsWidget->size().toSize());
00357         d->view->centerOn(graphicsWidget);
00358 
00359         if (size() != prevSize) {
00360             //the size of the dialog has changed, emit the signal:
00361             emit dialogResized();
00362         }
00363 
00364         d->resizeStartCorner = prevStartCorner;
00365     }
00366 }
00367 
00368 int DialogPrivate::calculateWidthForHeightAndRatio(int height, qreal ratio)
00369 {
00370     switch (aspectRatioMode) {
00371         case KeepAspectRatio:
00372             return qRound(height * ratio);
00373             break;
00374         case Square:
00375             return height;
00376             break;
00377         case ConstrainedSquare:
00378             return height;
00379             break;
00380         default:
00381             return -1;
00382     }
00383 }
00384 
00385 Dialog::Dialog(QWidget *parent, Qt::WindowFlags f)
00386     : QWidget(parent, f | Qt::FramelessWindowHint),
00387       d(new DialogPrivate(this))
00388 {
00389     setMouseTracking(true);
00390     setAttribute(Qt::WA_TranslucentBackground);
00391     d->background = new FrameSvg(this);
00392     d->background->setImagePath("dialogs/background");
00393     d->background->setEnabledBorders(FrameSvg::AllBorders);
00394     d->background->resizeFrame(size());
00395     connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(themeChanged()));
00396 
00397     QPalette pal = palette();
00398     pal.setColor(backgroundRole(), Qt::transparent);
00399     setPalette(pal);
00400     WindowEffects::overrideShadow(winId(), true);
00401 
00402     d->adjustViewTimer = new QTimer(this);
00403     d->adjustViewTimer->setSingleShot(true);
00404     connect(d->adjustViewTimer, SIGNAL(timeout()), this, SLOT(syncToGraphicsWidget()));
00405 
00406     d->adjustSizeTimer = new QTimer(this);
00407     d->adjustSizeTimer->setSingleShot(true);
00408     connect(d->adjustSizeTimer, SIGNAL(timeout()), this, SLOT(delayedAdjustSize()));
00409 
00410     d->themeChanged();
00411 }
00412 
00413 Dialog::~Dialog()
00414 {
00415     delete d;
00416 }
00417 
00418 void Dialog::paintEvent(QPaintEvent *e)
00419 {
00420     QPainter p(this);
00421     p.setCompositionMode(QPainter::CompositionMode_Source);
00422     d->background->paintFrame(&p, e->rect(), e->rect());
00423 }
00424 
00425 void Dialog::mouseMoveEvent(QMouseEvent *event)
00426 {
00427     if (event->modifiers() == Qt::AltModifier) {
00428         unsetCursor();
00429     } else if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
00430         setCursor(Qt::SizeBDiagCursor);
00431     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
00432         setCursor(Qt::SizeFDiagCursor);
00433     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
00434         setCursor(Qt::SizeFDiagCursor);
00435     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
00436         setCursor(Qt::SizeBDiagCursor);
00437     } else if (!(event->buttons() & Qt::LeftButton)) {
00438         unsetCursor();
00439     }
00440 
00441     // here we take care of resize..
00442     if (d->resizeStartCorner != Dialog::NoCorner) {
00443         int newWidth;
00444         int newHeight;
00445         QPoint position;
00446 
00447         qreal aspectRatio = (qreal)width() / (qreal)height();
00448 
00449         switch(d->resizeStartCorner) {
00450             case Dialog::NorthEast:
00451                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00452                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00453                 if (newWidth == -1) {
00454                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00455                 }
00456                 position = QPoint(x(), y() + height() - newHeight);
00457                 break;
00458             case Dialog::NorthWest:
00459                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00460                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00461                 if (newWidth == -1) {
00462                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00463                 }
00464                 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
00465                 break;
00466             case Dialog::SouthWest:
00467                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00468                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00469                 if (newWidth == -1) {
00470                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00471                 }
00472                 position = QPoint(x() + width() - newWidth, y());
00473                 break;
00474             case Dialog::SouthEast:
00475                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00476                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00477                 if (newWidth == -1) {
00478                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00479                 }
00480                 position = QPoint(x(), y());
00481                 break;
00482              default:
00483                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
00484                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00485                 if (newWidth == -1) {
00486                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
00487                 }
00488                 position = QPoint(x(), y());
00489                 break;
00490         }
00491 
00492         QRect newGeom(position, QSize(newWidth, newHeight));
00493 
00494         // now sanity check the resize results again min constraints, if any
00495         if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
00496             newGeom.setLeft(d->leftResizeMin);
00497         }
00498 
00499         if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
00500             newGeom.setTop(d->topResizeMin);
00501         }
00502 
00503         if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
00504             newGeom.setRight(d->rightResizeMin);
00505         }
00506 
00507         if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
00508             newGeom.setBottom(d->bottomResizeMin);
00509         }
00510 
00511         if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
00512             setGeometry(newGeom);
00513         }
00514     }
00515 
00516     QWidget::mouseMoveEvent(event);
00517 }
00518 
00519 void Dialog::mousePressEvent(QMouseEvent *event)
00520 {
00521     if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
00522         d->resizeStartCorner = Dialog::NorthEast;
00523     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
00524         d->resizeStartCorner = Dialog::NorthWest;
00525     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
00526         d->resizeStartCorner = Dialog::SouthEast;
00527     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
00528         d->resizeStartCorner = Dialog::SouthWest;
00529     } else {
00530         d->resizeStartCorner = Dialog::NoCorner;
00531     }
00532 
00533     QWidget::mousePressEvent(event);
00534 }
00535 
00536 void Dialog::mouseReleaseEvent(QMouseEvent *event)
00537 {
00538     if (d->resizeStartCorner != Dialog::NoCorner) {
00539         emit dialogResized();
00540         d->resizeStartCorner = Dialog::NoCorner;
00541         unsetCursor();
00542     }
00543 
00544     QWidget::mouseReleaseEvent(event);
00545 }
00546 
00547 void Dialog::keyPressEvent(QKeyEvent *event)
00548 {
00549     if (event->key() == Qt::Key_Escape) {
00550         hide();
00551     }
00552 }
00553 
00554 bool Dialog::event(QEvent *event)
00555 {
00556     return QWidget::event(event);
00557 }
00558 
00559 void Dialog::resizeEvent(QResizeEvent *event)
00560 {
00561     Q_UNUSED(event)
00562     //kDebug();
00563     d->scheduleBorderCheck(true);
00564 
00565     if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
00566         QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00567         graphicsWidget->resize(d->view->size());
00568 
00569         QRectF sceneRect(graphicsWidget->sceneBoundingRect());
00570         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00571         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00572         d->view->setSceneRect(sceneRect);
00573         d->view->centerOn(graphicsWidget);
00574     }
00575 }
00576 
00577 void DialogPrivate::updateResizeCorners()
00578 {
00579     const int resizeAreaMargin = 20;
00580     const QRect r = q->rect();
00581     const FrameSvg::EnabledBorders borders = background->enabledBorders();
00582 
00583     // IMPLEMENTATION NOTE: we set resize corners for the corners set, but also
00584     // for the complimentary corners if we've cut out an edge of our SVG background
00585     // which implies we are up against an immovable edge (e.g. a screen edge)
00586 
00587     resizeAreas.clear();
00588     if (resizeCorners & Dialog::NorthEast ||
00589         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
00590         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
00591         resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
00592                                                resizeAreaMargin, resizeAreaMargin);
00593     }
00594 
00595     if (resizeCorners & Dialog::NorthWest ||
00596         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
00597         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
00598         resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
00599     }
00600 
00601     if (resizeCorners & Dialog::SouthEast ||
00602         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
00603         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
00604         resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
00605                                                r.bottom() - resizeAreaMargin,
00606                                                resizeAreaMargin, resizeAreaMargin);
00607     }
00608 
00609     if (resizeCorners & Dialog::SouthWest ||
00610         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
00611         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
00612         resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
00613                                                resizeAreaMargin, resizeAreaMargin);
00614     }
00615 }
00616 
00617 void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
00618 {
00619     if (d->graphicsWidgetPtr) {
00620         d->graphicsWidgetPtr.data()->removeEventFilter(this);
00621     }
00622 
00623     d->graphicsWidgetPtr = widget;
00624 
00625     if (widget) {
00626         Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
00627         if (c) {
00628             c->addOffscreenWidget(widget);
00629         }
00630 
00631         if (!layout()) {
00632             QVBoxLayout *lay = new QVBoxLayout(this);
00633             lay->setMargin(0);
00634             lay->setSpacing(0);
00635         }
00636 
00637         d->checkBorders();
00638 
00639         if (!d->view) {
00640             d->view = new QGraphicsView(this);
00641             d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00642             d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00643             d->view->setFrameShape(QFrame::NoFrame);
00644             d->view->viewport()->setAutoFillBackground(false);
00645             layout()->addWidget(d->view);
00646         }
00647 
00648         d->view->setScene(widget->scene());
00649 
00650         //try to have the proper size -before- showing the dialog
00651         d->view->centerOn(widget);
00652         if (widget->layout()) {
00653             widget->layout()->activate();
00654         }
00655         static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
00656         widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
00657 
00658         syncToGraphicsWidget();
00659 
00660         //d->adjustSizeTimer->start(150);
00661 
00662         widget->installEventFilter(this);
00663         d->view->installEventFilter(this);
00664     } else {
00665         delete d->view;
00666         d->view = 0;
00667     }
00668 }
00669 
00670 //KDE5 FIXME: should be const
00671 QGraphicsWidget *Dialog::graphicsWidget()
00672 {
00673     return d->graphicsWidgetPtr.data();
00674 }
00675 
00676 bool Dialog::eventFilter(QObject *watched, QEvent *event)
00677 {
00678     if (d->resizeStartCorner == Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
00679         (event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
00680         d->adjustViewTimer->start(150);
00681     }
00682 
00683     // when moving the cursor with a 45° angle from the outside
00684     // to the inside passing over a resize angle the cursor changes its
00685     // shape to a resize cursor. As a side effect this is the only case
00686     // when the cursor immediately enters the view without giving
00687     // the dialog the chance to restore the original cursor shape.
00688     if (event->type() == QEvent::Enter && watched == d->view) {
00689         unsetCursor();
00690     }
00691 
00692     return QWidget::eventFilter(watched, event);
00693 }
00694 
00695 void Dialog::hideEvent(QHideEvent * event)
00696 {
00697     Q_UNUSED(event);
00698     emit dialogVisible(false);
00699 }
00700 
00701 void Dialog::showEvent(QShowEvent * event)
00702 {
00703     Q_UNUSED(event);
00704 
00705     //check if the widget size is still synced with the view
00706     d->checkBorders();
00707     d->updateResizeCorners();
00708 
00709     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00710     if (graphicsWidget &&
00711         ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
00712          d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
00713          d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
00714         //here have to be done immediately, ideally should have to be done -before- shwing, but is not possible to catch show() so early
00715         syncToGraphicsWidget();
00716         d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
00717         d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
00718     }
00719 
00720     if (d->view) {
00721         d->view->setFocus();
00722     }
00723 
00724     if (graphicsWidget) {
00725         graphicsWidget->setFocus();
00726     }
00727 
00728     emit dialogVisible(true);
00729     WindowEffects::overrideShadow(winId(), true);
00730 }
00731 
00732 void Dialog::focusInEvent(QFocusEvent *event)
00733 {
00734     Q_UNUSED(event)
00735 
00736     if (d->view) {
00737         d->view->setFocus();
00738     }
00739 
00740     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00741     if (graphicsWidget) {
00742         graphicsWidget->setFocus();
00743     }
00744 }
00745 
00746 void Dialog::moveEvent(QMoveEvent *event)
00747 {
00748     Q_UNUSED(event)
00749     //kDebug();
00750     d->scheduleBorderCheck();
00751 }
00752 
00753 void Dialog::setResizeHandleCorners(ResizeCorners corners)
00754 {
00755     if ((d->resizeCorners != corners) && (aspectRatioMode() != FixedSize)) {
00756         d->resizeCorners = corners;
00757         d->updateResizeCorners();
00758     }
00759 }
00760 
00761 Dialog::ResizeCorners Dialog::resizeCorners() const
00762 {
00763     return d->resizeCorners;
00764 }
00765 
00766 bool Dialog::isUserResizing() const
00767 {
00768     return d->resizeStartCorner > NoCorner;
00769 }
00770 
00771 void Dialog::setMinimumResizeLimits(int left, int top, int right, int bottom)
00772 {
00773     d->leftResizeMin = left;
00774     d->topResizeMin = top;
00775     d->rightResizeMin = right;
00776     d->bottomResizeMin = bottom;
00777 }
00778 
00779 void Dialog::getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
00780 {
00781     if (left) {
00782         *left = d->leftResizeMin;
00783     }
00784 
00785     if (top) {
00786         *top = d->topResizeMin;
00787     }
00788 
00789     if (right) {
00790         *right = d->rightResizeMin;
00791     }
00792 
00793     if (bottom) {
00794         *bottom = d->bottomResizeMin;
00795     }
00796 }
00797 
00798 void Dialog::animatedHide(Plasma::Direction direction)
00799 {
00800     if (!isVisible()) {
00801         return;
00802     }
00803 
00804     if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00805         hide();
00806         return;
00807     }
00808 
00809     Location location = Desktop;
00810     switch (direction) {
00811     case Down:
00812         location = BottomEdge;
00813         break;
00814     case Right:
00815         location = RightEdge;
00816         break;
00817     case Left:
00818         location = LeftEdge;
00819         break;
00820     case Up:
00821         location = TopEdge;
00822         break;
00823     default:
00824         break;
00825     }
00826 
00827     Plasma::WindowEffects::slideWindow(this, location);
00828     hide();
00829 }
00830 
00831 void Dialog::animatedShow(Plasma::Direction direction)
00832 {
00833     if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00834         show();
00835         return;
00836     }
00837 
00838     //copied to not add new api
00839     Location location = Desktop;
00840     switch (direction) {
00841     case Up:
00842         location = BottomEdge;
00843         break;
00844     case Left:
00845         location = RightEdge;
00846         break;
00847     case Right:
00848         location = LeftEdge;
00849         break;
00850     case Down:
00851         location = TopEdge;
00852         break;
00853     default:
00854         break;
00855     }
00856 
00857     if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00858         Plasma::WindowEffects::slideWindow(this, location);
00859     }
00860 
00861     show();
00862 }
00863 
00864 bool Dialog::inControlArea(const QPoint &point)
00865 {
00866     foreach (const QRect &r, d->resizeAreas) {
00867         if (r.contains(point)) {
00868             return true;
00869         }
00870     }
00871     return false;
00872 }
00873 
00874 Plasma::AspectRatioMode Dialog::aspectRatioMode() const
00875 {
00876     return d->aspectRatioMode;
00877 }
00878 
00879 void Dialog::setAspectRatioMode(Plasma::AspectRatioMode mode)
00880 {
00881     if (mode == FixedSize) {
00882         setResizeHandleCorners(NoCorner);
00883     }
00884 
00885     d->aspectRatioMode = mode;
00886 }
00887 
00888 }
00889 #include "dialog.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:30:43 by doxygen 1.7.5.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.9.5 API Reference

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