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 Wed May 2 2012 17:36:05 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:36:05 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.