implement popupPosition

call it only by setting a visualParent, don't expose it to qml for now
This commit is contained in:
Marco Martin 2013-02-20 20:39:15 +01:00
parent a1507092a0
commit de81cdada3
3 changed files with 84 additions and 99 deletions

View File

@ -28,6 +28,7 @@
#include <QQuickItem> #include <QQuickItem>
#include <QTimer> #include <QTimer>
#include <QLayout> #include <QLayout>
#include <QScreen>
#include <KWindowSystem> #include <KWindowSystem>
@ -166,6 +167,25 @@ void DialogProxy::setMainItem(QQuickItem *mainItem)
} }
} }
QQuickItem *DialogProxy::visualParent() const
{
return m_visualParent.data();
}
void DialogProxy::setVisualParent(QQuickItem *visualParent)
{
if (m_visualParent.data() == visualParent) {
return;
}
if (visualParent) {
setPosition(popupPosition(visualParent, Qt::AlignCenter));
}
m_visualParent = visualParent;
emit visualParentChanged();
}
bool DialogProxy::isVisible() const bool DialogProxy::isVisible() const
{ {
return QQuickWindow::isVisible(); return QQuickWindow::isVisible();
@ -176,6 +196,10 @@ void DialogProxy::setVisible(const bool visible)
if (visible) { if (visible) {
syncToMainItemSize(); syncToMainItemSize();
if (m_visualParent) {
setPosition(popupPosition(m_visualParent.data(), Qt::AlignCenter));
}
const QRect workArea(KWindowSystem::workArea()); const QRect workArea(KWindowSystem::workArea());
if (!workArea.contains(geometry())) { if (!workArea.contains(geometry())) {
setPosition(qBound(workArea.left(), x(), workArea.right() - width()), setPosition(qBound(workArea.left(), x(), workArea.right() - width()),
@ -190,102 +214,47 @@ void DialogProxy::setVisible(const bool visible)
QPoint DialogProxy::popupPosition(QQuickItem *item, int alignment) QPoint DialogProxy::popupPosition(QQuickItem *item, int alignment)
{ {
/* if (!item) {
QQuickItem *actualItem = item; //If no item was specified try to align at the center of the parent view
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
//if no item is passed search the root item in order to figure out the view if (parentItem && parentItem->window()) {
if (!actualItem) { return parentItem->window()->geometry().center() - QPoint(width()/2, height()/2);
actualItem = qobject_cast<QQuickItem *>(parent());
//search the root object
while (true) {
QQuickItem *ancestor = qobject_cast<QQuickItem *>(actualItem->parent());
if (ancestor) {
actualItem = ancestor;
} else {
break;
}
}
if (!actualItem) {
return QPoint();
}
}
//m_dialog->syncToGraphicsWidget();
Plasma::Corona *corona = qobject_cast<Plasma::Corona *>(actualItem->scene());
if (corona && item) {
return corona->popupPosition(actualItem, m_dialog->size(), (Qt::AlignmentFlag)alignment);
} else {
if (!actualItem->scene()) {
return QPoint();
}
QList<QGraphicsView*> views = actualItem->scene()->views();
if (views.size() < 1) {
return QPoint();
}
QGraphicsView *view = 0;
if (views.size() == 1) {
view = views[0];
} else { } else {
QGraphicsView *found = 0;
QGraphicsView *possibleFind = 0;
foreach (QGraphicsView *v, views) {
if (v->sceneRect().intersects(actualItem->sceneBoundingRect()) ||
v->sceneRect().contains(actualItem->scenePos())) {
if (v->isActiveWindow()) {
found = v;
} else {
possibleFind = v;
}
}
}
view = found ? found : possibleFind;
}
if (!view) {
return QPoint(); return QPoint();
} }
//if no item was explicitly specified, align the dialog in the center of the parent view
if (!item) {
return view->geometry().center() - QPoint(m_dialog->width()/2, m_dialog->height()/2);
}
//swap direction if necessary
if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
if (alignment == Qt::AlignRight) {
alignment = Qt::AlignLeft;
} else {
alignment = Qt::AlignRight;
}
}
int xOffset = 0;
if (alignment == Qt::AlignCenter) {
xOffset = actualItem->boundingRect().width()/2 - m_dialog->width()/2;
} else if (alignment == Qt::AlignRight) {
xOffset = actualItem->boundingRect().width() - m_dialog->width();
}
const QRect avail = QApplication::desktop()->availableGeometry(view);
QPoint menuPos = view->mapToGlobal(view->mapFromScene(actualItem->scenePos()+QPoint(xOffset, actualItem->boundingRect().height())));
if (menuPos.y() + m_dialog->height() > avail.bottom()) {
menuPos = view->mapToGlobal(view->mapFromScene(actualItem->scenePos() - QPoint(-xOffset, m_dialog->height())));
}
return menuPos;
} }
*/
return QPoint(200, 400); QPointF pos = item->mapToScene(QPointF(0, 0));
if (item->window() && item->window()->screen()) {
pos = item->window()->mapToGlobal(pos.toPoint());
} else {
return QPoint();
}
//swap direction if necessary
if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
if (alignment == Qt::AlignRight) {
alignment = Qt::AlignLeft;
} else {
alignment = Qt::AlignRight;
}
}
int xOffset = 0;
if (alignment == Qt::AlignCenter) {
xOffset = item->boundingRect().width()/2 - width()/2;
} else if (alignment == Qt::AlignRight) {
xOffset = item->boundingRect().width() - width();
}
const QRect avail = item->window()->screen()->availableGeometry();
QPoint menuPos = pos.toPoint() + QPoint(xOffset, item->boundingRect().height());
if (menuPos.y() + height() > avail.bottom()) {
menuPos = pos.toPoint() + QPoint(xOffset, -height());
}
return menuPos;
} }

View File

@ -100,6 +100,11 @@ class DialogProxy : public QQuickWindow
*/ */
Q_PROPERTY(QQuickItem *mainItem READ mainItem WRITE setMainItem NOTIFY mainItemChanged) Q_PROPERTY(QQuickItem *mainItem READ mainItem WRITE setMainItem NOTIFY mainItemChanged)
/**
* The main QML item that will be displayed in the Dialog
*/
Q_PROPERTY(QQuickItem *visualParent READ visualParent WRITE setVisualParent NOTIFY visualParentChanged)
/** /**
* Visibility of the Dialog window. Doesn't have anything to do with the visibility of the mainItem. * Visibility of the Dialog window. Doesn't have anything to do with the visibility of the mainItem.
*/ */
@ -146,6 +151,9 @@ public:
QQuickItem *mainItem() const; QQuickItem *mainItem() const;
void setMainItem(QQuickItem *mainItem); void setMainItem(QQuickItem *mainItem);
QQuickItem *visualParent() const;
void setVisualParent(QQuickItem *visualParent);
bool isVisible() const; bool isVisible() const;
void setVisible(const bool visible); void setVisible(const bool visible);
@ -176,7 +184,7 @@ public:
* @arg alignment alignment of the popup compared to the item * @arg alignment alignment of the popup compared to the item
*/ */
//FIXME: alignment should be Qt::AlignmentFlag //FIXME: alignment should be Qt::AlignmentFlag
Q_INVOKABLE QPoint popupPosition(QQuickItem *item, int alignment=Qt::AlignLeft) ; QPoint popupPosition(QQuickItem *item, int alignment=Qt::AlignLeft) ;
/** /**
* Set a Qt.WidgetAttribute to the dialog window * Set a Qt.WidgetAttribute to the dialog window
@ -192,6 +200,7 @@ Q_SIGNALS:
void visibleChanged(); void visibleChanged();
void activeWindowChanged(); void activeWindowChanged();
void locationChanged(); void locationChanged();
void visualParentChanged();
private Q_SLOTS: private Q_SLOTS:
void syncToMainItemSize(); void syncToMainItemSize();
@ -206,6 +215,7 @@ private:
Qt::WindowFlags m_flags; Qt::WindowFlags m_flags;
QTimer *m_syncTimer; QTimer *m_syncTimer;
QWeakPointer<QQuickItem> m_mainItem; QWeakPointer<QQuickItem> m_mainItem;
QWeakPointer<QQuickItem> m_visualParent;
DialogMargins *m_margins; DialogMargins *m_margins;
bool m_activeWindow; bool m_activeWindow;
Plasma::Location m_location; Plasma::Location m_location;

View File

@ -44,12 +44,7 @@ Item {
//windowFlags: Qt.Popup //windowFlags: Qt.Popup
color: Qt.rgba(0,0,0,0) color: Qt.rgba(0,0,0,0)
visible: plasmoid.expanded visible: plasmoid.expanded
onVisibleChanged: { visualParent: root
if (!visible) {
plasmoid.expanded = false
}
}
mainItem: Rectangle { mainItem: Rectangle {
id: appletParent id: appletParent
radius: 5 radius: 5
@ -58,5 +53,16 @@ Item {
onWidthChanged: applet.width = width onWidthChanged: applet.width = width
onHeightChanged: applet.height = height onHeightChanged: applet.height = height
} }
onActiveWindowChanged: {
if (!activeWindow) {
plasmoid.expanded = false
}
}
onVisibleChanged: {
if (!visible) {
plasmoid.expanded = false
}
}
} }
} }