• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 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     if (applet) {
00175         background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00176 
00177         switch (applet->location()) {
00178         case BottomEdge:
00179             if (applet->containment() &&
00180                 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
00181                 dialogGeom.width() <= applet->containment()->size().width()) {
00182                 borders &= ~FrameSvg::BottomBorder;
00183                 leftWidth = 0;
00184                 rightWidth = 0;
00185                 bottomHeight = 0;
00186             }
00187         break;
00188 
00189         case TopEdge:
00190             if (applet->containment() &&
00191                 dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
00192                 dialogGeom.width() <= applet->containment()->size().width()) {
00193                 borders &= ~FrameSvg::TopBorder;
00194                 topHeight = 0;
00195                 leftWidth = 0;
00196                 rightWidth = 0;
00197             }
00198         break;
00199 
00200         case LeftEdge:
00201             if (applet->containment() &&
00202                 dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
00203                 dialogGeom.height() <= applet->containment()->size().height()) {
00204                 borders &= ~FrameSvg::LeftBorder;
00205                 leftWidth = 0;
00206                 rightWidth = 0;
00207             }
00208         break;
00209 
00210         case RightEdge:
00211             if (applet->containment() &&
00212                 dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
00213                 dialogGeom.height() <= applet->containment()->size().height()) {
00214                 borders &= ~FrameSvg::RightBorder;
00215                 leftWidth = 0;
00216                 rightWidth = 0;
00217             }
00218         break;
00219 
00220         default:
00221         break;
00222         }
00223     }
00224 
00225     //decide if to disable the other borders
00226     if (q->isVisible()) {
00227         if (dialogGeom.left() <= avail.left()) {
00228             borders &= ~FrameSvg::LeftBorder;
00229         }
00230         if (dialogGeom.top() <= avail.top()) {
00231             borders &= ~FrameSvg::TopBorder;
00232         }
00233         //FIXME: that 2 pixels offset has probably something to do with kwin
00234         if (dialogGeom.right() + 2 > avail.right()) {
00235             borders &= ~FrameSvg::RightBorder;
00236         }
00237         if (dialogGeom.bottom() + 2 > avail.bottom()) {
00238             borders &= ~FrameSvg::BottomBorder;
00239         }
00240     }
00241 
00242     background->setEnabledBorders(borders);
00243 
00244     if (extender)  {
00245         FrameSvg::EnabledBorders disabledBorders = FrameSvg::NoBorder;
00246         if (!(borders & FrameSvg::LeftBorder)) {
00247             disabledBorders |= FrameSvg::LeftBorder;
00248         }
00249         if (!(borders & FrameSvg::RightBorder)) {
00250             disabledBorders |= FrameSvg::RightBorder;
00251         }
00252         extender->d->setDisabledBordersHint(disabledBorders);
00253 
00254         //if there is a scrollbar, reserve a margin to not draw it over the shadow
00255         qreal left, top, right, bottom;
00256         background->getMargins(left, top, right, bottom);
00257         if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
00258             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00259                 leftWidth = left;
00260             } else {
00261                 rightWidth = right;
00262             }
00263         }
00264     } else {
00265         background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00266     }
00267 
00268     //kDebug() << leftWidth << topHeight << rightWidth << bottomHeight;
00269     q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00270 
00271     if (resizeChecksWithBorderCheck) {
00272         updateResizeCorners();
00273         updateMask();
00274         q->update();
00275     } else if (currentBorders != borders) {
00276         if (updateMaskIfNeeded) {
00277             updateMask();
00278         }
00279 
00280         q->update();
00281     }
00282 
00283     resizeChecksWithBorderCheck = false;
00284 }
00285 
00286 void Dialog::syncToGraphicsWidget()
00287 {
00288     d->adjustViewTimer->stop();
00289     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00290     if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
00291         const int prevStartCorner = d->resizeStartCorner;
00292         d->resizeStartCorner = -1;
00293         QSize prevSize = size();
00294         /*
00295         kDebug() << "Widget size:" << graphicsWidget->size()
00296                  << "| Widget size hint:" << graphicsWidget->effectiveSizeHint(Qt::PreferredSize)
00297                  << "| Widget minsize hint:" << graphicsWidget->minimumSize()
00298                  << "| Widget maxsize hint:" << graphicsWidget->maximumSize()
00299                  << "| Widget bounding rect:" << graphicsWidget->sceneBoundingRect();
00300         */
00301         //set the sizehints correctly:
00302         int left, top, right, bottom;
00303         getContentsMargins(&left, &top, &right, &bottom);
00304 
00305         QDesktopWidget *desktop = QApplication::desktop();
00306         QSize maxSize = desktop->availableGeometry(desktop->screenNumber(this)).size();
00307 
00308         graphicsWidget->setMaximumSize(maxSize - QSize(left + right, top + bottom).boundedTo(graphicsWidget->effectiveSizeHint(Qt::MaximumSize).toSize()));
00309 
00310         setMinimumSize(0, 0);
00311         setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00312 
00313         QSize newSize(qMin(int(graphicsWidget->size().width()) + left + right, maxSize.width()),
00314                qMin(int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
00315 
00316         const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
00317         QSize newMinimumSize(qMin(int(minimum.width()) + left + right, maxSize.width()),
00318                        qMin(int(minimum.height()) + top + bottom, maxSize.height()));
00319 
00320 
00321         QSize newMaximumSize(qMin(int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
00322                        qMin(int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
00323 
00324 
00325         Plasma::Applet *applet = d->appletPtr.data();
00326         if (applet) {
00327             QRect currentGeometry(geometry());
00328             currentGeometry.setSize(newSize);
00329             if (applet->location() == Plasma::TopEdge ||
00330                 applet->location() == Plasma::LeftEdge) {
00331                 currentGeometry.setSize(newSize);
00332             } else if (applet->location() == Plasma::RightEdge) {
00333                 currentGeometry.moveTopRight(geometry().topRight());
00334             //BottomEdge and floating
00335             } else {
00336                 currentGeometry.moveBottomLeft(geometry().bottomLeft());
00337             }
00338             setGeometry(currentGeometry);
00339         } else {
00340             resize(newSize);
00341         }
00342 
00343         setMinimumSize(newMinimumSize);
00344         setMaximumSize(newMaximumSize);
00345 
00346 
00347         updateGeometry();
00348 
00349         //reposition and resize the view.
00350         //force a valid rect, otherwise it will take up the whole scene
00351         QRectF sceneRect(graphicsWidget->sceneBoundingRect());
00352 
00353         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00354         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00355         d->view->setSceneRect(sceneRect);
00356 
00357         //d->view->resize(graphicsWidget->size().toSize());
00358         d->view->centerOn(graphicsWidget);
00359 
00360         if (size() != prevSize) {
00361             //the size of the dialog has changed, emit the signal:
00362             emit dialogResized();
00363         }
00364 
00365         d->resizeStartCorner = prevStartCorner;
00366     }
00367 }
00368 
00369 int DialogPrivate::calculateWidthForHeightAndRatio(int height, qreal ratio)
00370 {
00371     switch (aspectRatioMode) {
00372         case KeepAspectRatio:
00373             return qRound(height * ratio);
00374             break;
00375         case Square:
00376             return height;
00377             break;
00378         case ConstrainedSquare:
00379             return height;
00380             break;
00381         default:
00382             return -1;
00383     }
00384 }
00385 
00386 Dialog::Dialog(QWidget *parent, Qt::WindowFlags f)
00387     : QWidget(parent, f | Qt::FramelessWindowHint),
00388       d(new DialogPrivate(this))
00389 {
00390     setMouseTracking(true);
00391     setAttribute(Qt::WA_TranslucentBackground);
00392     d->background = new FrameSvg(this);
00393     d->background->setImagePath("dialogs/background");
00394     d->background->setEnabledBorders(FrameSvg::AllBorders);
00395     d->background->resizeFrame(size());
00396     connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(themeChanged()));
00397 
00398     QPalette pal = palette();
00399     pal.setColor(backgroundRole(), Qt::transparent);
00400     setPalette(pal);
00401     WindowEffects::overrideShadow(winId(), true);
00402 
00403     d->adjustViewTimer = new QTimer(this);
00404     d->adjustViewTimer->setSingleShot(true);
00405     connect(d->adjustViewTimer, SIGNAL(timeout()), this, SLOT(syncToGraphicsWidget()));
00406 
00407     d->adjustSizeTimer = new QTimer(this);
00408     d->adjustSizeTimer->setSingleShot(true);
00409     connect(d->adjustSizeTimer, SIGNAL(timeout()), this, SLOT(delayedAdjustSize()));
00410 
00411     d->themeChanged();
00412 }
00413 
00414 Dialog::~Dialog()
00415 {
00416     delete d;
00417 }
00418 
00419 void Dialog::paintEvent(QPaintEvent *e)
00420 {
00421     QPainter p(this);
00422     p.setCompositionMode(QPainter::CompositionMode_Source);
00423     d->background->paintFrame(&p, e->rect(), e->rect());
00424 }
00425 
00426 void Dialog::mouseMoveEvent(QMouseEvent *event)
00427 {
00428     if (event->modifiers() == Qt::AltModifier) {
00429         unsetCursor();
00430     } else if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
00431         setCursor(Qt::SizeBDiagCursor);
00432     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
00433         setCursor(Qt::SizeFDiagCursor);
00434     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
00435         setCursor(Qt::SizeFDiagCursor);
00436     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
00437         setCursor(Qt::SizeBDiagCursor);
00438     } else if (!(event->buttons() & Qt::LeftButton)) {
00439         unsetCursor();
00440     }
00441 
00442     // here we take care of resize..
00443     if (d->resizeStartCorner != Dialog::NoCorner) {
00444         int newWidth;
00445         int newHeight;
00446         QPoint position;
00447 
00448         qreal aspectRatio = (qreal)width() / (qreal)height();
00449 
00450         switch(d->resizeStartCorner) {
00451             case Dialog::NorthEast:
00452                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00453                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00454                 if (newWidth == -1) {
00455                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00456                 }
00457                 position = QPoint(x(), y() + height() - newHeight);
00458                 break;
00459             case Dialog::NorthWest:
00460                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00461                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00462                 if (newWidth == -1) {
00463                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00464                 }
00465                 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
00466                 break;
00467             case Dialog::SouthWest:
00468                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00469                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00470                 if (newWidth == -1) {
00471                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00472                 }
00473                 position = QPoint(x() + width() - newWidth, y());
00474                 break;
00475             case Dialog::SouthEast:
00476                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00477                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00478                 if (newWidth == -1) {
00479                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00480                 }
00481                 position = QPoint(x(), y());
00482                 break;
00483              default:
00484                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
00485                 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
00486                 if (newWidth == -1) {
00487                     newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
00488                 }
00489                 position = QPoint(x(), y());
00490                 break;
00491         }
00492 
00493         QRect newGeom(position, QSize(newWidth, newHeight));
00494 
00495         // now sanity check the resize results again min constraints, if any
00496         if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
00497             newGeom.setLeft(d->leftResizeMin);
00498         }
00499 
00500         if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
00501             newGeom.setTop(d->topResizeMin);
00502         }
00503 
00504         if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
00505             newGeom.setRight(d->rightResizeMin);
00506         }
00507 
00508         if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
00509             newGeom.setBottom(d->bottomResizeMin);
00510         }
00511 
00512         if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
00513             setGeometry(newGeom);
00514         }
00515     }
00516 
00517     QWidget::mouseMoveEvent(event);
00518 }
00519 
00520 void Dialog::mousePressEvent(QMouseEvent *event)
00521 {
00522     if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
00523         d->resizeStartCorner = Dialog::NorthEast;
00524     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
00525         d->resizeStartCorner = Dialog::NorthWest;
00526     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
00527         d->resizeStartCorner = Dialog::SouthEast;
00528     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
00529         d->resizeStartCorner = Dialog::SouthWest;
00530     } else {
00531         d->resizeStartCorner = Dialog::NoCorner;
00532     }
00533 
00534     QWidget::mousePressEvent(event);
00535 }
00536 
00537 void Dialog::mouseReleaseEvent(QMouseEvent *event)
00538 {
00539     if (d->resizeStartCorner != Dialog::NoCorner) {
00540         emit dialogResized();
00541         d->resizeStartCorner = Dialog::NoCorner;
00542         unsetCursor();
00543     }
00544 
00545     QWidget::mouseReleaseEvent(event);
00546 }
00547 
00548 void Dialog::keyPressEvent(QKeyEvent *event)
00549 {
00550     if (event->key() == Qt::Key_Escape) {
00551         hide();
00552     }
00553 }
00554 
00555 bool Dialog::event(QEvent *event)
00556 {
00557     return QWidget::event(event);
00558 }
00559 
00560 void Dialog::resizeEvent(QResizeEvent *event)
00561 {
00562     Q_UNUSED(event)
00563     //kDebug();
00564     d->scheduleBorderCheck(true);
00565 
00566     if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
00567         QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00568         graphicsWidget->resize(d->view->size());
00569 
00570         QRectF sceneRect(graphicsWidget->sceneBoundingRect());
00571         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00572         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00573         d->view->setSceneRect(sceneRect);
00574         d->view->centerOn(graphicsWidget);
00575     }
00576 }
00577 
00578 void DialogPrivate::updateResizeCorners()
00579 {
00580     const int resizeAreaMargin = 20;
00581     const QRect r = q->rect();
00582     const FrameSvg::EnabledBorders borders = background->enabledBorders();
00583 
00584     // IMPLEMENTATION NOTE: we set resize corners for the corners set, but also
00585     // for the complimentary corners if we've cut out an edge of our SVG background
00586     // which implies we are up against an immovable edge (e.g. a screen edge)
00587 
00588     resizeAreas.clear();
00589     if (resizeCorners & Dialog::NorthEast ||
00590         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
00591         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
00592         resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
00593                                                resizeAreaMargin, resizeAreaMargin);
00594     }
00595 
00596     if (resizeCorners & Dialog::NorthWest ||
00597         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
00598         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
00599         resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
00600     }
00601 
00602     if (resizeCorners & Dialog::SouthEast ||
00603         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
00604         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
00605         resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
00606                                                r.bottom() - resizeAreaMargin,
00607                                                resizeAreaMargin, resizeAreaMargin);
00608     }
00609 
00610     if (resizeCorners & Dialog::SouthWest ||
00611         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
00612         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
00613         resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
00614                                                resizeAreaMargin, resizeAreaMargin);
00615     }
00616 }
00617 
00618 void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
00619 {
00620     if (d->graphicsWidgetPtr) {
00621         d->graphicsWidgetPtr.data()->removeEventFilter(this);
00622     }
00623 
00624     d->graphicsWidgetPtr = widget;
00625 
00626     if (widget) {
00627         Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
00628         if (c) {
00629             c->addOffscreenWidget(widget);
00630         }
00631 
00632         if (!layout()) {
00633             QVBoxLayout *lay = new QVBoxLayout(this);
00634             lay->setMargin(0);
00635             lay->setSpacing(0);
00636         }
00637 
00638         d->checkBorders();
00639 
00640         if (!d->view) {
00641             d->view = new QGraphicsView(this);
00642             d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00643             d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00644             d->view->setFrameShape(QFrame::NoFrame);
00645             d->view->viewport()->setAutoFillBackground(false);
00646             layout()->addWidget(d->view);
00647         }
00648 
00649         d->view->setScene(widget->scene());
00650 
00651         //try to have the proper size -before- showing the dialog
00652         d->view->centerOn(widget);
00653         if (widget->layout()) {
00654             widget->layout()->activate();
00655         }
00656         static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
00657         widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
00658 
00659         syncToGraphicsWidget();
00660 
00661         //d->adjustSizeTimer->start(150);
00662 
00663         widget->installEventFilter(this);
00664         d->view->installEventFilter(this);
00665     } else {
00666         delete d->view;
00667         d->view = 0;
00668     }
00669 }
00670 
00671 //KDE5 FIXME: should be const
00672 QGraphicsWidget *Dialog::graphicsWidget()
00673 {
00674     return d->graphicsWidgetPtr.data();
00675 }
00676 
00677 bool Dialog::eventFilter(QObject *watched, QEvent *event)
00678 {
00679     if (d->resizeStartCorner == Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
00680         (event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
00681         d->adjustViewTimer->start(150);
00682     }
00683 
00684     // when moving the cursor with a 45° angle from the outside
00685     // to the inside passing over a resize angle the cursor changes its
00686     // shape to a resize cursor. As a side effect this is the only case
00687     // when the cursor immediately enters the view without giving
00688     // the dialog the chance to restore the original cursor shape.
00689     if (event->type() == QEvent::Enter && watched == d->view) {
00690         unsetCursor();
00691     }
00692 
00693     return QWidget::eventFilter(watched, event);
00694 }
00695 
00696 void Dialog::hideEvent(QHideEvent * event)
00697 {
00698     Q_UNUSED(event);
00699     emit dialogVisible(false);
00700 }
00701 
00702 void Dialog::showEvent(QShowEvent * event)
00703 {
00704     Q_UNUSED(event);
00705 
00706     //check if the widget size is still synced with the view
00707     d->checkBorders();
00708     d->updateResizeCorners();
00709 
00710     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00711     if (graphicsWidget &&
00712         ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
00713          d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
00714          d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
00715         //here have to be done immediately, ideally should have to be done -before- shwing, but is not possible to catch show() so early
00716         syncToGraphicsWidget();
00717         d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
00718         d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
00719     }
00720 
00721     if (d->view) {
00722         d->view->setFocus();
00723     }
00724 
00725     if (graphicsWidget) {
00726         graphicsWidget->setFocus();
00727     }
00728 
00729     emit dialogVisible(true);
00730     WindowEffects::overrideShadow(winId(), true);
00731 }
00732 
00733 void Dialog::focusInEvent(QFocusEvent *event)
00734 {
00735     Q_UNUSED(event)
00736 
00737     if (d->view) {
00738         d->view->setFocus();
00739     }
00740 
00741     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00742     if (graphicsWidget) {
00743         graphicsWidget->setFocus();
00744     }
00745 }
00746 
00747 void Dialog::moveEvent(QMoveEvent *event)
00748 {
00749     Q_UNUSED(event)
00750     //kDebug();
00751     d->scheduleBorderCheck();
00752 }
00753 
00754 void Dialog::setResizeHandleCorners(ResizeCorners corners)
00755 {
00756     if ((d->resizeCorners != corners) && (aspectRatioMode() != FixedSize)) {
00757         d->resizeCorners = corners;
00758         d->updateResizeCorners();
00759     }
00760 }
00761 
00762 Dialog::ResizeCorners Dialog::resizeCorners() const
00763 {
00764     return d->resizeCorners;
00765 }
00766 
00767 bool Dialog::isUserResizing() const
00768 {
00769     return d->resizeStartCorner > NoCorner;
00770 }
00771 
00772 void Dialog::setMinimumResizeLimits(int left, int top, int right, int bottom)
00773 {
00774     d->leftResizeMin = left;
00775     d->topResizeMin = top;
00776     d->rightResizeMin = right;
00777     d->bottomResizeMin = bottom;
00778 }
00779 
00780 void Dialog::getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
00781 {
00782     if (left) {
00783         *left = d->leftResizeMin;
00784     }
00785 
00786     if (top) {
00787         *top = d->topResizeMin;
00788     }
00789 
00790     if (right) {
00791         *right = d->rightResizeMin;
00792     }
00793 
00794     if (bottom) {
00795         *bottom = d->bottomResizeMin;
00796     }
00797 }
00798 
00799 void Dialog::animatedHide(Plasma::Direction direction)
00800 {
00801     if (!isVisible()) {
00802         return;
00803     }
00804 
00805     if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00806         hide();
00807         return;
00808     }
00809 
00810     Location location = Desktop;
00811     switch (direction) {
00812     case Down:
00813         location = BottomEdge;
00814         break;
00815     case Right:
00816         location = RightEdge;
00817         break;
00818     case Left:
00819         location = LeftEdge;
00820         break;
00821     case Up:
00822         location = TopEdge;
00823         break;
00824     default:
00825         break;
00826     }
00827 
00828     Plasma::WindowEffects::slideWindow(this, location);
00829     hide();
00830 }
00831 
00832 void Dialog::animatedShow(Plasma::Direction direction)
00833 {
00834     if (!Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00835         show();
00836         return;
00837     }
00838 
00839     //copied to not add new api
00840     Location location = Desktop;
00841     switch (direction) {
00842     case Up:
00843         location = BottomEdge;
00844         break;
00845     case Left:
00846         location = RightEdge;
00847         break;
00848     case Right:
00849         location = LeftEdge;
00850         break;
00851     case Down:
00852         location = TopEdge;
00853         break;
00854     default:
00855         break;
00856     }
00857 
00858     if (Plasma::Theme::defaultTheme()->windowTranslucencyEnabled()) {
00859         Plasma::WindowEffects::slideWindow(this, location);
00860     }
00861 
00862     show();
00863 }
00864 
00865 bool Dialog::inControlArea(const QPoint &point)
00866 {
00867     foreach (const QRect &r, d->resizeAreas) {
00868         if (r.contains(point)) {
00869             return true;
00870         }
00871     }
00872     return false;
00873 }
00874 
00875 Plasma::AspectRatioMode Dialog::aspectRatioMode() const
00876 {
00877     return d->aspectRatioMode;
00878 }
00879 
00880 void Dialog::setAspectRatioMode(Plasma::AspectRatioMode mode)
00881 {
00882     if (mode == FixedSize) {
00883         setResizeHandleCorners(NoCorner);
00884     }
00885 
00886     d->aspectRatioMode = mode;
00887 }
00888 
00889 }
00890 #include "dialog.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:51:36 by doxygen 1.8.0 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.3 API Reference

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