• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 
00025 #include <QPainter>
00026 #include <QSvgRenderer>
00027 #include <QResizeEvent>
00028 #include <QMouseEvent>
00029 #ifdef Q_WS_X11
00030 #include <QX11Info>
00031 #endif
00032 #include <QBitmap>
00033 #include <QtGui/QVBoxLayout>
00034 #include <QtGui/QGraphicsSceneEvent>
00035 #include <QtGui/QGraphicsView>
00036 #include <QtGui/QGraphicsWidget>
00037 
00038 #include <kdebug.h>
00039 #include <netwm.h>
00040 
00041 #include "plasma/applet.h"
00042 #include "plasma/extender.h"
00043 #include "plasma/private/extender_p.h"
00044 #include "plasma/framesvg.h"
00045 #include "plasma/theme.h"
00046 
00047 #ifdef Q_WS_X11
00048 #include <X11/Xlib.h>
00049 #endif
00050 
00051 const int resizeAreaMargin = 20;
00052 
00053 namespace Plasma
00054 {
00055 
00056 class DialogPrivate
00057 {
00058 public:
00059     DialogPrivate(Dialog *dialog)
00060             : q(dialog),
00061               background(0),
00062               view(0),
00063               widget(0),
00064               resizeCorners(Dialog::NoCorner),
00065               resizeStartCorner(Dialog::NoCorner)
00066     {
00067     }
00068 
00069     ~DialogPrivate()
00070     {
00071     }
00072 
00073     void themeUpdated();
00074     void adjustView();
00075 
00076     Plasma::Dialog *q;
00081     Plasma::FrameSvg *background;
00082     QGraphicsView *view;
00083     QGraphicsWidget *widget;
00084     Dialog::ResizeCorners resizeCorners;
00085     QMap<Dialog::ResizeCorner, QRect> resizeAreas;
00086     Dialog::ResizeCorner resizeStartCorner;
00087 };
00088 
00089 void DialogPrivate::themeUpdated()
00090 {
00091     const int topHeight = background->marginSize(Plasma::TopMargin);
00092     const int leftWidth = background->marginSize(Plasma::LeftMargin);
00093     const int rightWidth = background->marginSize(Plasma::RightMargin);
00094     const int bottomHeight = background->marginSize(Plasma::BottomMargin);
00095 
00096     //TODO: correct handling of the situation when having vertical panels.
00097     Extender *extender = qobject_cast<Extender*>(widget);
00098     if (extender) {
00099         switch (extender->d->applet->location()) {
00100         case BottomEdge:
00101             background->setEnabledBorders(FrameSvg::LeftBorder | FrameSvg::TopBorder
00102                                                                | FrameSvg::RightBorder);
00103             q->setContentsMargins(0, topHeight, 0, 0);
00104             break;
00105         case TopEdge:
00106             background->setEnabledBorders(FrameSvg::LeftBorder | FrameSvg::BottomBorder
00107                                                                | FrameSvg::RightBorder);
00108             q->setContentsMargins(0, 0, 0, bottomHeight);
00109             break;
00110         case LeftEdge:
00111             background->setEnabledBorders(FrameSvg::TopBorder | FrameSvg::BottomBorder
00112                                                               | FrameSvg::RightBorder);
00113             q->setContentsMargins(0, topHeight, 0, bottomHeight);
00114             break;
00115         case RightEdge:
00116             background->setEnabledBorders(FrameSvg::TopBorder | FrameSvg::BottomBorder
00117                                                               | FrameSvg::LeftBorder);
00118             q->setContentsMargins(0, topHeight, 0, bottomHeight);
00119             break;
00120         default:
00121             background->setEnabledBorders(FrameSvg::AllBorders);
00122             q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00123         }
00124     } else {
00125         q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00126     }
00127     q->update();
00128 }
00129 
00130 void DialogPrivate::adjustView()
00131 {
00132     if (view && widget) {
00133         QSize prevSize = q->size();
00134         kDebug() << "Widget size:" << widget->size()
00135                  << "| Widget size hint:" << widget->effectiveSizeHint(Qt::PreferredSize)
00136                  << "| Widget minsize hint:" << widget->minimumSize()
00137                  << "| Widget maxsize hint:" << widget->maximumSize()
00138                  << "| Widget bounding rect:" << widget->boundingRect();
00139         //set the sizehints correctly:
00140         int left, top, right, bottom;
00141         q->getContentsMargins(&left, &top, &right, &bottom);
00142 
00143         q->setMinimumSize(qMin(int(widget->minimumSize().width()) + left + right, QWIDGETSIZE_MAX),
00144                           qMin(int(widget->minimumSize().height()) + top + bottom, QWIDGETSIZE_MAX));
00145         q->setMaximumSize(qMin(int(widget->maximumSize().width()) + left + right, QWIDGETSIZE_MAX),
00146                           qMin(int(widget->maximumSize().height()) + top + bottom, QWIDGETSIZE_MAX));
00147         q->resize(qMin(int(widget->size().width()) + left + right, QWIDGETSIZE_MAX),
00148                           qMin(int(widget->size().height()) + top + bottom, QWIDGETSIZE_MAX));
00149         q->updateGeometry();
00150 
00151         //reposition and resize the view.
00152         //force a valid rect, otherwise it will take up the whole scene
00153         QRectF sceneRect(widget->sceneBoundingRect());
00154 
00155         sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
00156         sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
00157         view->setSceneRect(sceneRect);
00158 
00159         view->resize(widget->size().toSize());
00160         view->centerOn(widget);
00161 
00162         if (q->size() != prevSize) {
00163             //the size of the dialog has changed, emit the signal:
00164             emit q->dialogResized();
00165         }
00166     }
00167 }
00168 
00169 Dialog::Dialog(QWidget *parent, Qt::WindowFlags f)
00170     : QWidget(parent, f),
00171       d(new DialogPrivate(this))
00172 {
00173     setWindowFlags(Qt::FramelessWindowHint);
00174     d->background = new FrameSvg(this);
00175     d->background->setImagePath("dialogs/background");
00176     d->background->setEnabledBorders(FrameSvg::AllBorders);
00177     d->background->resizeFrame(size());
00178 
00179     QPalette pal = palette();
00180     pal.setColor(backgroundRole(), Qt::transparent);
00181     setPalette(pal);
00182 
00183     connect(d->background, SIGNAL(repaintNeeded()), this, SLOT(update()));
00184 
00185     connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeUpdated()));
00186     d->themeUpdated();
00187 
00188     setMouseTracking(true);
00189 }
00190 
00191 Dialog::~Dialog()
00192 {
00193     delete d;
00194 }
00195 
00196 void Dialog::paintEvent(QPaintEvent *e)
00197 {
00198     QPainter p(this);
00199     p.setRenderHint(QPainter::Antialiasing);
00200     p.setClipRect(e->rect());
00201     p.setCompositionMode(QPainter::CompositionMode_Source);
00202     d->background->paintFrame(&p);
00203 
00204     //we set the resize handlers
00205     d->resizeAreas.clear();
00206     if (d->resizeCorners & Dialog::NorthEast) {
00207         d->resizeAreas[Dialog::NorthEast] = QRect(rect().right() - resizeAreaMargin, 0,
00208                                              resizeAreaMargin, resizeAreaMargin);
00209     }
00210 
00211     if (d->resizeCorners & Dialog::NorthWest) {
00212         d->resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
00213     }
00214 
00215     if (d->resizeCorners & Dialog::SouthEast) {
00216         d->resizeAreas[Dialog::SouthEast] = QRect(rect().right() - resizeAreaMargin,
00217                                             rect().bottom() - resizeAreaMargin,
00218                                             resizeAreaMargin, resizeAreaMargin);
00219     }
00220 
00221     if (d->resizeCorners & Dialog::SouthWest) {
00222         d->resizeAreas[Dialog::SouthWest] = QRect(0, rect().bottom() - resizeAreaMargin,
00223                                             resizeAreaMargin, resizeAreaMargin);
00224     }
00225 }
00226 
00227 void Dialog::mouseMoveEvent(QMouseEvent *event)
00228 {
00229     if (d->resizeAreas[Dialog::NorthEast].contains(event->pos()) && d->resizeCorners & Dialog::NorthEast) {
00230         setCursor(Qt::SizeBDiagCursor);
00231     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos()) && d->resizeCorners & Dialog::NorthWest) {
00232         setCursor(Qt::SizeFDiagCursor);
00233     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos()) && d->resizeCorners & Dialog::SouthEast) {
00234         setCursor(Qt::SizeFDiagCursor);
00235     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos()) && d->resizeCorners & Dialog::SouthWest) {
00236         setCursor(Qt::SizeBDiagCursor);
00237     } else if (!(event->buttons() & Qt::LeftButton)) {
00238         unsetCursor();
00239     }
00240 
00241     // here we take care of resize..
00242     if (d->resizeStartCorner != Dialog::NoCorner) {
00243         int newWidth;
00244         int newHeight;
00245         QPoint position;
00246 
00247         switch(d->resizeStartCorner) {
00248             case Dialog::NorthEast:
00249                 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00250                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00251                 position = QPoint(x(), y() + height() - newHeight);
00252                 break;
00253             case Dialog::NorthWest:
00254                 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00255                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
00256                 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
00257                 break;
00258             case Dialog::SouthWest:
00259                 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
00260                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00261                 position = QPoint(x() + width() - newWidth, y());
00262                 break;
00263             case Dialog::SouthEast:
00264                 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
00265                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
00266                 position = QPoint(x(), y());
00267                 break;
00268              default:
00269                 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
00270                 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
00271                 position = QPoint(x(), y());
00272                 break;
00273         }
00274 
00275         setGeometry(QRect(position, QSize(newWidth, newHeight)));
00276     }
00277 
00278     QWidget::mouseMoveEvent(event);
00279 }
00280 
00281 void Dialog::mousePressEvent(QMouseEvent *event)
00282 {
00283     if (d->resizeAreas[Dialog::NorthEast].contains(event->pos()) && d->resizeCorners & Dialog::NorthEast) {
00284         d->resizeStartCorner = Dialog::NorthEast;
00285 
00286     } else if (d->resizeAreas[Dialog::NorthWest].contains(event->pos()) && d->resizeCorners & Dialog::NorthWest) {
00287         d->resizeStartCorner = Dialog::NorthWest;
00288 
00289     } else if (d->resizeAreas[Dialog::SouthEast].contains(event->pos()) && d->resizeCorners & Dialog::SouthEast) {
00290         d->resizeStartCorner = Dialog::SouthEast;
00291 
00292     } else if (d->resizeAreas[Dialog::SouthWest].contains(event->pos()) && d->resizeCorners & Dialog::SouthWest) {
00293         d->resizeStartCorner = Dialog::SouthWest;
00294 
00295     } else {
00296         d->resizeStartCorner = Dialog::NoCorner;
00297     }
00298 
00299     QWidget::mousePressEvent(event);
00300 }
00301 
00302 void Dialog::mouseReleaseEvent(QMouseEvent *event)
00303 {
00304     if (d->resizeStartCorner != Dialog::NoCorner) {
00305         d->resizeStartCorner = Dialog::NoCorner;
00306         unsetCursor();
00307         emit dialogResized();
00308     }
00309 
00310     QWidget::mouseReleaseEvent(event);
00311 }
00312 
00313 void Dialog::keyPressEvent(QKeyEvent *event)
00314 {
00315     if (event->key() == Qt::Key_Escape) {
00316         hide();
00317     }
00318 }
00319 
00320 bool Dialog::event(QEvent *event)
00321 {
00322     if (event->type() == QEvent::Paint) {
00323         QPainter p(this);
00324         p.setCompositionMode(QPainter::CompositionMode_Source);
00325         p.fillRect(rect(), Qt::transparent);
00326     }
00327 
00328     return QWidget::event(event);
00329 }
00330 
00331 void Dialog::resizeEvent(QResizeEvent *e)
00332 {
00333     d->background->resizeFrame(e->size());
00334 
00335     setMask(d->background->mask());
00336 
00337     if (d->resizeStartCorner != Dialog::NoCorner && d->view && d->widget) {
00338         d->widget->resize(d->view->size());
00339 
00340         d->view->setSceneRect(d->widget->mapToScene(d->widget->boundingRect()).boundingRect());
00341         d->view->centerOn(d->widget);
00342     }
00343 }
00344 
00345 void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
00346 {
00347     if (d->widget) {
00348         d->widget->removeEventFilter(this);
00349     }
00350 
00351     d->widget = widget;
00352 
00353     if (widget) {
00354         if (!layout()) {
00355             QVBoxLayout *lay = new QVBoxLayout(this);
00356             lay->setMargin(0);
00357             lay->setSpacing(0);
00358         }
00359 
00360         d->themeUpdated();
00361 
00362         if (!d->view) {
00363             d->view = new QGraphicsView(this);
00364             d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00365             d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00366             d->view->setFrameShape(QFrame::NoFrame);
00367             d->view->viewport()->setAutoFillBackground(false);
00368             layout()->addWidget(d->view);
00369         }
00370 
00371         d->view->setScene(widget->scene());
00372         d->adjustView();
00373 
00374         adjustSize();
00375 
00376         widget->installEventFilter(this);
00377     } else {
00378         delete d->view;
00379         d->view = 0;
00380     }
00381 }
00382 
00383 QGraphicsWidget *Dialog::graphicsWidget()
00384 {
00385     return d->widget;
00386 }
00387 
00388 bool Dialog::eventFilter(QObject *watched, QEvent *event)
00389 {
00390     if (d->resizeStartCorner == Dialog::NoCorner && watched == d->widget &&
00391         (event->type() == QEvent::GraphicsSceneResize || event->type() == QEvent::GraphicsSceneMove)) {
00392         d->adjustView();
00393     }
00394 
00395     return QWidget::eventFilter(watched, event);
00396 }
00397 
00398 void Dialog::hideEvent(QHideEvent * event)
00399 {
00400     Q_UNUSED(event);
00401     emit dialogVisible(false);
00402 }
00403 
00404 void Dialog::showEvent(QShowEvent * event)
00405 {
00406     Q_UNUSED(event);
00407 
00408     //check if the widget size is still synced with the view
00409     if (d->widget && d->view && d->widget->size().toSize() != d->view->size()) {
00410         d->widget->resize(d->view->size());
00411 
00412         d->view->setSceneRect(d->widget->mapToScene(d->widget->boundingRect()).boundingRect());
00413         d->view->centerOn(d->widget);
00414     }
00415     
00416     emit dialogVisible(true);
00417 }
00418 
00419 void Dialog::setResizeHandleCorners(ResizeCorners corners)
00420 {
00421     d->resizeCorners = corners;
00422     update();
00423 }
00424 
00425 Dialog::ResizeCorners Dialog::resizeCorners() const
00426 {
00427     return d->resizeCorners;
00428 }
00429 
00430 bool Dialog::inControlArea(const QPoint &point)
00431 {
00432     foreach (const QRect &r, d->resizeAreas) {
00433         if (r.contains(point)) {
00434             return true;
00435         }
00436     }
00437     return false;
00438 }
00439 
00440 }
00441 #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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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