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) {
156 foreach (QRect rect, r.rects()) {
157 if (rect.width() > maxRect.width() && rect.height() > maxRect.height()) {
164 avail = desktop->availableGeometry(desktop->screenNumber(q));
165 screenGeom = desktop->screenGeometry(desktop->screenNumber(q));
168 QRect dialogGeom = q->geometry();
173 qreal bottomHeight(0);
177 if (applet && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
178 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
180 switch (applet->location()) {
182 if (applet->containment() &&
183 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->containment()->size().height() &&
184 dialogGeom.width() <= applet->containment()->size().width()) {
185 borders &= ~FrameSvg::BottomBorder;
193 if (applet->containment() &&
194 dialogGeom.top() <= screenGeom.top() + applet->containment()->size().height() &&
195 dialogGeom.width() <= applet->containment()->size().width()) {
196 borders &= ~FrameSvg::TopBorder;
204 if (applet->containment() &&
205 dialogGeom.left() <= screenGeom.left() + applet->containment()->size().width() &&
206 dialogGeom.height() <= applet->containment()->size().height()) {
207 borders &= ~FrameSvg::LeftBorder;
214 if (applet->containment() &&
215 dialogGeom.right() + 2 >= screenGeom.right() - applet->containment()->size().width() &&
216 dialogGeom.height() <= applet->containment()->size().height()) {
217 borders &= ~FrameSvg::RightBorder;
229 if (q->isVisible() && !q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) {
230 if (dialogGeom.left() <= avail.left()) {
231 borders &= ~FrameSvg::LeftBorder;
233 if (dialogGeom.top() <= avail.top()) {
234 borders &= ~FrameSvg::TopBorder;
237 if (dialogGeom.right() + 2 > avail.right()) {
238 borders &= ~FrameSvg::RightBorder;
240 if (dialogGeom.bottom() + 2 > avail.bottom()) {
241 borders &= ~FrameSvg::BottomBorder;
245 background->setEnabledBorders(borders);
246 DialogShadows::self()->addWindow(q, borders);
256 extender->d->setDisabledBordersHint(disabledBorders);
259 qreal left, top, right, bottom;
260 background->getMargins(left, top, right, bottom);
261 if (extender->d->scrollWidget->viewportGeometry().height() < extender->d->scrollWidget->contentsSize().height()) {
262 if (QApplication::layoutDirection() == Qt::RightToLeft) {
269 background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
273 q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
275 if (resizeChecksWithBorderCheck) {
276 updateResizeCorners();
279 }
else if (currentBorders != borders) {
280 if (updateMaskIfNeeded) {
287 resizeChecksWithBorderCheck =
false;
292 d->adjustViewTimer->stop();
294 if (d->view && graphicsWidget && d->resizeStartCorner != -1) {
295 const int prevStartCorner = d->resizeStartCorner;
296 d->resizeStartCorner = -1;
297 QSize prevSize = size();
306 int left, top, right, bottom;
307 getContentsMargins(&left, &top, &right, &bottom);
309 QDesktopWidget *desktop = QApplication::desktop();
310 QSize maxSize = desktop->availableGeometry(desktop->screenNumber(
this)).size();
312 setMinimumSize(0, 0);
313 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
315 QSize newSize(qMin(
int(graphicsWidget->size().width()) + left + right, maxSize.width()),
316 qMin(
int(graphicsWidget->size().height()) + top + bottom, maxSize.height()));
318 const QSizeF minimum = graphicsWidget->effectiveSizeHint(Qt::MinimumSize);
319 QSize newMinimumSize(qMin(
int(minimum.width()) + left + right, maxSize.width()),
320 qMin(
int(minimum.height()) + top + bottom, maxSize.height()));
323 QSize newMaximumSize(qMin(
int(graphicsWidget->maximumSize().width()) + left + right, maxSize.width()),
324 qMin(
int(graphicsWidget->maximumSize().height()) + top + bottom, maxSize.height()));
329 QRect currentGeometry(geometry());
330 currentGeometry.setSize(newSize);
333 currentGeometry.setSize(newSize);
335 currentGeometry.moveTopRight(geometry().topRight());
338 currentGeometry.moveBottomLeft(geometry().bottomLeft());
340 setGeometry(currentGeometry);
345 setMinimumSize(newMinimumSize);
346 setMaximumSize(newMaximumSize);
353 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
355 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
356 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
357 d->view->setSceneRect(sceneRect);
360 d->view->centerOn(graphicsWidget);
362 if (size() != prevSize) {
367 d->resizeStartCorner = prevStartCorner;
371 int DialogPrivate::calculateWidthForHeightAndRatio(
int height, qreal ratio)
373 switch (aspectRatioMode) {
375 return qRound(height * ratio);
389 :
QWidget(parent, f | Qt::FramelessWindowHint),
390 d(new DialogPrivate(this))
392 setMouseTracking(
true);
393 setAttribute(Qt::WA_TranslucentBackground);
395 d->background->setImagePath(
"dialogs/background");
397 d->background->resizeFrame(size());
398 connect(d->background, SIGNAL(repaintNeeded()),
this, SLOT(themeChanged()));
400 QPalette pal = palette();
401 pal.setColor(backgroundRole(), Qt::transparent);
405 d->adjustViewTimer =
new QTimer(
this);
406 d->adjustViewTimer->setSingleShot(
true);
409 d->adjustSizeTimer =
new QTimer(
this);
410 d->adjustSizeTimer->setSingleShot(
true);
411 connect(d->adjustSizeTimer, SIGNAL(timeout()),
this, SLOT(delayedAdjustSize()));
418 DialogShadows::self()->removeWindow(
this);
425 p.setCompositionMode(QPainter::CompositionMode_Source);
426 d->background->paintFrame(&p, e->rect(), e->rect());
431 if (event->modifiers() == Qt::AltModifier) {
434 setCursor(Qt::SizeBDiagCursor);
436 setCursor(Qt::SizeFDiagCursor);
438 setCursor(Qt::SizeFDiagCursor);
440 setCursor(Qt::SizeBDiagCursor);
441 }
else if (!(event->buttons() & Qt::LeftButton)) {
451 qreal aspectRatio = (qreal)width() / (qreal)height();
453 switch(d->resizeStartCorner) {
455 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
456 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
457 if (newWidth == -1) {
458 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
460 position = QPoint(x(), y() + height() - newHeight);
463 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height() - event->y()));
464 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
465 if (newWidth == -1) {
466 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
468 position = QPoint(x() + width() - newWidth, y() + height() - newHeight);
471 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
472 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
473 if (newWidth == -1) {
474 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width() - event->x()));
476 position = QPoint(x() + width() - newWidth, y());
479 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), event->y()));
480 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
481 if (newWidth == -1) {
482 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), event->x()));
484 position = QPoint(x(), y());
487 newHeight = qMin(maximumHeight(), qMax(minimumHeight(), height()));
488 newWidth = d->calculateWidthForHeightAndRatio(newHeight, aspectRatio);
489 if (newWidth == -1) {
490 newWidth = qMin(maximumWidth(), qMax(minimumWidth(), width()));
492 position = QPoint(x(), y());
496 QRect newGeom(position, QSize(newWidth, newHeight));
499 if (d->leftResizeMin > -1 && newGeom.left() > d->leftResizeMin) {
500 newGeom.setLeft(d->leftResizeMin);
503 if (d->topResizeMin > -1 && newGeom.top() > d->topResizeMin) {
504 newGeom.setTop(d->topResizeMin);
507 if (d->rightResizeMin > -1 && newGeom.right() < d->rightResizeMin) {
508 newGeom.setRight(d->rightResizeMin);
511 if (d->bottomResizeMin > -1 && newGeom.bottom() < d->bottomResizeMin) {
512 newGeom.setBottom(d->bottomResizeMin);
515 if ((newGeom.width() >= minimumSize().width()) && (newGeom.height() >= minimumSize().height())) {
516 setGeometry(newGeom);
520 QWidget::mouseMoveEvent(event);
537 QWidget::mousePressEvent(event);
548 QWidget::mouseReleaseEvent(event);
553 if (event->key() == Qt::Key_Escape) {
560 return QWidget::event(event);
567 d->scheduleBorderCheck(
true);
569 if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
571 graphicsWidget->resize(d->view->size());
573 QRectF sceneRect(graphicsWidget->sceneBoundingRect());
574 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
575 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
576 d->view->setSceneRect(sceneRect);
577 d->view->centerOn(graphicsWidget);
581 void DialogPrivate::updateResizeCorners()
583 const int resizeAreaMargin = 20;
584 const QRect r = q->rect();
585 const FrameSvg::EnabledBorders borders = background->enabledBorders();
596 resizeAreaMargin, resizeAreaMargin);
602 resizeAreas[
Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
609 r.bottom() - resizeAreaMargin,
610 resizeAreaMargin, resizeAreaMargin);
617 resizeAreaMargin, resizeAreaMargin);
623 if (d->graphicsWidgetPtr) {
624 d->graphicsWidgetPtr.data()->removeEventFilter(
this);
627 d->graphicsWidgetPtr = widget;
636 QVBoxLayout *lay =
new QVBoxLayout(
this);
645 d->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
646 d->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
647 d->view->setFrameShape(QFrame::NoFrame);
648 d->view->viewport()->setAutoFillBackground(
false);
649 layout()->addWidget(d->view);
652 d->view->setScene(widget->scene());
655 d->view->centerOn(widget);
656 if (widget->layout()) {
657 widget->layout()->activate();
659 static_cast<QGraphicsLayoutItem *
>(widget)->updateGeometry();
660 widget->resize(widget->size().expandedTo(widget->effectiveSizeHint(Qt::MinimumSize)));
666 widget->installEventFilter(
this);
667 d->view->installEventFilter(
this);
677 return d->graphicsWidgetPtr.data();
682 if (d->resizeStartCorner ==
Dialog::NoCorner && watched == d->graphicsWidgetPtr.data() &&
683 (
event->type() == QEvent::GraphicsSceneResize ||
event->type() == QEvent::GraphicsSceneMove)) {
684 d->adjustViewTimer->start(150);
692 if (event->type() == QEvent::Enter && watched == d->view) {
696 return QWidget::eventFilter(watched, event);
711 d->updateResizeCorners();
714 if (graphicsWidget &&
715 ((d->view && graphicsWidget->size().toSize() != d->view->size()) ||
716 d->oldGraphicsWidgetMinimumSize != graphicsWidget->minimumSize() ||
717 d->oldGraphicsWidgetMaximumSize != graphicsWidget->maximumSize())) {
720 d->oldGraphicsWidgetMinimumSize = graphicsWidget->minimumSize().toSize();
721 d->oldGraphicsWidgetMaximumSize = graphicsWidget->maximumSize().toSize();
728 if (graphicsWidget) {
729 graphicsWidget->setFocus();
734 DialogShadows::self()->addWindow(
this, d->background->enabledBorders());
746 if (graphicsWidget) {
747 graphicsWidget->setFocus();
755 d->scheduleBorderCheck();
761 d->resizeCorners = corners;
762 d->updateResizeCorners();
768 return d->resizeCorners;
773 return d->resizeStartCorner >
NoCorner;
778 d->leftResizeMin = left;
779 d->topResizeMin = top;
780 d->rightResizeMin = right;
781 d->bottomResizeMin = bottom;
787 *left = d->leftResizeMin;
791 *top = d->topResizeMin;
795 *right = d->rightResizeMin;
799 *bottom = d->bottomResizeMin;
871 foreach (
const QRect &r, d->resizeAreas) {
872 if (r.contains(point)) {
881 return d->aspectRatioMode;
890 d->aspectRatioMode = mode;
894 #include "dialog.moc"