24 #include "private/dialog_p.h"
27 #include <QSvgRenderer>
28 #include <QResizeEvent>
29 #include <QMouseEvent>
35 #include <QtGui/QVBoxLayout>
36 #include <QtGui/QGraphicsSceneEvent>
37 #include <QtGui/QGraphicsView>
38 #include <QtGui/QGraphicsWidget>
39 #include <QApplication>
40 #include <QDesktopWidget>
41 #include <QVarLengthArray>
42 #include <QGraphicsLayout>
45 #include <kwindowsystem.h>
53 #include "plasma/private/extender_p.h"
66 void DialogPrivate::scheduleBorderCheck(
bool triggeredByResize)
69 if (triggeredByResize) {
70 resizeChecksWithBorderCheck =
true;
86 moveTimer =
new QTimer(q);
87 moveTimer->setSingleShot(
true);
88 QObject::connect(moveTimer, SIGNAL(timeout()), q, SLOT(checkBorders()));
94 void DialogPrivate::themeChanged()
101 q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
106 void DialogPrivate::updateMask()
110 translucency ? background->mask() : QRegion());
114 q->setMask(background->mask());
118 void DialogPrivate::checkBorders()
123 void DialogPrivate::delayedAdjustSize()
125 q->syncToGraphicsWidget();
128 void DialogPrivate::checkBorders(
bool updateMaskIfNeeded)
130 if (resizeChecksWithBorderCheck) {
131 background->resizeFrame(q->size());
135 const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
138 Extender *extender = qobject_cast<Extender*>(graphicsWidget);
144 QDesktopWidget *desktop = QApplication::desktop();
148 }
else if (graphicsWidget) {
154 foreach (QRect rect, r.rects()) {
155 if (rect.width() > maxRect.width() && rect.height() > maxRect.height()) {
162 avail = desktop->availableGeometry(desktop->screenNumber(q));
163 screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
166 QRect dialogGeom = q->geometry();
171 qreal bottomHeight(0);
175 if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
176 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
178 switch (applet->location()) {
180 if (applet->containment() &&
181 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
182 dialogGeom.width() <= applet->containment()->size().width()) {
183 borders &= ~FrameSvg::BottomBorder;
191 if (applet->containment() &&
192 dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
193 dialogGeom.width() <= applet->containment()->size().width()) {
194 borders &= ~FrameSvg::TopBorder;
202 if (applet->containment() &&
203 dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
204 dialogGeom.height() <= applet->containment()->size().height()) {
205 borders &= ~FrameSvg::LeftBorder;
212 if (applet->containment() &&
213 dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
214 dialogGeom.height() <= applet->containment()->size().height()) {
215 borders &= ~FrameSvg::RightBorder;
227 if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
228 if (dialogGeom.left() <= avail.left()) {
229 borders &= ~FrameSvg::LeftBorder;
231 if (dialogGeom.top() <= avail.top()) {
232 borders &= ~FrameSvg::TopBorder;
235 if (dialogGeom.right() + 2 > avail.right()) {
236 borders &= ~FrameSvg::RightBorder;
238 if (dialogGeom.bottom() + 2 > avail.bottom()) {
239 borders &= ~FrameSvg::BottomBorder;
243 background->setEnabledBorders(borders);
253 extender->d->setDisabledBordersHint(disabledBorders);
256 qreal left, top, right, bottom;
257 background->getMargins(left, top, right, bottom);
258 if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
259 if (QApplication::layoutDirection() == Qt::RightToLeft) {
266 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
270 q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
272 if (resizeChecksWithBorderCheck) {
273 updateResizeCorners();
276 }
else if (currentBorders != borders) {
277 if (updateMaskIfNeeded) {
284 resizeChecksWithBorderCheck =
false;
289 d->adjustViewTimer->stop();
291 if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
292 const int prevStartCorner = d->resizeStartCorner;
293 d->resizeStartCorner = -1;
294 QSize prevSize = size();
303 int left, top, right, bottom;
304 getContentsMargins(&left, &top, &right, &bottom);
306 QDesktopWidget *desktop = QApplication::desktop();
307 QSize maxSize = desktop->availableGeometry(desktop->screenNumber(
this)).size();
309 setMinimumSize(0, 0);
310 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
312 QSize newSize(qMin(
int(graphicsWidget->size().width()) + left + right, maxSize.width()),
313 qMin(
int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
315 const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
316 QSize newMinimumSize(qMin(
int(minimum.width()) + left + right, maxSize.width()),
317 qMin(
int(minimum.height()) + top + bottom, maxSize.height()));
320 QSize newMaximumSize(qMin(
int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
321 qMin(
int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
326 QRect currentGeometry(geometry());
327 currentGeometry.setSize(newSize);
330 currentGeometry.setSize(newSize);
332 currentGeometry.moveTopRight(geometry().topRight());
335 currentGeometry.moveBottomLeft(geometry().bottomLeft());
337 setGeometry(currentGeometry);
342 setMinimumSize(newMinimumSize);
343 setMaximumSize(newMaximumSize);
350 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
352 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
353 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
354 d->view->setSceneRect(sceneRect);
357 d->view->centerOn(graphicsWidget);
359 if (size() != prevSize) {
364 d->resizeStartCorner = prevStartCorner;
368 int DialogPrivate::calculateWidthForHeightAndRatio(
int height, qreal ratio)
370 switch (aspectRatioMode) {
372 return qRound(height * ratio);
386 :
QWidget(parent, f | Qt::FramelessWindowHint),
387 d(new DialogPrivate(this))
389 setMouseTracking(
true);
390 setAttribute(Qt::WA_TranslucentBackground);
392 d->background->setImagePath(
"dialogs/background");
394 d->background->resizeFrame(size());
395 connect(d->background, SIGNAL(repaintNeeded()),
this, SLOT(themeChanged()));
397 QPalette pal = palette();
398 pal.setColor(backgroundRole(), Qt::transparent);
402 d->adjustViewTimer =
new QTimer(
this);
403 d->adjustViewTimer->setSingleShot(
true);
406 d->adjustSizeTimer =
new QTimer(
this);
407 d->adjustSizeTimer->setSingleShot(
true);
408 connect(d->adjustSizeTimer, SIGNAL(timeout()),
this, SLOT(delayedAdjustSize()));
421 p.setCompositionMode(QPainter::CompositionMode_Source);
422 d->background->paintFrame(&p, e->rect(), e->rect());
427 if (event->modifiers() == Qt::AltModifier) {
430 setCursor(Qt::SizeBDiagCursor);
432 setCursor(Qt::SizeFDiagCursor);
434 setCursor(Qt::SizeFDiagCursor);
436 setCursor(Qt::SizeBDiagCursor);
437 }
else if (!(event->buttons() & Qt::LeftButton)) {
447 qreal aspectRatio = (qreal)width() / (qreal)height();
449 switch(d->resizeStartCorner) {
451 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
452 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
453 if (newWidth == -1) {
454 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
456 position = QPoint(x(), y() + height() - newHeight);
459 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
460 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
461 if (newWidth == -1) {
462 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
464 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
467 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
468 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
469 if (newWidth == -1) {
470 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
472 position = QPoint(x() + width() - newWidth, y());
475 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
476 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
477 if (newWidth == -1) {
478 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
480 position = QPoint(x(), y());
483 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
484 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
485 if (newWidth == -1) {
486 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
488 position = QPoint(x(), y());
492 QRect newGeom(position, QSize(newWidth, newHeight));
495 if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
496 newGeom.setLeft(d->leftResizeMin);
499 if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
500 newGeom.setTop(d->topResizeMin);
503 if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
504 newGeom.setRight(d->rightResizeMin);
507 if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
508 newGeom.setBottom(d->bottomResizeMin);
511 if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
512 setGeometry(newGeom);
549 if (event->key() == Qt::Key_Escape) {
563 d->scheduleBorderCheck(
true);
565 if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
567 graphicsWidget->resize(d->view->size());
569 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
570 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
571 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
572 d->view->setSceneRect(sceneRect);
573 d->view->centerOn(graphicsWidget);
577 void DialogPrivate::updateResizeCorners()
579 const int resizeAreaMargin = 20;
580 const QRect r = q->rect();
581 const FrameSvg::EnabledBorders borders = background->enabledBorders();
592 resizeAreaMargin, resizeAreaMargin);
598 resizeAreas[
Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
605 r.bottom() - resizeAreaMargin,
606 resizeAreaMargin, resizeAreaMargin);
613 resizeAreaMargin, resizeAreaMargin);
619 if (d->graphicsWidgetPtr) {
620 d->graphicsWidgetPtr.data()->removeEventFilter(
this);
623 d->graphicsWidgetPtr = widget;
632 QVBoxLayout *lay =
new QVBoxLayout(
this);
641 d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
642 d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
643 d->view->setFrameShape(QFrame::NoFrame);
644 d->view->viewport()->setAutoFillBackground(
false);
645 layout()->addWidget(d->view);
648 d->view->setScene(widget->scene());
651 d->view->centerOn(widget);
652 if (widget->layout()) {
653 widget->layout()->activate();
655 static_cast<QGraphicsLayoutItem *
>(widget)->updateGeometry();
656 widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
662 widget->installEventFilter(
this);
663 d->view->installEventFilter(
this);
673 return d->graphicsWidgetPtr.data();
678 if (d->resizeStartCorner ==
Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
679 (
event->type() == QEvent::GraphicsSceneResize ||
event->type() == QEvent::GraphicsSceneMove)) {
680 d->adjustViewTimer->start(150);
688 if (event->type() == QEvent::Enter && watched == d->view) {
707 d->updateResizeCorners();
710 if (graphicsWidget &&
711 ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
712 d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
713 d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
716 d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
717 d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
724 if (graphicsWidget) {
725 graphicsWidget->setFocus();
741 if (graphicsWidget) {
742 graphicsWidget->setFocus();
750 d->scheduleBorderCheck();
756 d->resizeCorners = corners;
757 d->updateResizeCorners();
763 return d->resizeCorners;
768 return d->resizeStartCorner >
NoCorner;
773 d->leftResizeMin = left;
774 d->topResizeMin = top;
775 d->rightResizeMin = right;
776 d->bottomResizeMin = bottom;
782 *left = d->leftResizeMin;
786 *top = d->topResizeMin;
790 *right = d->rightResizeMin;
794 *bottom = d->bottomResizeMin;
866 foreach (
const QRect &r, d->resizeAreas) {
867 if (r.contains(point)) {
876 return d->aspectRatioMode;
885 d->aspectRatioMode = mode;
889 #include "dialog.moc"