From 989d699372dd5662e1a7879231eeff8d14b974f5 Mon Sep 17 00:00:00 2001 From: Thomas Frauendorfer Date: Fri, 29 Feb 2008 18:23:06 +0100 Subject: [PATCH] Make Windows attached to the Mainwindow snap to Windows they get near and move the mainwindow accordingly --- src/basewindow.cpp | 232 +++++++++++++++++++++------------- src/basewindow.h | 7 +- src/mainwindow/mainwindow.cpp | 14 +- 3 files changed, 157 insertions(+), 96 deletions(-) diff --git a/src/basewindow.cpp b/src/basewindow.cpp index 3e008a1..14abb18 100644 --- a/src/basewindow.cpp +++ b/src/basewindow.cpp @@ -92,110 +92,166 @@ BaseWindow::mouseMoveEvent (QMouseEvent *event) } QPoint -BaseWindow::snapWindow(QPoint pos, QWidgetList ignore) +BaseWindow::snapWindow(QPoint pos, AttachedWindowMap attached) { //TODO: make snapdistance configurable qint32 snapdistance = 10; - qint32 left = pos.x (); - qint32 right = left + width (); - qint32 top = pos.y (); - qint32 bottom = top + height (); - QWidgetList widgets = qApp->topLevelWidgets (); - QWidget *w; - // ignore widgets, MainWindow needs this for attached Widgets - if (!ignore.isEmpty ()) { - foreach (w, ignore) { - int i = widgets.indexOf (w); + BaseWindow *b; + widgets.removeAt (widgets.indexOf (this)); + // ignore attached widgets + // attached Widgets touch this window, and would create a strange movement + if (!attached.isEmpty ()) { + foreach (b, attached.keys ()) { + int i = widgets.indexOf (b); if (i >= 0) { widgets.removeAt (i); } } } - // snap to left or right edge - bool snappedV = false; - bool snappedH = false; - foreach (w, widgets) { - if (w == this) { - continue; - } - if (!w->isVisible ()) { - continue; - } - qint32 w_left = w->x (); - qint32 w_right = w_left + w->width (); - qint32 w_top = w->y (); - qint32 w_bottom = w_top + w->height (); - // test if we are anywhere near this widget - if ((w_top > bottom + snapdistance) || - (w_bottom < top - snapdistance) || - (w_left > right + snapdistance) || - (w_right < left - snapdistance)) { - continue; - } + bool vSnapped = false; + bool hSnapped = false; - // test if this widget can snap left or right to another widget - // and if it can, test if the tops or bottoms can also snap - if (!snappedV && (qAbs (w_left - right) < snapdistance)) { - pos.setX (w_left - width ()); - snappedV = true; - if (snappedH) { - break; + attached.insert (this, QPoint (0,0)); + BaseWindow *ref; + + // equalizerwindow and playlistwindow have only process this method once + // the ugly part comes into play, because mainwindow also snaps to + // windows it's subwindows get near. + // We iterate over the moved window and all it's attached windows. + // if a attached window can snap to a window, we use the offset of + // this windows position to the mainwindow to calculate the position + // we have to move the mainwindow to. + // + // As soon as we have a horizontal an vertical postition where the + // windows can snap to, we stop further processing + // (vSnapped and hSnapped are used to keep track of that) + foreach (ref, attached.keys ()) { + qint32 left = pos.x () + attached[ref].x (); + qint32 right = left + ref->width (); + qint32 top = pos.y () + attached[ref].y (); + qint32 bottom = top + ref->height (); + + QWidget *w; + + // snap to left or right edge + foreach (w, widgets) { + if (!w->isVisible ()) { + continue; } - if (qAbs (w_bottom - bottom) < snapdistance) { - pos.setY (w_bottom - height ()); - break; - } else if (qAbs (w_top - top) < snapdistance) { - pos.setY (w_top); - break; - } - } else if (!snappedV && (qAbs (left - w_right) < snapdistance)) { - pos.setX (w_right); - snappedV = true; - if (snappedH) { - break; - } - if (qAbs (w_bottom - bottom) < snapdistance) { - pos.setY (w_bottom - height ()); - break; - } else if (qAbs (w_top - top) < snapdistance) { - pos.setY (w_top); - break; - } - } - // test if this widget can snap to top or bottom of another widget - // and if it can, test if the left or right edges also can - if (!snappedH && (qAbs (top - w_bottom) < snapdistance)) { - pos.setY (w_bottom); - snappedH = true; - if (snappedV) { - break; - } - if (qAbs (w_left - left) < snapdistance) { - pos.setX (w_left); - break; - } else if (qAbs (w_right - right) < snapdistance) { - pos.setX (w_right - width ()); - break; - } - } else if (!snappedH && (qAbs (w_top - bottom) < snapdistance)) { - pos.setY (w_top - height ()); - snappedH = true; - if (snappedV) { - break; - } - if (qAbs (w_left - left) < snapdistance) { - pos.setX (w_left); - break; - } else if (qAbs (w_right - right) < snapdistance) { - pos.setX (w_right - width ()); - break; + qint32 w_left = w->x (); + qint32 w_right = w_left + w->width (); + qint32 w_top = w->y (); + qint32 w_bottom = w_top + w->height (); + // test if we are anywhere near this widget + if ((w_top > bottom + snapdistance) || + (w_bottom < top - snapdistance) || + (w_left > right + snapdistance) || + (w_right < left - snapdistance)) { + continue; } + // test if this widget can snap left or right to another widget + // and if it can, test if the tops or bottoms can also snap + if (!vSnapped && (qAbs (w_left - right) < snapdistance)) { + pos.setX (w_left - ref->width () - attached[ref].x ()); + vSnapped = true; + if (hSnapped) { + break; + } + if (qAbs (w_bottom - bottom) < snapdistance) { + pos.setY (w_bottom - ref->height () - attached[ref].y ()); + hSnapped = true; + break; + } else if (qAbs (w_top - top) < snapdistance) { + pos.setY (w_top - attached[ref].y ()); + hSnapped = true; + break; + } + } else if (!vSnapped && (qAbs (left - w_right) < snapdistance)) { + pos.setX (w_right - attached[ref].x ()); + vSnapped = true; + if (hSnapped) { + break; + } + if (qAbs (w_bottom - bottom) < snapdistance) { + pos.setY (w_bottom - ref->height () - attached[ref].y ()); + hSnapped = true; + break; + } else if (qAbs (w_top - top) < snapdistance) { + pos.setY (w_top - attached[ref].y ()); + hSnapped = true; + break; + } + } + // test if this widget can snap to top or bottom of another widget + // and if it can, test if the left or right edges also can + if ((!hSnapped) && (qAbs (top - w_bottom) < snapdistance)) { + pos.setY (w_bottom - attached[ref].y ()); + hSnapped = true; + if (vSnapped) { + break; + } + if (qAbs (w_left - left) < snapdistance) { + pos.setX (w_left - attached[ref].x ()); + vSnapped = true; + break; + } else if (qAbs (w_right - right) < snapdistance) { + pos.setX (w_right - ref->width () - attached[ref].x ()); + vSnapped = true; + break; + } + } else if ((!hSnapped) && (qAbs (w_top - bottom) < snapdistance)) { + pos.setY (w_top - ref->height () - attached[ref].y ()); + hSnapped = true; + if (vSnapped) { + break; + } + if (qAbs (w_left - left) < snapdistance) { + pos.setX (w_left - attached[ref].x ()); + vSnapped = true; + break; + } else if (qAbs (w_right - right) < snapdistance) { + pos.setX (w_right - ref->width () - attached[ref].x ()); + vSnapped = true; + break; + } + + } + } // end foreach (w, widgets) + + if (hSnapped && vSnapped) { + break; } - } + } // end foreach (ref, attached) return pos; } + +/* + if (!widgets.isEmpty ()) { + QPoint ret = testSnapWindow (this, pos, widgets); + // test is attached Windows can snap to a unattached window + if (((ret.x () == -1) || (ret.y () == -1)) && (!attached.isEmpty ())) { + QPoint tmp; + foreach (w, attached.keys ()) { + tmp = testSnapWindow (w, pos + attached[w], widgets); + if ((ret.x () == -1) && (tmp.x () > -1)) { + ret.setX (tmp.x () - attached[w].x ()); + } + if ((ret.y () == -1) && (tmp.y () > -1)) { + ret.setY (tmp.y () - attached[w]. y()); + } + ret = mergePoint (ret, tmp); + if ((ret.x () > -1) && (ret.y () > -1)) { + break; + } + } + } + // Subwindows didn't provide snap target for x and y axis: + ret = mergePoint (ret, pos); + return ret; + } +*/ diff --git a/src/basewindow.h b/src/basewindow.h index a47deb6..58ad211 100644 --- a/src/basewindow.h +++ b/src/basewindow.h @@ -18,11 +18,16 @@ #define __BASEWINDOW_H__ #include +#include +#include class QMouseEvent; class QPoint; class MainWindow; +class BaseWindow; +typedef QMap AttachedWindowMap; + class BaseWindow : public QMainWindow { Q_OBJECT @@ -37,7 +42,7 @@ class BaseWindow : public QMainWindow { void mouseReleaseEvent (QMouseEvent *event); void mouseMoveEvent (QMouseEvent *event); - QPoint snapWindow (QPoint pos, QWidgetList ignore = QWidgetList()); + QPoint snapWindow (QPoint pos, AttachedWindowMap attached = AttachedWindowMap()); QPoint m_diff; }; diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp index 7ecb19f..26be404 100644 --- a/src/mainwindow/mainwindow.cpp +++ b/src/mainwindow/mainwindow.cpp @@ -132,12 +132,12 @@ void MainWindow::mouseMoveEvent (QMouseEvent *event) { if ((event->buttons () & Qt::LeftButton) && !m_diff.isNull ()) { - QWidgetList ignore; - QWidget *w; - foreach (w, m_attachedWidgets.keys ()) { - ignore.append (w); - } - move (snapWindow (event->globalPos() - m_diff, ignore)); + // QWidgetList attached; + // QWidget *w; + // foreach (w, m_attachedWidgets.keys ()) { + // attached.append (w); + // } + move (snapWindow (event->globalPos() - m_diff, m_attachedWidgets)); } } @@ -169,7 +169,7 @@ MainWindow::attachWidgets () if (w == this) { continue; } - if (w->inherits ("BaseWindow")) { + if ((w->inherits ("BaseWindow")) && (w->isVisible ())) { widgets.append (qobject_cast (w)); } }