Make Windows attached to the Mainwindow snap to Windows they get near and move the mainwindow accordingly
This commit is contained in:
parent
553138578d
commit
989d699372
3 changed files with 157 additions and 96 deletions
|
@ -92,35 +92,52 @@ BaseWindow::mouseMoveEvent (QMouseEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint
|
QPoint
|
||||||
BaseWindow::snapWindow(QPoint pos, QWidgetList ignore)
|
BaseWindow::snapWindow(QPoint pos, AttachedWindowMap attached)
|
||||||
{
|
{
|
||||||
//TODO: make snapdistance configurable
|
//TODO: make snapdistance configurable
|
||||||
qint32 snapdistance = 10;
|
qint32 snapdistance = 10;
|
||||||
|
|
||||||
qint32 left = pos.x ();
|
|
||||||
qint32 right = left + width ();
|
|
||||||
qint32 top = pos.y ();
|
|
||||||
qint32 bottom = top + height ();
|
|
||||||
|
|
||||||
QWidgetList widgets = qApp->topLevelWidgets ();
|
QWidgetList widgets = qApp->topLevelWidgets ();
|
||||||
QWidget *w;
|
BaseWindow *b;
|
||||||
// ignore widgets, MainWindow needs this for attached Widgets
|
widgets.removeAt (widgets.indexOf (this));
|
||||||
if (!ignore.isEmpty ()) {
|
// ignore attached widgets
|
||||||
foreach (w, ignore) {
|
// attached Widgets touch this window, and would create a strange movement
|
||||||
int i = widgets.indexOf (w);
|
if (!attached.isEmpty ()) {
|
||||||
|
foreach (b, attached.keys ()) {
|
||||||
|
int i = widgets.indexOf (b);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
widgets.removeAt (i);
|
widgets.removeAt (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vSnapped = false;
|
||||||
|
bool hSnapped = false;
|
||||||
|
|
||||||
|
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
|
// snap to left or right edge
|
||||||
bool snappedV = false;
|
|
||||||
bool snappedH = false;
|
|
||||||
foreach (w, widgets) {
|
foreach (w, widgets) {
|
||||||
if (w == this) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!w->isVisible ()) {
|
if (!w->isVisible ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -138,64 +155,103 @@ BaseWindow::snapWindow(QPoint pos, QWidgetList ignore)
|
||||||
|
|
||||||
// test if this widget can snap left or right to another widget
|
// 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
|
// and if it can, test if the tops or bottoms can also snap
|
||||||
if (!snappedV && (qAbs (w_left - right) < snapdistance)) {
|
if (!vSnapped && (qAbs (w_left - right) < snapdistance)) {
|
||||||
pos.setX (w_left - width ());
|
pos.setX (w_left - ref->width () - attached[ref].x ());
|
||||||
snappedV = true;
|
vSnapped = true;
|
||||||
if (snappedH) {
|
if (hSnapped) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (qAbs (w_bottom - bottom) < snapdistance) {
|
if (qAbs (w_bottom - bottom) < snapdistance) {
|
||||||
pos.setY (w_bottom - height ());
|
pos.setY (w_bottom - ref->height () - attached[ref].y ());
|
||||||
|
hSnapped = true;
|
||||||
break;
|
break;
|
||||||
} else if (qAbs (w_top - top) < snapdistance) {
|
} else if (qAbs (w_top - top) < snapdistance) {
|
||||||
pos.setY (w_top);
|
pos.setY (w_top - attached[ref].y ());
|
||||||
|
hSnapped = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!snappedV && (qAbs (left - w_right) < snapdistance)) {
|
} else if (!vSnapped && (qAbs (left - w_right) < snapdistance)) {
|
||||||
pos.setX (w_right);
|
pos.setX (w_right - attached[ref].x ());
|
||||||
snappedV = true;
|
vSnapped = true;
|
||||||
if (snappedH) {
|
if (hSnapped) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (qAbs (w_bottom - bottom) < snapdistance) {
|
if (qAbs (w_bottom - bottom) < snapdistance) {
|
||||||
pos.setY (w_bottom - height ());
|
pos.setY (w_bottom - ref->height () - attached[ref].y ());
|
||||||
|
hSnapped = true;
|
||||||
break;
|
break;
|
||||||
} else if (qAbs (w_top - top) < snapdistance) {
|
} else if (qAbs (w_top - top) < snapdistance) {
|
||||||
pos.setY (w_top);
|
pos.setY (w_top - attached[ref].y ());
|
||||||
|
hSnapped = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// test if this widget can snap to top or bottom of another widget
|
// 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
|
// and if it can, test if the left or right edges also can
|
||||||
if (!snappedH && (qAbs (top - w_bottom) < snapdistance)) {
|
if ((!hSnapped) && (qAbs (top - w_bottom) < snapdistance)) {
|
||||||
pos.setY (w_bottom);
|
pos.setY (w_bottom - attached[ref].y ());
|
||||||
snappedH = true;
|
hSnapped = true;
|
||||||
if (snappedV) {
|
if (vSnapped) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (qAbs (w_left - left) < snapdistance) {
|
if (qAbs (w_left - left) < snapdistance) {
|
||||||
pos.setX (w_left);
|
pos.setX (w_left - attached[ref].x ());
|
||||||
|
vSnapped = true;
|
||||||
break;
|
break;
|
||||||
} else if (qAbs (w_right - right) < snapdistance) {
|
} else if (qAbs (w_right - right) < snapdistance) {
|
||||||
pos.setX (w_right - width ());
|
pos.setX (w_right - ref->width () - attached[ref].x ());
|
||||||
|
vSnapped = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!snappedH && (qAbs (w_top - bottom) < snapdistance)) {
|
} else if ((!hSnapped) && (qAbs (w_top - bottom) < snapdistance)) {
|
||||||
pos.setY (w_top - height ());
|
pos.setY (w_top - ref->height () - attached[ref].y ());
|
||||||
snappedH = true;
|
hSnapped = true;
|
||||||
if (snappedV) {
|
if (vSnapped) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (qAbs (w_left - left) < snapdistance) {
|
if (qAbs (w_left - left) < snapdistance) {
|
||||||
pos.setX (w_left);
|
pos.setX (w_left - attached[ref].x ());
|
||||||
|
vSnapped = true;
|
||||||
break;
|
break;
|
||||||
} else if (qAbs (w_right - right) < snapdistance) {
|
} else if (qAbs (w_right - right) < snapdistance) {
|
||||||
pos.setX (w_right - width ());
|
pos.setX (w_right - ref->width () - attached[ref].x ());
|
||||||
|
vSnapped = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} // end foreach (w, widgets)
|
||||||
|
|
||||||
|
if (hSnapped && vSnapped) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
} // end foreach (ref, attached)
|
||||||
|
|
||||||
return pos;
|
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;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -18,11 +18,16 @@
|
||||||
#define __BASEWINDOW_H__
|
#define __BASEWINDOW_H__
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QMap>
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QPoint;
|
class QPoint;
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
|
||||||
|
class BaseWindow;
|
||||||
|
typedef QMap<BaseWindow *, QPoint> AttachedWindowMap;
|
||||||
|
|
||||||
class BaseWindow : public QMainWindow {
|
class BaseWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -37,7 +42,7 @@ class BaseWindow : public QMainWindow {
|
||||||
void mouseReleaseEvent (QMouseEvent *event);
|
void mouseReleaseEvent (QMouseEvent *event);
|
||||||
void mouseMoveEvent (QMouseEvent *event);
|
void mouseMoveEvent (QMouseEvent *event);
|
||||||
|
|
||||||
QPoint snapWindow (QPoint pos, QWidgetList ignore = QWidgetList());
|
QPoint snapWindow (QPoint pos, AttachedWindowMap attached = AttachedWindowMap());
|
||||||
QPoint m_diff;
|
QPoint m_diff;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -132,12 +132,12 @@ void
|
||||||
MainWindow::mouseMoveEvent (QMouseEvent *event)
|
MainWindow::mouseMoveEvent (QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if ((event->buttons () & Qt::LeftButton) && !m_diff.isNull ()) {
|
if ((event->buttons () & Qt::LeftButton) && !m_diff.isNull ()) {
|
||||||
QWidgetList ignore;
|
// QWidgetList attached;
|
||||||
QWidget *w;
|
// QWidget *w;
|
||||||
foreach (w, m_attachedWidgets.keys ()) {
|
// foreach (w, m_attachedWidgets.keys ()) {
|
||||||
ignore.append (w);
|
// attached.append (w);
|
||||||
}
|
// }
|
||||||
move (snapWindow (event->globalPos() - m_diff, ignore));
|
move (snapWindow (event->globalPos() - m_diff, m_attachedWidgets));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ MainWindow::attachWidgets ()
|
||||||
if (w == this) {
|
if (w == this) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (w->inherits ("BaseWindow")) {
|
if ((w->inherits ("BaseWindow")) && (w->isVisible ())) {
|
||||||
widgets.append (qobject_cast<BaseWindow *> (w));
|
widgets.append (qobject_cast<BaseWindow *> (w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue