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"
virtual QRect screenGeometry(int id) const
Returns the geometry of a given screen.
void mouseReleaseEvent(QMouseEvent *event)
void dialogVisible(bool status)
Emit a signal when the dialog become visible/invisible.
void enableBlurBehind(WId window, bool enable, const QRegion ®ion)
Instructs the window manager to blur the background in the specified region behind the given window...
void overrideShadow(WId window, bool override)
Forbid te windowmanager to automatically generate a shadow for this window.
bool eventFilter(QObject *watched, QEvent *event)
void animatedShow(Plasma::Direction direction)
Causes an animated show; requires compositing to work, otherwise the dialog will simply show...
virtual Location location() const
Returns the location of the scene which is displaying applet.
The applet is no wider (in horizontal formfactors) or no higher (in vertical ones) than a square...
Plasma::AspectRatioMode aspectRatioMode() const
virtual QRegion availableScreenRegion(int id) const
Returns the available region for a given screen.
On the planar desktop layer, extending across the full screen from edge to edge.
bool isUserResizing() const
Provides an SVG with borders.
The applet is always a square.
void syncToGraphicsWidget()
Adjusts the dialog to the associated QGraphicsWidget's geometry Should not normally need to be called...
void hideEvent(QHideEvent *event)
QGraphicsWidget * graphicsWidget()
void resizeEvent(QResizeEvent *e)
void focusInEvent(QFocusEvent *event)
void setGraphicsWidget(QGraphicsWidget *widget)
Sets a QGraphicsWidget to be shown as the content in this dialog.
void moveEvent(QMoveEvent *event)
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
void keyPressEvent(QKeyEvent *event)
bool inControlArea(const QPoint &point)
Convenience method to know whether the point is in a control area (e.g.
The applet keeps a fixed aspect ratio.
void slideWindow(WId id, Plasma::Location location, int offset)
Mark a window as sliding from screen edge.
void setMinimumResizeLimits(int left, int top, int right, int bottom)
Sets the minimum values that each of four sides of the rect may expand to or from.
void mousePressEvent(QMouseEvent *event)
Q_INVOKABLE bool windowTranslucencyEnabled() const
Along the top of the screen.
void animatedHide(Plasma::Direction direction)
Causes an animated hide; requires compositing to work, otherwise the dialog will simply hide...
void setAspectRatioMode(Plasma::AspectRatioMode mode)
Sets the preferred aspect ratio mode for placement and resizing.
bool event(QEvent *event)
Along the bottom of the screen.
Dialog(QWidget *parent=0, Qt::WindowFlags f=Qt::Window)
void getMinimumResizeLimits(int *left, int *top, int *right, int *bottom)
Retrives the minimum resize limits for the dialog.
static Theme * defaultTheme()
Singleton pattern accessor.
ResizeCorners resizeCorners() const
Convenience method to get the enabled resize corners.
Along the right side of the screen.
void setResizeHandleCorners(ResizeCorners corners)
Direction
The Direction enumeration describes in which direction, relative to the Applet (and its managing cont...
void showEvent(QShowEvent *event)
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
void paintEvent(QPaintEvent *e)
Reimplemented from QWidget.
Along the left side of the screen.
void dialogResized()
Fires when the dialog automatically resizes.
void mouseMoveEvent(QMouseEvent *event)
A QGraphicsScene for Plasma::Applets.
AspectRatioMode
Defines the aspect ratio used when scaling an applet.