• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • 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(triggeredByResize ? 0 : 200);
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         if ((newWidth >= minimumSize().width()) && (newHeight >= minimumSize().height())) {
00494             setGeometry(QRect(position, QSize(newWidth, newHeight)));
00495         }
00496     }
00497 
00498     QWidget::mouseMoveEvent(event);
00499 }
00500 
00501 void Dialog::mousePressEvent(QMouseEvent *event)
00502 {
00503     if (d->resizeAreas[Dialog::NorthEast].contains(event->pos())) {
00504         d->resizeStartCorner = Dialog::NorthEast;
00505     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos())) {
00506         d->resizeStartCorner = Dialog::NorthWest;
00507     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos())) {
00508         d->resizeStartCorner = Dialog::SouthEast;
00509     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos())) {
00510         d->resizeStartCorner = Dialog::SouthWest;
00511     } else {
00512         d->resizeStartCorner = Dialog::NoCorner;
00513     }
00514 
00515     QWidget::mousePressEvent(event);
00516 }
00517 
00518 void Dialog::mouseReleaseEvent(QMouseEvent *event)
00519 {
00520     if (d->resizeStartCorner != Dialog::NoCorner) {
00521         d->resizeStartCorner = Dialog::NoCorner;
00522         unsetCursor();
00523         emit dialogResized();
00524     }
00525 
00526     QWidget::mouseReleaseEvent(event);
00527 }
00528 
00529 void Dialog::keyPressEvent(QKeyEvent *event)
00530 {
00531     if (event->key() == Qt::Key_Escape) {
00532         hide();
00533     }
00534 }
00535 
00536 bool Dialog::event(QEvent *event)
00537 {
00538     if (event->type() == QEvent::Paint) {
00539         QPainter p(this);
00540         p.setCompositionMode(QPainter::CompositionMode_Source);
00541         p.fillRect(rect(), Qt::transparent);
00542     }
00543 
00544     return QWidget::event(event);
00545 }
00546 
00547 void Dialog::resizeEvent(QResizeEvent *event)
00548 {
00549     Q_UNUSED(event)
00550     //kDebug();
00551     d->scheduleBorderCheck(true);
00552 
00553     if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
00554         QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00555         graphicsWidget->resize(d->view->size());
00556 
00557         QRectF sceneRect(graphicsWidget->sceneBoundingRect());
00558         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00559         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00560         d->view->setSceneRect(sceneRect);
00561         d->view->centerOn(graphicsWidget);
00562     }
00563 }
00564 
00565 void DialogPrivate::updateResizeCorners()
00566 {
00567     const int resizeAreaMargin = 20;
00568     const QRect r = q->rect();
00569     const FrameSvg::EnabledBorders borders = background->enabledBorders();
00570 
00571     // IMPLEMENTATION NOTE: we set resize corners for the corners set, but also
00572     // for the complimentary corners if we've cut out an edge of our SVG background
00573     // which implies we are up against an immovable edge (e.g. a screen edge)
00574 
00575     resizeAreas.clear();
00576     if (resizeCorners & Dialog::NorthEast ||
00577         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
00578         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
00579         resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
00580                                                resizeAreaMargin, resizeAreaMargin);
00581     }
00582 
00583     if (resizeCorners & Dialog::NorthWest ||
00584         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
00585         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
00586         resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
00587     }
00588 
00589     if (resizeCorners & Dialog::SouthEast ||
00590         (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
00591         (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
00592         resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
00593                                                r.bottom() - resizeAreaMargin,
00594                                                resizeAreaMargin, resizeAreaMargin);
00595     }
00596 
00597     if (resizeCorners & Dialog::SouthWest ||
00598         (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
00599         (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
00600         resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
00601                                                resizeAreaMargin, resizeAreaMargin);
00602     }
00603 }
00604 
00605 void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
00606 {
00607     if (d->graphicsWidgetPtr) {
00608         d->graphicsWidgetPtr.data()->removeEventFilter(this);
00609     }
00610 
00611     d->graphicsWidgetPtr = widget;
00612 
00613     if (widget) {
00614         Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
00615         if (c) {
00616             c->addOffscreenWidget(widget);
00617         }
00618 
00619         if (!layout()) {
00620             QVBoxLayout *lay = new QVBoxLayout(this);
00621             lay->setMargin(0);
00622             lay->setSpacing(0);
00623         }
00624 
00625         d->checkBorders();
00626 
00627         if (!d->view) {
00628             d->view = new QGraphicsView(this);
00629             d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00630             d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00631             d->view->setFrameShape(QFrame::NoFrame);
00632             d->view->viewport()->setAutoFillBackground(false);
00633             layout()->addWidget(d->view);
00634         }
00635 
00636         d->view->setScene(widget->scene());
00637 
00638         //try to have the proper size -before- showing the dialog
00639         d->view->centerOn(widget);
00640         if (widget->layout()) {
00641             widget->layout()->activate();
00642         }
00643         static_cast<QGraphicsLayoutItem *>(widget)->updateGeometry();
00644         widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
00645 
00646         syncToGraphicsWidget();
00647 
00648         //d->adjustSizeTimer->start(150);
00649 
00650         widget->installEventFilter(this);
00651         d->view->installEventFilter(this);
00652     } else {
00653         delete d->view;
00654         d->view = 0;
00655     }
00656 }
00657 
00658 //KDE5 FIXME: should be const
00659 QGraphicsWidget *Dialog::graphicsWidget()
00660 {
00661     return d->graphicsWidgetPtr.data();
00662 }
00663 
00664 bool Dialog::eventFilter(QObject *watched, QEvent *event)
00665 {
00666     if (d->resizeStartCorner == Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
00667         (event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
00668         d->adjustViewTimer->start(150);
00669     }
00670 
00671     // when moving the cursor with a 45° angle from the outside
00672     // to the inside passing over a resize angle the cursor changes its
00673     // shape to a resize cursor. As a side effect this is the only case
00674     // when the cursor immediately enters the view without giving
00675     // the dialog the chance to restore the original cursor shape.
00676     if (event->type() == QEvent::Enter && watched == d->view) {
00677         unsetCursor();
00678     }
00679 
00680     return QWidget::eventFilter(watched, event);
00681 }
00682 
00683 void Dialog::hideEvent(QHideEvent * event)
00684 {
00685     Q_UNUSED(event);
00686     emit dialogVisible(false);
00687 }
00688 
00689 void Dialog::showEvent(QShowEvent * event)
00690 {
00691     Q_UNUSED(event);
00692 
00693     //check if the widget size is still synced with the view
00694     d->checkBorders();
00695     d->updateResizeCorners();
00696 
00697     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00698     if (graphicsWidget &&
00699         ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
00700          d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
00701          d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
00702         //here have to be done immediately, ideally should have to be done -before- shwing, but is not possible to catch show() so early
00703         syncToGraphicsWidget();
00704         d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
00705         d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
00706     }
00707 
00708     if (d->view) {
00709         d->view->setFocus();
00710     }
00711 
00712     if (graphicsWidget) {
00713         graphicsWidget->setFocus();
00714     }
00715 
00716     emit dialogVisible(true);
00717     WindowEffects::overrideShadow(winId(), true);
00718 }
00719 
00720 void Dialog::focusInEvent(QFocusEvent *event)
00721 {
00722     Q_UNUSED(event)
00723 
00724     if (d->view) {
00725         d->view->setFocus();
00726     }
00727 
00728     QGraphicsWidget *graphicsWidget = d->graphicsWidgetPtr.data();
00729     if (graphicsWidget) {
00730         graphicsWidget->setFocus();
00731     }
00732 }
00733 
00734 void Dialog::moveEvent(QMoveEvent *event)
00735 {
00736     Q_UNUSED(event)
00737     //kDebug();
00738     d->scheduleBorderCheck();
00739 }
00740 
00741 void Dialog::setResizeHandleCorners(ResizeCorners corners)
00742 {
00743     if ((d->resizeCorners != corners) && (aspectRatioMode() != FixedSize)) {
00744         d->resizeCorners = corners;
00745         d->updateResizeCorners();
00746     }
00747 }
00748 
00749 Dialog::ResizeCorners Dialog::resizeCorners() const
00750 {
00751     return d->resizeCorners;
00752 }
00753 
00754 void Dialog::animatedHide(Plasma::Direction direction)
00755 {
00756     if (!KWindowSystem::compositingActive()) {
00757         hide();
00758         return;
00759     }
00760 
00761     Location location = Desktop;
00762     switch (direction) {
00763     case Down:
00764         location = BottomEdge;
00765         break;
00766     case Right:
00767         location = RightEdge;
00768         break;
00769     case Left:
00770         location = LeftEdge;
00771         break;
00772     case Up:
00773         location = TopEdge;
00774         break;
00775     default:
00776         break;
00777     }
00778 
00779     Plasma::WindowEffects::slideWindow(this, location);
00780     hide();
00781 }
00782 
00783 void Dialog::animatedShow(Plasma::Direction direction)
00784 {
00785     if (!KWindowSystem::compositingActive()) {
00786         show();
00787         return;
00788     }
00789 
00790     //copied to not add new api
00791     Location location = Desktop;
00792     switch (direction) {
00793     case Up:
00794         location = BottomEdge;
00795         break;
00796     case Left:
00797         location = RightEdge;
00798         break;
00799     case Right:
00800         location = LeftEdge;
00801         break;
00802     case Down:
00803         location = TopEdge;
00804         break;
00805     default:
00806         break;
00807     }
00808 
00809     if (KWindowSystem::compositingActive()) {
00810         Plasma::WindowEffects::slideWindow(this, location);
00811     }
00812 
00813     show();
00814 }
00815 
00816 bool Dialog::inControlArea(const QPoint &point)
00817 {
00818     foreach (const QRect &r, d->resizeAreas) {
00819         if (r.contains(point)) {
00820             return true;
00821         }
00822     }
00823     return false;
00824 }
00825 
00826 Plasma::AspectRatioMode Dialog::aspectRatioMode() const
00827 {
00828     return d->aspectRatioMode;
00829 }
00830 
00831 void Dialog::setAspectRatioMode(Plasma::AspectRatioMode mode)
00832 {
00833     if (mode == FixedSize) {
00834         setResizeHandleCorners(NoCorner);
00835     }
00836 
00837     d->aspectRatioMode = mode;
00838 }
00839 
00840 }
00841 #include "dialog.moc"

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal