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"
54 #include "plasma/private/dialogshadows_p.h"
67 void DialogPrivate::scheduleBorderCheck(
bool triggeredByResize)
70 if (triggeredByResize) {
71 resizeChecksWithBorderCheck =
true;
87 moveTimer =
new QTimer(q);
88 moveTimer->setSingleShot(
true);
89 QObject::connect(moveTimer, SIGNAL(timeout()), q, SLOT(checkBorders()));
95 void DialogPrivate::themeChanged()
102 q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
108 void DialogPrivate::updateMask()
112 translucency ? background->mask() : QRegion());
116 q->setMask(background->mask());
120 void DialogPrivate::checkBorders()
125 void DialogPrivate::delayedAdjustSize()
127 q->syncToGraphicsWidget();
130 void DialogPrivate::checkBorders(
bool updateMaskIfNeeded)
132 if (resizeChecksWithBorderCheck) {
133 background->resizeFrame(q->size());
137 const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
140 Extender *extender = qobject_cast<Extender*>(graphicsWidget);
146 QDesktopWidget *desktop = QApplication::desktop();
150 }
else if (graphicsWidget) {
157 avail = QRegion(desktop->availableGeometry(desktop->screenNumber(q)));
158 screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
161 QRect dialogGeom = q->geometry();
166 qreal bottomHeight(0);
170 if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
171 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
173 switch (applet->location()) {
175 if (applet->containment() &&
176 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
177 dialogGeom.width() <= applet->containment()->size().width()) {
178 borders &= ~FrameSvg::BottomBorder;
186 if (applet->containment() &&
187 dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
188 dialogGeom.width() <= applet->containment()->size().width()) {
189 borders &= ~FrameSvg::TopBorder;
197 if (applet->containment() &&
198 dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
199 dialogGeom.height() <= applet->containment()->size().height()) {
200 borders &= ~FrameSvg::LeftBorder;
207 if (applet->containment() &&
208 dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
209 dialogGeom.height() <= applet->containment()->size().height()) {
210 borders &= ~FrameSvg::RightBorder;
222 if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
223 if (!avail.contains(QPoint(dialogGeom.left()-1, dialogGeom.center().y()))) {
224 borders &= ~FrameSvg::LeftBorder;
226 if (!avail.contains(QPoint(dialogGeom.center().x(), dialogGeom.top()-1))) {
227 borders &= ~FrameSvg::TopBorder;
230 if (!avail.contains(QPoint(dialogGeom.right()+1, dialogGeom.center().y()))) {
231 borders &= ~FrameSvg::RightBorder;
233 if (!avail.contains(QPoint(dialogGeom.center().x(), dialogGeom.bottom()+1))) {
234 borders &= ~FrameSvg::BottomBorder;
238 background->setEnabledBorders(borders);
239 DialogShadows::self()->addWindow(q, borders);
249 extender->d->setDisabledBordersHint(disabledBorders);
252 qreal left, top, right, bottom;
253 background->getMargins(left, top, right, bottom);
254 if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
255 if (QApplication::layoutDirection() == Qt::RightToLeft) {
262 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
266 q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
268 if (resizeChecksWithBorderCheck) {
269 updateResizeCorners();
272 }
else if (currentBorders != borders) {
273 if (updateMaskIfNeeded) {
280 resizeChecksWithBorderCheck =
false;
285 d->adjustViewTimer->stop();
287 if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
288 const int prevStartCorner = d->resizeStartCorner;
289 d->resizeStartCorner = -1;
290 QSize prevSize = size();
299 int left, top, right, bottom;
300 getContentsMargins(&left, &top, &right, &bottom);
302 QDesktopWidget *desktop = QApplication::desktop();
303 QSize maxSize = desktop->availableGeometry(desktop->screenNumber(
this)).size();
305 setMinimumSize(0, 0);
306 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
308 QSize newSize(qMin(
int(graphicsWidget->size().width()) + left + right, maxSize.width()),
309 qMin(
int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
311 const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
312 QSize newMinimumSize(qMin(
int(minimum.width()) + left + right, maxSize.width()),
313 qMin(
int(minimum.height()) + top + bottom, maxSize.height()));
316 QSize newMaximumSize(qMin(
int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
317 qMin(
int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
322 QRect currentGeometry(geometry());
323 currentGeometry.setSize(newSize);
326 currentGeometry.setSize(newSize);
328 currentGeometry.moveTopRight(geometry().topRight());
331 currentGeometry.moveBottomLeft(geometry().bottomLeft());
333 setGeometry(currentGeometry);
338 setMinimumSize(newMinimumSize);
339 setMaximumSize(newMaximumSize);
346 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
348 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
349 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
350 d->view->setSceneRect(sceneRect);
353 d->view->centerOn(graphicsWidget);
355 if (size() != prevSize) {
360 d->resizeStartCorner = prevStartCorner;
364 int DialogPrivate::calculateWidthForHeightAndRatio(
int height, qreal ratio)
366 switch (aspectRatioMode) {
368 return qRound(height * ratio);
382 :
QWidget(parent, f | Qt::FramelessWindowHint),
383 d(new DialogPrivate(this))
385 setMouseTracking(
true);
386 setAttribute(Qt::WA_TranslucentBackground);
388 d->background->setImagePath(
"dialogs/background");
390 d->background->resizeFrame(size());
391 connect(d->background, SIGNAL(repaintNeeded()),
this, SLOT(themeChanged()));
393 QPalette pal = palette();
394 pal.setColor(backgroundRole(), Qt::transparent);
398 d->adjustViewTimer =
new QTimer(
this);
399 d->adjustViewTimer->setSingleShot(
true);
402 d->adjustSizeTimer =
new QTimer(
this);
403 d->adjustSizeTimer->setSingleShot(
true);
404 connect(d->adjustSizeTimer, SIGNAL(timeout()),
this, SLOT(delayedAdjustSize()));
411 DialogShadows::self()->removeWindow(
this);
418 p.setCompositionMode(QPainter::CompositionMode_Source);
419 d->background->paintFrame(&p, e->rect(), e->rect());
424 if (event->modifiers() == Qt::AltModifier) {
427 setCursor(Qt::SizeBDiagCursor);
429 setCursor(Qt::SizeFDiagCursor);
431 setCursor(Qt::SizeFDiagCursor);
433 setCursor(Qt::SizeBDiagCursor);
434 }
else if (!(event->buttons() & Qt::LeftButton)) {
444 qreal aspectRatio = (qreal)width() / (qreal)height();
446 switch(d->resizeStartCorner) {
448 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
449 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
450 if (newWidth == -1) {
451 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
453 position = QPoint(x(), y() + height() - newHeight);
456 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
457 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
458 if (newWidth == -1) {
459 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
461 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
464 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
465 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
466 if (newWidth == -1) {
467 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
469 position = QPoint(x() + width() - newWidth, y());
472 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
473 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
474 if (newWidth == -1) {
475 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
477 position = QPoint(x(), y());
480 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
481 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
482 if (newWidth == -1) {
483 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
485 position = QPoint(x(), y());
489 QRect newGeom(position, QSize(newWidth, newHeight));
492 if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
493 newGeom.setLeft(d->leftResizeMin);
496 if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
497 newGeom.setTop(d->topResizeMin);
500 if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
501 newGeom.setRight(d->rightResizeMin);
504 if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
505 newGeom.setBottom(d->bottomResizeMin);
508 if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
509 setGeometry(newGeom);
513 QWidget::mouseMoveEvent(event);
530 QWidget::mousePressEvent(event);
541 QWidget::mouseReleaseEvent(event);
546 if (event->key() == Qt::Key_Escape) {
553 return QWidget::event(event);
560 d->scheduleBorderCheck(
true);
562 if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
564 graphicsWidget->resize(d->view->size());
566 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
567 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
568 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
569 d->view->setSceneRect(sceneRect);
570 d->view->centerOn(graphicsWidget);
574 void DialogPrivate::updateResizeCorners()
576 const int resizeAreaMargin = 20;
577 const QRect r = q->rect();
578 const FrameSvg::EnabledBorders borders = background->enabledBorders();
589 resizeAreaMargin, resizeAreaMargin);
595 resizeAreas[
Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
602 r.bottom() - resizeAreaMargin,
603 resizeAreaMargin, resizeAreaMargin);
610 resizeAreaMargin, resizeAreaMargin);
616 if (d->graphicsWidgetPtr) {
617 d->graphicsWidgetPtr.data()->removeEventFilter(
this);
620 d->graphicsWidgetPtr = widget;
629 QVBoxLayout *lay =
new QVBoxLayout(
this);
638 d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
639 d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
640 d->view->setFrameShape(QFrame::NoFrame);
641 d->view->viewport()->setAutoFillBackground(
false);
642 layout()->addWidget(d->view);
645 d->view->setScene(widget->scene());
648 d->view->centerOn(widget);
649 if (widget->layout()) {
650 widget->layout()->activate();
652 static_cast<QGraphicsLayoutItem *
>(widget)->updateGeometry();
653 widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
659 widget->installEventFilter(
this);
660 d->view->installEventFilter(
this);
670 return d->graphicsWidgetPtr.data();
675 if (d->resizeStartCorner ==
Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
676 (
event->type() == QEvent::GraphicsSceneResize ||
event->type() == QEvent::GraphicsSceneMove)) {
677 d->adjustViewTimer->start(150);
685 if (event->type() == QEvent::Enter && watched == d->view) {
689 return QWidget::eventFilter(watched, event);
704 d->updateResizeCorners();
707 if (graphicsWidget &&
708 ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
709 d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
710 d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
713 d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
714 d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
721 if (graphicsWidget) {
722 graphicsWidget->setFocus();
727 DialogShadows::self()->addWindow(
this, d->background->enabledBorders());
739 if (graphicsWidget) {
740 graphicsWidget->setFocus();
748 d->scheduleBorderCheck();
754 d->resizeCorners = corners;
755 d->updateResizeCorners();
761 return d->resizeCorners;
766 return d->resizeStartCorner >
NoCorner;
771 d->leftResizeMin = left;
772 d->topResizeMin = top;
773 d->rightResizeMin = right;
774 d->bottomResizeMin = bottom;
780 *left = d->leftResizeMin;
784 *top = d->topResizeMin;
788 *right = d->rightResizeMin;
792 *bottom = d->bottomResizeMin;
864 foreach (
const QRect &r, d->resizeAreas) {
865 if (r.contains(point)) {
874 return d->aspectRatioMode;
883 d->aspectRatioMode = mode;
887 #include "dialog.moc"