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