24#include "private/dialog_p.h"
27#include <QSvgRenderer>
28#include <QResizeEvent>
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"
67void 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()));
95void DialogPrivate::themeChanged()
102 q->setAttribute(Qt::WA_NoSystemBackground, !translucency);
103 WindowEffects::overrideShadow(q->winId(), !DialogShadows::self()->enabled());
108void DialogPrivate::updateMask()
111 WindowEffects::enableBlurBehind(q->winId(), translucency,
112 translucency ? background->mask() : QRegion());
116 q->setMask(background->mask());
120void DialogPrivate::checkBorders()
125void DialogPrivate::delayedAdjustSize()
127 q->syncToGraphicsWidget();
130void DialogPrivate::checkBorders(
bool updateMaskIfNeeded)
132 if (resizeChecksWithBorderCheck) {
133 background->resizeFrame(q->size());
137 const FrameSvg::EnabledBorders currentBorders = background->enabledBorders();
138 FrameSvg::EnabledBorders borders = FrameSvg::AllBorders;
140 Extender *extender = qobject_cast<Extender*>(graphicsWidget);
146 QDesktopWidget *desktop = QApplication::desktop();
149 c = qobject_cast<Plasma::Corona *>(applet->scene());
150 }
else if (graphicsWidget) {
151 c = qobject_cast<Plasma::Corona *>(graphicsWidget->scene());
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);
176 dialogGeom.bottom() + 2 >= screenGeom.bottom() - applet->
containment()->size().height() &&
177 dialogGeom.width() <= applet->
containment()->size().width()) {
178 borders &= ~FrameSvg::BottomBorder;
187 dialogGeom.top() <= screenGeom.top() + applet->
containment()->size().height() &&
188 dialogGeom.width() <= applet->
containment()->size().width()) {
189 borders &= ~FrameSvg::TopBorder;
198 dialogGeom.left() <= screenGeom.left() + applet->
containment()->size().width() &&
199 dialogGeom.height() <= applet->
containment()->size().height()) {
200 borders &= ~FrameSvg::LeftBorder;
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);
242 FrameSvg::EnabledBorders disabledBorders = FrameSvg::NoBorder;
243 if (!(borders & FrameSvg::LeftBorder)) {
244 disabledBorders |= FrameSvg::LeftBorder;
246 if (!(borders & FrameSvg::RightBorder)) {
247 disabledBorders |= FrameSvg::RightBorder;
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;
283void Dialog::syncToGraphicsWidget()
285 d->adjustViewTimer->stop();
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);
348 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
349 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
350 d->view->setSceneRect(sceneRect);
355 if (size() != prevSize) {
360 d->resizeStartCorner = prevStartCorner;
364int DialogPrivate::calculateWidthForHeightAndRatio(
int height, qreal ratio)
366 switch (aspectRatioMode) {
368 return qRound(height * ratio);
381Dialog::Dialog(
QWidget *parent, Qt::WindowFlags f)
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);
415void Dialog::paintEvent(QPaintEvent *e)
418 p.setCompositionMode(QPainter::CompositionMode_Source);
419 d->background->paintFrame(&p, e->rect(), e->rect());
422void Dialog::mouseMoveEvent(QMouseEvent *event)
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);
516void Dialog::mousePressEvent(QMouseEvent *event)
530 QWidget::mousePressEvent(
event);
533void Dialog::mouseReleaseEvent(QMouseEvent *event)
541 QWidget::mouseReleaseEvent(
event);
544void Dialog::keyPressEvent(QKeyEvent *event)
546 if (
event->key() == Qt::Key_Escape) {
551bool Dialog::event(QEvent *event)
553 return QWidget::event(
event);
556void Dialog::resizeEvent(QResizeEvent *event)
560 d->scheduleBorderCheck(
true);
562 if (d->resizeStartCorner != -1 && d->view && d->graphicsWidgetPtr) {
567 sceneRect.setWidth(qMax(qreal(1), sceneRect.width()));
568 sceneRect.setHeight(qMax(qreal(1), sceneRect.height()));
569 d->view->setSceneRect(sceneRect);
574void DialogPrivate::updateResizeCorners()
576 const int resizeAreaMargin = 20;
577 const QRect r = q->rect();
578 const FrameSvg::EnabledBorders borders = background->enabledBorders();
585 if (resizeCorners & Dialog::NorthEast ||
586 (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::LeftBorder)) ||
587 (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::BottomBorder))) {
588 resizeAreas[Dialog::NorthEast] = QRect(r.right() - resizeAreaMargin, 0,
589 resizeAreaMargin, resizeAreaMargin);
592 if (resizeCorners & Dialog::NorthWest ||
593 (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::RightBorder)) ||
594 (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::BottomBorder))) {
595 resizeAreas[Dialog::NorthWest] = QRect(0, 0, resizeAreaMargin, resizeAreaMargin);
598 if (resizeCorners & Dialog::SouthEast ||
599 (resizeCorners & Dialog::SouthWest && !(borders & FrameSvg::LeftBorder)) ||
600 (resizeCorners & Dialog::NorthEast && !(borders & FrameSvg::TopBorder))) {
601 resizeAreas[Dialog::SouthEast] = QRect(r.right() - resizeAreaMargin,
602 r.bottom() - resizeAreaMargin,
603 resizeAreaMargin, resizeAreaMargin);
606 if (resizeCorners & Dialog::SouthWest ||
607 (resizeCorners & Dialog::SouthEast && !(borders & FrameSvg::RightBorder)) ||
608 (resizeCorners & Dialog::NorthWest && !(borders & FrameSvg::TopBorder))) {
609 resizeAreas[Dialog::SouthWest] = QRect(0, r.bottom() - resizeAreaMargin,
610 resizeAreaMargin, resizeAreaMargin);
616 if (d->graphicsWidgetPtr) {
617 d->graphicsWidgetPtr.data()->removeEventFilter(
this);
620 d->graphicsWidgetPtr = widget;
623 Plasma::Corona *c = qobject_cast<Plasma::Corona *>(widget->scene());
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();
673bool Dialog::eventFilter(
QObject *watched, QEvent *event)
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);
692void Dialog::hideEvent(QHideEvent * event)
698void Dialog::showEvent(QShowEvent * event)
704 d->updateResizeCorners();
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();
727 DialogShadows::self()->addWindow(
this, d->background->enabledBorders());
730void Dialog::focusInEvent(QFocusEvent *event)
744void Dialog::moveEvent(QMoveEvent *event)
748 d->scheduleBorderCheck();
751void Dialog::setResizeHandleCorners(ResizeCorners corners)
754 d->resizeCorners = corners;
755 d->updateResizeCorners();
759Dialog::ResizeCorners Dialog::resizeCorners()
const
761 return d->resizeCorners;
764bool Dialog::isUserResizing()
const
766 return d->resizeStartCorner >
NoCorner;
769void Dialog::setMinimumResizeLimits(
int left,
int top,
int right,
int bottom)
771 d->leftResizeMin = left;
772 d->topResizeMin = top;
773 d->rightResizeMin = right;
774 d->bottomResizeMin = bottom;
777void Dialog::getMinimumResizeLimits(
int *left,
int *top,
int *right,
int *bottom)
780 *left = d->leftResizeMin;
784 *top = d->topResizeMin;
788 *right = d->rightResizeMin;
792 *bottom = d->bottomResizeMin;
862bool Dialog::inControlArea(
const QPoint &point)
864 foreach (
const QRect &r, d->resizeAreas) {
865 if (r.contains(point)) {
874 return d->aspectRatioMode;
883 d->aspectRatioMode = mode;
Containment * containment() const
virtual Location location() const
Returns the location of the scene which is displaying applet.
A QGraphicsScene for Plasma::Applets.
virtual QRegion availableScreenRegion(int id) const
Returns the available region for a given screen.
virtual QRect screenGeometry(int id) const
Returns the geometry of a given screen.
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
void dialogResized()
Fires when the dialog automatically resizes.
void setResizeHandleCorners(ResizeCorners corners)
void syncToGraphicsWidget()
Adjusts the dialog to the associated QGraphicsWidget's geometry Should not normally need to be called...
QGraphicsWidget * graphicsWidget()
void dialogVisible(bool status)
Emit a signal when the dialog become visible/invisible.
bool event(QEvent *event)
Plasma::AspectRatioMode aspectRatioMode() const
Provides an SVG with borders.
static Theme * defaultTheme()
Singleton pattern accessor.
Q_INVOKABLE bool windowTranslucencyEnabled() const
void slideWindow(WId id, Plasma::Location location, int offset)
Mark a window as sliding from screen edge.
void overrideShadow(WId window, bool override)
Forbid te windowmanager to automatically generate a shadow for this window.
Namespace for everything in libplasma.
AspectRatioMode
Defines the aspect ratio used when scaling an applet.
@ KeepAspectRatio
The applet keeps a fixed aspect ratio.
@ Square
The applet is always a square.
@ ConstrainedSquare
The applet is no wider (in horizontal formfactors) or no higher (in vertical ones) than a square.
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
@ LeftEdge
Along the left side of the screen.
@ Desktop
On the planar desktop layer, extending across the full screen from edge to edge.
@ TopEdge
Along the top of the screen.
@ RightEdge
Along the right side of the screen.
@ BottomEdge
Along the bottom of the screen.
Direction
The Direction enumeration describes in which direction, relative to the Applet (and its managing cont...
@ Right
Display to the right.
@ Left
Display to the left.