diff --git a/src/GcWindowLayout.cpp b/src/GcWindowLayout.cpp index 464c05bf3..f0d376533 100644 --- a/src/GcWindowLayout.cpp +++ b/src/GcWindowLayout.cpp @@ -43,6 +43,12 @@ void GcWindowLayout::addItem(QLayoutItem *item) itemList.append(item); } +void GcWindowLayout::insert(int index, QWidget *widget) +{ + addChildWidget(widget); + itemList.insert(index, new QWidgetItem(widget)); +} + int GcWindowLayout::horizontalSpacing() const { if (m_hSpace >= 0) { diff --git a/src/GcWindowLayout.h b/src/GcWindowLayout.h index f7e55688d..17e243f95 100644 --- a/src/GcWindowLayout.h +++ b/src/GcWindowLayout.h @@ -36,6 +36,8 @@ public: ~GcWindowLayout(); void addItem(QLayoutItem *item); + void insert(int index, QWidget *item); + int horizontalSpacing() const; int verticalSpacing() const; Qt::Orientations expandingDirections() const; @@ -49,8 +51,8 @@ public: QLayoutItem *takeAt(int index); private: - int doLayout(const QRect &rect, bool testOnly) const; int smartSpacing(QStyle::PixelMetric pm) const; + int doLayout(const QRect &rect, bool testOnly) const; QList itemList; int m_hSpace; diff --git a/src/GoldenCheetah.cpp b/src/GoldenCheetah.cpp index 0b3cf76aa..cf4036434 100644 --- a/src/GoldenCheetah.cpp +++ b/src/GoldenCheetah.cpp @@ -337,7 +337,8 @@ GcWindow::mouseMoveEvent(QMouseEvent *e) default: case Move : - move(oX + relx, oY + rely); + //move(oX + relx, oY + rely); + setCursor(Qt::DragMoveCursor); emit moving(this); break; diff --git a/src/GoldenCheetah.h b/src/GoldenCheetah.h index 0e4e6f5d4..44ab96f71 100644 --- a/src/GoldenCheetah.h +++ b/src/GoldenCheetah.h @@ -82,8 +82,6 @@ private: bool _resizable; bool _gripped; - // we paint a heading if there is space in the top margin - void paintEvent (QPaintEvent * event); enum drag { None, Close, Flip, Move, Left, Right, Top, Bottom, TLCorner, TRCorner, BLCorner, BRCorner }; typedef enum drag DragState; // state data for resizing tiles @@ -142,6 +140,9 @@ public: // for sorting... we look at x bool operator< (GcWindow right) const { return geometry().x() < right.geometry().x(); } + // we paint a heading if there is space in the top margin + void paintEvent (QPaintEvent * event); + // mouse actions -- resizing and dragging tiles bool eventFilter(QObject *object, QEvent *e); virtual void mousePressEvent(QMouseEvent *); diff --git a/src/HomeWindow.cpp b/src/HomeWindow.cpp index 417e24d9f..2993ac6ff 100644 --- a/src/HomeWindow.cpp +++ b/src/HomeWindow.cpp @@ -21,7 +21,7 @@ #include "LTMSettings.h" HomeWindow::HomeWindow(MainWindow *mainWindow) : - GcWindow(mainWindow), mainWindow(mainWindow), active(false), clicked(NULL) + GcWindow(mainWindow), mainWindow(mainWindow), active(false), clicked(NULL), dropPending(false), chartCursor(-2) { setInstanceName("Home Window"); setControls(new QStackedWidget(this)); @@ -98,8 +98,6 @@ HomeWindow::HomeWindow(MainWindow *mainWindow) : winWidget = new QWidget(this); winWidget->setContentsMargins(0,0,0,0); winWidget->setPalette(palette); - //tileWidget->setMouseTracking(true); - //tileWidget->installEventFilter(this); winFlow = new GcWindowLayout(winWidget, 0, 20, 20); winFlow->setContentsMargins(20,20,20,20); @@ -110,6 +108,8 @@ HomeWindow::HomeWindow(MainWindow *mainWindow) : winArea->setFrameStyle(QFrame::NoFrame); winArea->setContentsMargins(0,0,0,0); style->addWidget(winArea); + winWidget->installEventFilter(this); // to draw cursor + winWidget->setMouseTracking(true); // to draw cursor currentStyle=2; #ifdef Q_OS_MAC @@ -130,6 +130,10 @@ HomeWindow::HomeWindow(MainWindow *mainWindow) : #endif restoreState(); + + // watch drop operations + //setMouseTracking(true); + installEventFilter(this); } HomeWindow::~HomeWindow() @@ -270,8 +274,10 @@ HomeWindow::styleChanged(int id) void HomeWindow::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->formats().contains("application/x-qabstractitemmodeldatalist")) + if (event->mimeData()->formats().contains("application/x-qabstractitemmodeldatalist")) { event->accept(); + dropPending = true; + } } void @@ -281,6 +287,8 @@ HomeWindow::dropEvent(QDropEvent *event) model.dropMimeData(event->mimeData(), Qt::CopyAction, 0,0, QModelIndex()); QString chart = model.data(model.index(0,0), Qt::DisplayRole).toString(); + dropPending = false; + // which one am i? for (int i = 0; GcWindows[i].id != GcWindowTypes::None; i++) { if (GcWindows[i].name == chart) { @@ -296,12 +304,21 @@ HomeWindow::dropEvent(QDropEvent *event) addChart(newone); newone->show(); } + + // before we return lets turn the cursor off + chartCursor = -2; + winWidget->repaint(); return; } } // nope not one of ours event->ignore(); + + // turn off cursor + chartCursor = -2; + winWidget->repaint(); + return; } @@ -317,7 +334,11 @@ HomeWindow::addChart(GcWindow* newone) QWidget *x = dynamic_cast(newone)->controls(); QWidget *c = (x != NULL) ? x : new QWidget(this); - m->addWidget(c); + + if (chartCursor >= 0) + m->insertWidget(chartCursor, c); + else + m->addWidget(c); // watch for enter events! newone->installEventFilter(this); @@ -372,12 +393,15 @@ HomeWindow::addChart(GcWindow* newone) else newone->setFixedHeight(newheight); newone->setContentsMargins(0,15,0,0); newone->setResizable(true); // we need to show on tab selection! - winFlow->addWidget(newone); + + if (chartCursor >= 0) winFlow->insert(chartCursor, newone); + else winFlow->addWidget(newone); } break; } // add to the list - charts.append(newone); + if (chartCursor >= 0) charts.insert(chartCursor, newone); + else charts.append(newone); newone->hide(); // watch for moves etc @@ -485,6 +509,29 @@ HomeWindow::resizeEvent(QResizeEvent *e) bool HomeWindow::eventFilter(QObject *object, QEvent *e) { + // we watch the mouse when + // dropping charts, to update + // the cursor position + // dropping and mouse move? + if (object == this) { + if (dropPending == true && e->type() == QEvent::DragMove) { + QPoint pos = winWidget->mapFromGlobal(QCursor::pos()); + winArea->ensureVisible(pos.x(), pos.y(), 20, 20); + chartCursor = pointTile(pos); + winWidget->repaint(); // show cursor + } + return false; + } + + // draw a cursor when winWidget paint event kicks off + if (object == winWidget) { + if (e->type() == QEvent::Paint) drawCursor(); + return false; + } + + // From here on, we're looking at events + // from the charts... + // is it a mouse enter event? if (e->type() == QEvent::Enter) { @@ -556,10 +603,108 @@ HomeWindow::eventFilter(QObject *object, QEvent *e) return false; } +// which tile to place before, -1 means append +int +HomeWindow::pointTile(QPoint pos) +{ + // find the window that is to the right of + // the drop point + + // is the cursor above a widget? + int i; + int here = -1; // chart number to the right of cursor... + for (i=0; igeometry().contains(pos)) { + here = i; + break; + } + } + + // is it to the right? + if (here == -1) { + + int toRight = pos.x(); + while (here == -1 && toRight < winArea->width()) { + toRight += 20; + QPoint right = QPoint(toRight, pos.y()); + for (i=0; igeometry().contains(right)) { + here = i; + break; + } + } + } + } + + // is it to the left? + if (here == -1) { + + int toLeft = pos.x(); + while (here == -1 && toLeft > 0) { + toLeft -= 20; + QPoint left = QPoint(toLeft, pos.y()); + for (i=0; igeometry().contains(left)) { + here = i+1; + break; + } + } + } + } + + // well it must be below, so if there is + // anything at y+20, use that, otherwise + // we can assume we are at the end and + // append to the list... + if (here == -1) { + QPoint below(20, pos.y()+20); + for (i=0; igeometry().contains(below)) { + here = i; + break; + } + } + } + + // all done + if (here == -1 || here >= charts.count()) return -1; + return here; +} + void HomeWindow::windowMoved(GcWindow*w) { + // now drop at the cursor + if (currentStyle == 2) { + // go find... + int before=0; + for (;before < charts.count(); before++) { + if (charts[before] == w) { + QWidget *m = winFlow->takeAt(before)->widget(); + QWidget *c = dynamic_cast(controls())->widget(before); + dynamic_cast(controls())->removeWidget(c); + QWidget *l = charts.takeAt(before); + if (chartCursor > before) chartCursor--; + if (chartCursor >= 0) { + dynamic_cast(controls())->insertWidget(chartCursor, c); + winFlow->insert(chartCursor, m); + charts.insert(chartCursor, dynamic_cast(l)); + } else { + dynamic_cast(controls())->addWidget(c); + winFlow->addWidget(m); + charts.append(dynamic_cast(l)); + } + break; + } + } + //winFlow->doLayout(winFlow->geometry(), false); + winFlow->update(); + chartCursor = -2; + winWidget->repaint(); + } + // remove the cursor + chartCursor = -2; // -2 means don't show } void @@ -570,10 +715,22 @@ HomeWindow::windowResized(GcWindow*w) void HomeWindow::windowMoving(GcWindow*w) { - // ensure the mouse pointer is visible + // ensure the mouse pointer is visible, scrolls + // as we get near to the margins... QPoint pos = winWidget->mapFromGlobal(QCursor::pos()); winArea->ensureVisible(pos.x(), pos.y(), 20, 20); + chartCursor = pointTile(pos); + winWidget->repaint(); // show cursor + +#if 0 + // code for bumping tiles movement + // disaobled for now in preference for + // a drag operation with a cursor that + // highlights where the window will be + // moved to... + 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 @@ -708,6 +865,7 @@ HomeWindow::windowMoving(GcWindow*w) } } } +#endif } void @@ -717,6 +875,45 @@ HomeWindow::windowResizing(GcWindow*w) winArea->ensureVisible(pos.x(), pos.y(), 20, 20); } +void +HomeWindow::drawCursor() +{ + if (chartCursor == -2) return; + + QPainter painter(winWidget); + + // lets draw to the left of the chart... + if (chartCursor > -1) { + + // background light gray for now? + QRect line(charts[chartCursor]->geometry().x()-12, + charts[chartCursor]->geometry().y(), + 4, + charts[chartCursor]->geometry().height()); + + painter.setPen(Qt::NoPen); + painter.setBrush(QBrush(Qt::white)); + painter.drawRect(line); + + } + + // lets draw at to the right of the + // last chart... + if (chartCursor == -1) { + + // background light gray for now? + QRect line(charts[charts.count()-1]->geometry().x() + charts[charts.count()-1]->width() + 8, + charts[charts.count()-1]->geometry().y(), + 4, + charts[charts.count()-1]->geometry().height()); + + painter.setPen(Qt::NoPen); + painter.setBrush(QBrush(Qt::white)); + painter.drawRect(line); + + } +} + GcWindowDialog::GcWindowDialog(GcWinID type, MainWindow *mainWindow) : mainWindow(mainWindow), type(type) { setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/HomeWindow.h b/src/HomeWindow.h index eb2fbe6e4..7116ec750 100644 --- a/src/HomeWindow.h +++ b/src/HomeWindow.h @@ -76,10 +76,15 @@ class HomeWindow : public GcWindow void windowMoved(GcWindow*); void windowResized(GcWindow*); + // when moving tiles + int pointTile(QPoint pos); + void drawCursor(); + protected: MainWindow *mainWindow; bool active; // ignore gui signals when changing views GcWindow *clicked; // keep track of selected charts + bool dropPending; // top bar QLabel *title; @@ -105,6 +110,7 @@ class HomeWindow : public GcWindow // the charts! QList charts; + int chartCursor; };