mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Move tiles on HomeWindow
More work to support moving tiles on HomeWindow. This update adds tile movement and 'pushing' other tiles out the way as you move them around. Tile ordering/positioning is still todo, but this introduces the visual feedback during a move for the user.
This commit is contained in:
@@ -99,6 +99,16 @@ bool GcWindow::resizable() const
|
||||
return _resizable;
|
||||
}
|
||||
|
||||
void GcWindow::setGripped(bool x)
|
||||
{
|
||||
_gripped = x;
|
||||
}
|
||||
|
||||
bool GcWindow::gripped() const
|
||||
{
|
||||
return _gripped;
|
||||
}
|
||||
|
||||
GcWindow::GcWindow()
|
||||
{
|
||||
}
|
||||
@@ -251,8 +261,8 @@ GcWindow::mousePressEvent(QMouseEvent *e)
|
||||
oHeightFactor = heightFactor();
|
||||
oX = pos().x();
|
||||
oY = pos().y();
|
||||
mX = e->globalX();
|
||||
mY = e->globalY();
|
||||
mX = mapFromGlobal(QCursor::pos()).x();
|
||||
mY = mapFromGlobal(QCursor::pos()).y();
|
||||
|
||||
setDragState(h); // set drag state then!
|
||||
|
||||
@@ -262,6 +272,20 @@ GcWindow::mousePressEvent(QMouseEvent *e)
|
||||
void
|
||||
GcWindow::mouseReleaseEvent(QMouseEvent *)
|
||||
{
|
||||
// tell the owner!
|
||||
if (dragState == Move) {
|
||||
setProperty("gripped", false);
|
||||
emit moved(this);
|
||||
} else if (dragState == Left ||
|
||||
dragState == Right ||
|
||||
dragState == Top ||
|
||||
dragState == Bottom ||
|
||||
dragState == TLCorner ||
|
||||
dragState == TRCorner ||
|
||||
dragState == BLCorner ||
|
||||
dragState == BRCorner) {
|
||||
emit resized(this);
|
||||
}
|
||||
setDragState(None);
|
||||
repaint();
|
||||
}
|
||||
@@ -306,14 +330,15 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
}
|
||||
|
||||
// work out the relative move x and y
|
||||
int relx = e->globalX() - mX;
|
||||
int rely = e->globalY() - mY;
|
||||
int relx = mapFromGlobal(QCursor::pos()).x() - mX;
|
||||
int rely = mapFromGlobal(QCursor::pos()).y() - mY;
|
||||
|
||||
switch (dragState) {
|
||||
|
||||
default:
|
||||
case Move :
|
||||
move(oX + relx, oY + rely);
|
||||
emit moving(this);
|
||||
break;
|
||||
|
||||
case TLCorner :
|
||||
@@ -325,6 +350,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
if (newWidth > 30 && newHeight > 30) {
|
||||
move(oX + relx, oY + rely);
|
||||
setNewSize(newWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -338,6 +364,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
if (newWidth > 30 && newHeight > 30) {
|
||||
move(oX, oY + rely);
|
||||
setNewSize(newWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -351,6 +378,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
if (newWidth > 30 && newHeight > 30) {
|
||||
move(oX + relx, oY);
|
||||
setNewSize(newWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -363,6 +391,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
// need to move and resize
|
||||
if (newWidth > 30 && newHeight > 30) {
|
||||
setNewSize(newWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -375,6 +404,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
if (newHeight > 30) {
|
||||
move (oX, oY + rely);
|
||||
setNewSize(oWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -386,6 +416,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
// need to move and resize
|
||||
if (newHeight > 30) {
|
||||
setNewSize(oWidth, newHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -398,6 +429,7 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
if (newWidth > 30) {
|
||||
move (oX + relx, oY);
|
||||
setNewSize(newWidth, oHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -409,11 +441,14 @@ GcWindow::mouseMoveEvent(QMouseEvent *e)
|
||||
// need to move and resize
|
||||
if (newWidth > 30) {
|
||||
setNewSize(newWidth, oHeight);
|
||||
emit resizing(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
oX = pos().x();
|
||||
oY = pos().y();
|
||||
//repaint();
|
||||
//QApplication::processEvents(); // flicker...
|
||||
}
|
||||
@@ -440,6 +475,7 @@ void
|
||||
GcWindow::setDragState(DragState d)
|
||||
{
|
||||
dragState = d;
|
||||
setProperty("gripped", dragState == Move ? true : false);
|
||||
setCursorShape(d);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ private:
|
||||
|
||||
// can be resized
|
||||
Q_PROPERTY(bool resizable READ resizable WRITE setResizable USER true);
|
||||
Q_PROPERTY(bool gripped READ gripped WRITE setGripped);
|
||||
|
||||
QWidget *_controls;
|
||||
QString _title;
|
||||
@@ -79,6 +80,7 @@ private:
|
||||
double _widthFactor;
|
||||
double _heightFactor;
|
||||
bool _resizable;
|
||||
bool _gripped;
|
||||
|
||||
// we paint a heading if there is space in the top margin
|
||||
void paintEvent (QPaintEvent * event);
|
||||
@@ -96,6 +98,10 @@ signals:
|
||||
void rideItemChanged(RideItem*);
|
||||
void heightFactorChanged(double);
|
||||
void widthFactorChanged(double);
|
||||
void resizing(GcWindow*);
|
||||
void moving(GcWindow*);
|
||||
void resized(GcWindow*); // finished resizing
|
||||
void moved(GcWindow*); // finished moving
|
||||
|
||||
public:
|
||||
|
||||
@@ -125,11 +131,17 @@ public:
|
||||
void setResizable(bool);
|
||||
bool resizable() const;
|
||||
|
||||
void setGripped(bool);
|
||||
bool gripped() const;
|
||||
|
||||
GcWinID type() const { return _type; }
|
||||
void setType(GcWinID x) { _type = x; } // only really used by the window registry
|
||||
|
||||
virtual bool amVisible();
|
||||
|
||||
// for sorting... we look at x
|
||||
bool operator< (GcWindow right) const { return geometry().x() < right.geometry().x(); }
|
||||
|
||||
// mouse actions -- resizing and dragging tiles
|
||||
bool eventFilter(QObject *object, QEvent *e);
|
||||
virtual void mousePressEvent(QMouseEvent *);
|
||||
|
||||
@@ -379,6 +379,12 @@ HomeWindow::addChart(GcWindow* newone)
|
||||
// add to the list
|
||||
charts.append(newone);
|
||||
newone->hide();
|
||||
|
||||
// watch for moves etc
|
||||
connect(newone, SIGNAL(resizing(GcWindow*)), this, SLOT(windowResizing(GcWindow*)));
|
||||
connect(newone, SIGNAL(moving(GcWindow*)), this, SLOT(windowMoving(GcWindow*)));
|
||||
connect(newone, SIGNAL(resized(GcWindow*)), this, SLOT(windowResized(GcWindow*)));
|
||||
connect(newone, SIGNAL(moved(GcWindow*)), this, SLOT(windowMoved(GcWindow*)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +462,7 @@ HomeWindow::resizeEvent(QResizeEvent *e)
|
||||
- ((widthFactor-1) * 20) /* internal spacing */
|
||||
) / widthFactor;
|
||||
|
||||
double newheight = (winArea->height()
|
||||
double newheight = (winArea->height()
|
||||
- 40 /* top and bottom marings */
|
||||
- ((heightFactor-1) * 20) /* internal spacing */
|
||||
) / heightFactor;
|
||||
@@ -550,6 +556,167 @@ HomeWindow::eventFilter(QObject *object, QEvent *e)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::windowMoved(GcWindow*w)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::windowResized(GcWindow*w)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::windowMoving(GcWindow*w)
|
||||
{
|
||||
// ensure the mouse pointer is visible
|
||||
QPoint pos = winWidget->mapFromGlobal(QCursor::pos());
|
||||
winArea->ensureVisible(pos.x(), pos.y(), 20, 20);
|
||||
|
||||
// since the widget has moved, the mouse is no longer
|
||||
// in the same position relevant to the widget, so
|
||||
// move the mouse back to the same position relevant
|
||||
// to the widget
|
||||
QCursor::setPos(winWidget->mapToGlobal(pos));
|
||||
|
||||
// Move the other windows out the way...
|
||||
for(int i=0; i<charts.count(); i++) {
|
||||
if (charts[i] != w && !charts[i]->gripped() && charts[i]->geometry().intersects(w->geometry())) {
|
||||
// shift whilst we move then
|
||||
QRect inter = charts[i]->geometry().intersected(w->geometry());
|
||||
// move left
|
||||
if (charts[i]->geometry().x() < w->geometry().x()) {
|
||||
int newx = inter.x() - 20 - charts[i]->geometry().width();
|
||||
if (charts[i]->geometry().x() > newx)
|
||||
charts[i]->move(newx, charts[i]->geometry().y());
|
||||
} else {
|
||||
int newx = inter.x()+inter.width() + 20;
|
||||
if (charts[i]->geometry().x() < newx)
|
||||
charts[i]->move(newx, charts[i]->geometry().y());
|
||||
}
|
||||
windowMoving(charts[i]); // move the rest...
|
||||
}
|
||||
}
|
||||
|
||||
// now if any are off the screen try and get them
|
||||
// back on the screen without disturbing the other
|
||||
// charts (unless they are off the screen too)
|
||||
for(int i=0; i<charts.count(); i++) {
|
||||
|
||||
if (!charts[i]->gripped() && (charts[i]->x() < 20 || (charts[i]->x()+charts[i]->width()) > winArea->geometry().width())) {
|
||||
|
||||
// to the left...
|
||||
if (charts[i]->geometry().x() < 20) {
|
||||
|
||||
QRect back(20, charts[i]->geometry().y(),
|
||||
charts[i]->geometry().width(),
|
||||
charts[i]->geometry().height());
|
||||
|
||||
// loop through the other charts and see
|
||||
// how far it can sneak back on...
|
||||
for(int j=0; j<charts.count(); j++) {
|
||||
if (charts[j] != charts[i]) {
|
||||
if (back.intersects(charts[j]->geometry())) {
|
||||
QRect inter = back.intersected(charts[j]->geometry());
|
||||
int newx = inter.x() - back.width() - 20;
|
||||
if (back.x() > newx) {
|
||||
back.setX(newx);
|
||||
back.setWidth(charts[i]->width());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// any space?
|
||||
if (back.x() < 20) {
|
||||
// we're still off screen so
|
||||
// lets shift all the windows to the
|
||||
// right if we can
|
||||
QList<GcWindow*> obstacles;
|
||||
QRect fback(20, charts[i]->geometry().y(),
|
||||
charts[i]->geometry().width(),
|
||||
charts[i]->geometry().height());
|
||||
|
||||
|
||||
// order obstacles left to right
|
||||
for(int j=0; j<charts.count(); j++) {
|
||||
if (charts[j] != charts[i] &&
|
||||
fback.intersects(charts[j]->geometry()))
|
||||
obstacles.append(charts[j]);
|
||||
qSort(obstacles);
|
||||
}
|
||||
|
||||
// where to stop? all or is the
|
||||
// gripped window in there
|
||||
// or stop if offscreen already
|
||||
int stop=0;
|
||||
while (stop < obstacles.count()) {
|
||||
if (obstacles[stop]->gripped() ||
|
||||
(obstacles[stop]->geometry().x() + obstacles[stop]->width()) > winArea->width())
|
||||
break;
|
||||
stop++;
|
||||
}
|
||||
|
||||
// at this point we know that members
|
||||
// 0 - stop are possibly in our way
|
||||
// we need to move the leftmost, if it
|
||||
// fits we stop, if not we move the next one
|
||||
// and the leftmost, then the next one
|
||||
// until we have exhausted all candidates
|
||||
|
||||
// try again!
|
||||
// loop through the other charts and see
|
||||
// how far it can sneak back on...
|
||||
back = QRect(20, charts[i]->geometry().y(),
|
||||
charts[i]->geometry().width(),
|
||||
charts[i]->geometry().height());
|
||||
for(int j=0; j<charts.count(); j++) {
|
||||
if (charts[j] != charts[i]) {
|
||||
if (back.intersects(charts[j]->geometry())) {
|
||||
QRect inter = back.intersected(charts[j]->geometry());
|
||||
back.setX(inter.x()-back.width()-20);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
charts[i]->move(back.x(), back.y());
|
||||
|
||||
} else {
|
||||
|
||||
QRect back(winArea->width() - charts[i]->width() - 20,
|
||||
charts[i]->geometry().y(),
|
||||
charts[i]->geometry().width(),
|
||||
charts[i]->geometry().height());
|
||||
|
||||
// loop through the other charts and see
|
||||
// how far it can sneak back on...
|
||||
for(int j=0; j<charts.count(); j++) {
|
||||
if (charts[j] != charts[i]) {
|
||||
if (back.intersects(charts[j]->geometry())) {
|
||||
QRect inter = back.intersected(charts[j]->geometry());
|
||||
int newx = inter.x() + inter.width() + 20;
|
||||
if (back.x() < newx) back.setX(newx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// any space?
|
||||
charts[i]->move(back.x(), back.y());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::windowResizing(GcWindow*w)
|
||||
{
|
||||
QPoint pos = this->mapFromGlobal(QCursor::pos());
|
||||
winArea->ensureVisible(pos.x(), pos.y(), 20, 20);
|
||||
}
|
||||
|
||||
GcWindowDialog::GcWindowDialog(GcWinID type, MainWindow *mainWindow) : mainWindow(mainWindow), type(type)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
@@ -830,4 +997,3 @@ bool ViewParser::endDocument()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,12 @@ class HomeWindow : public GcWindow
|
||||
//notifiction that been made visible
|
||||
void selected();
|
||||
|
||||
// moved or resized
|
||||
void windowMoving(GcWindow*);
|
||||
void windowResizing(GcWindow*);
|
||||
void windowMoved(GcWindow*);
|
||||
void windowResized(GcWindow*);
|
||||
|
||||
protected:
|
||||
MainWindow *mainWindow;
|
||||
bool active; // ignore gui signals when changing views
|
||||
|
||||
Reference in New Issue
Block a user