diff --git a/src/GcCalendar.cpp b/src/GcCalendar.cpp index bbe6d12cb..dc97f2977 100644 --- a/src/GcCalendar.cpp +++ b/src/GcCalendar.cpp @@ -702,3 +702,360 @@ GcCalendar::setSummary() } } + +GcMiniCalendar::GcMiniCalendar(MainWindow *main) : main(main) +{ + setContentsMargins(0,0,0,0); + setAutoFillBackground(true); + + month = year = 0; + _ride = NULL; + + setStyleSheet("QLabel { color: gray; }"); + layout = new QVBoxLayout(this); + layout->setSpacing(0); + layout->setContentsMargins(10,10,10,10); + + black.setColor(QPalette::WindowText, Qt::gray); + white.setColor(QPalette::WindowText, Qt::white); + grey.setColor(QPalette::WindowText, Qt::gray); + + // get the model + fieldDefinitions = main->rideMetadata()->getFields(); + calendarModel = new GcCalendarModel(this, &fieldDefinitions, main); + calendarModel->setSourceModel(main->listView->sqlModel); + + QHBoxLayout *line = new QHBoxLayout; + line->setSpacing(0); + line->setContentsMargins(0,0,0,0); + + QFont font; + font.setPointSize(12); + left = new GcLabel("<", this); + left->setAutoFillBackground(false); + left->setPalette(white); + left->setFont(font); + left->setAlignment(Qt::AlignLeft); + line->addWidget(left); + connect (left, SIGNAL(clicked()), this, SLOT(previous())); + + font.setPointSize(12); + monthName = new GcLabel("January 2012", this); + monthName->setAutoFillBackground(false); + monthName->setPalette(white); + monthName->setFont(font); + monthName->setAlignment(Qt::AlignCenter); + line->addWidget(monthName); + + font.setPointSize(12); + right = new GcLabel(">", this); + right->setAutoFillBackground(false); + right->setPalette(white); + right->setFont(font); + right->setAlignment(Qt::AlignRight); + line->addWidget(right); + connect (right, SIGNAL(clicked()), this, SLOT(next())); + + QWidget *month = new QWidget(this); + month->setContentsMargins(0,0,0,0); + month->setFixedWidth(180); + month->setFixedHeight(180); + QGridLayout *dayLayout = new QGridLayout(month); + dayLayout->setSpacing(1); + dayLayout->setContentsMargins(0,0,0,0); + dayLayout->addLayout(line, 0,0,1,7); + layout->addWidget(month, Qt::AlignCenter); + + font.setWeight(QFont::Normal); + + // Mon + font.setPointSize(9); + GcLabel *day = new GcLabel("Mon", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 0); + + // Tue + day = new GcLabel("Tue", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 1); + + // Wed + day = new GcLabel("Wed", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 2); + + // Thu + day = new GcLabel("Thu", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 3); + + // Fri + day = new GcLabel("Fri", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 4); + + // Sat + day = new GcLabel("Sat", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 5); + + // Sun + day = new GcLabel("Sun", this); + day->setFont(font); + day->setAutoFillBackground(false); + day->setPalette(white); + day->setFont(font); + day->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(day, 1, 6); + + signalMapper = new QSignalMapper(this); + font.setPointSize(11); + for (int row=2; row<8; row++) { + + for (int col=0; col < 7; col++) { + + GcLabel *d = new GcLabel(QString("%1").arg((row-2)*7+col), this); + d->setFont(font); + d->setAutoFillBackground(false); + d->setPalette(grey); + d->setStyleSheet("color: gray;"); + d->setAlignment(Qt::AlignCenter); + dayLayout->addWidget(d,row,col); + + // we like squares + d->setFixedHeight(22); + d->setFixedWidth(22); + + dayLabels << d; + + if (row== 3 && col == 4) d->setSelected(true); + + connect (d, SIGNAL(clicked()), signalMapper, SLOT(map())); + signalMapper->setMapping(d, (row-2)*7+col); + } + } + layout->addStretch(); + + // day clicked + connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(dayClicked(int))); + + // refresh on these events... + connect(main, SIGNAL(rideAdded(RideItem*)), this, SLOT(refresh())); + connect(main, SIGNAL(rideDeleted(RideItem*)), this, SLOT(refresh())); + connect(main, SIGNAL(configChanged()), this, SLOT(refresh())); + + // set up for current selections + refresh(); +} + +void +GcMiniCalendar::refresh() +{ + calendarModel->setMonth(month, year); + repaint(); +} + +bool +GcMiniCalendar::event(QEvent *e) +{ + if (e->type() != QEvent::ToolTip && e->type() != QEvent::Paint && e->type() != QEvent::Destroy && + e->type() != QEvent::LayoutRequest) { + main->setBubble(""); + //qDebug()<<"event"<type(); + } + + if (e->type() == QEvent::Paint) { + // fill the background + QPainter painter(this); + QRect all(0,0,width(),height()); + //painter.fillRect(all, QColor("#B3B4BA")); + painter.fillRect(all, QColor(Qt::white)); + } + + int n=0; + if (e->type() == QEvent::ToolTip) { + + // are we hovering over a label? + foreach(GcLabel *label, dayLabels) { + if (label->underMouse()) { + if (dayLabels.at(n)->text() == "") return false; + + // select a ride if there is one for this one? + int row = n / 7; + int col = n % 7; + + QModelIndex p = calendarModel->index(row,col); + QStringList files = calendarModel->data(p, GcCalendarModel::FilenamesRole).toStringList(); + + QPoint pos = dynamic_cast(e)->pos(); + + // Popup bubble for ride + if (files.count()) { + if (files[0] == "calendar") ; // handle planned rides + else main->setBubble(files.at(0), mapToGlobal(pos+QPoint(+2,+2))); + } + } + n++; + } + } + return QWidget::event(e); +} + +void +GcMiniCalendar::dayClicked(int i) +{ + if (dayLabels.at(i)->text() == "") return; + + // select a ride if there is one for this one? + int row = i / 7; + int col = i % 7; + + + QModelIndex p = calendarModel->index(row,col); + QStringList files = calendarModel->data(p, GcCalendarModel::FilenamesRole).toStringList(); + + if (files.count()) // if more than one file cycle through them? + main->selectRideFile(QFileInfo(files[0]).fileName()); + +} + +void +GcMiniCalendar::previous() +{ + QList allDates = main->metricDB->db()->getAllDates(); + qSort(allDates); + + // begin of month + QDateTime bom(QDate(year,month,01), QTime(0,0,0)); + for(int i=allDates.count()-1; i>0; i--) { + if (allDates.at(i) < bom) { + + QDate date = allDates.at(i).date(); + calendarModel->setMonth(date.month(), date.year()); + + // find the day in the calendar... + for (int day=42; day>0;day--) { + + QModelIndex p = calendarModel->index(day/7,day%7); + QDate heredate = calendarModel->date(p); + if (date == heredate) { + // select this ride... + QStringList files = calendarModel->data(p, GcCalendarModel::FilenamesRole).toStringList(); + if (files.count()) main->selectRideFile(QFileInfo(files[0]).fileName()); + } + } + break; + } + } +} + +void +GcMiniCalendar::next() +{ + QList allDates = main->metricDB->db()->getAllDates(); + qSort(allDates); + + // end of month + QDateTime eom(QDate(year,month,01).addMonths(1), QTime(00,00,00)); + for(int i=0; i= eom) { + + QDate date = allDates.at(i).date(); + calendarModel->setMonth(date.month(), date.year()); + + // find the day in the calendar... + for (int day=0; day<42;day++) { + + QModelIndex p = calendarModel->index(day/7,day%7); + QDate heredate = calendarModel->date(p); + if (date == heredate) { + // select this ride... + QStringList files = calendarModel->data(p, GcCalendarModel::FilenamesRole).toStringList(); + if (files.count()) main->selectRideFile(QFileInfo(files[0]).fileName()); + } + } + break; + } + } +} + +void +GcMiniCalendar::setRide(RideItem *ride) +{ + _ride = ride; + + QDate when; + if (_ride && _ride->ride()) when = _ride->dateTime.date(); + else when = QDate::currentDate(); + + // refresh the model + if (when.month() != month || when.year() != year) { + calendarModel->setMonth(when.month(), when.year()); + year = when.year(); + month = when.month(); + + monthName->setText(when.toString("MMMM yyyy")); + } + + // now reapply for each row/col of calendar... + for (int row=0; row<6; row++) { + for (int col=0; col < 7; col++) { + + GcLabel *d = dayLabels.at(row*7+col); + QModelIndex p = calendarModel->index(row,col); + QDate date = calendarModel->date(p); + + if (date.month() != month || date.year() != year) { + d->setText(""); + d->setBg(false); + d->setSelected(false); + } else { + d->setText(QString("%1").arg(date.day())); + + // what color should it be? + // for taste we /currently/ just set to bg to + // highlight there is a ride there, colors /will/ come + // back later when worked out a way of making it look + // nice and not garish + QList colors = p.data(Qt::BackgroundRole).value >(); + if (colors.count()) { + d->setBg(true); + d->setPalette(black); + d->setBgColor(colors.at(0)); // use first always + } else { + d->setBg(false); + d->setPalette(white); + } + if (date == when) { + d->setSelected(true); + d->setPalette(white); + } else d->setSelected(false); + } + } + } + refresh(); +} diff --git a/src/GcCalendar.h b/src/GcCalendar.h index 0d8e76e27..63fdcaaf4 100644 --- a/src/GcCalendar.h +++ b/src/GcCalendar.h @@ -64,6 +64,47 @@ protected: QColor bgColor; }; +class GcMiniCalendar : public QWidget +{ + Q_OBJECT + + public: + + GcMiniCalendar(MainWindow *); + + public slots: + + void setRide(RideItem *ride); + void refresh(); + + void dayClicked(int num); // for when a day is selected + void next(); + void previous(); + + bool event(QEvent *e); + + signals: + + protected: + MainWindow *main; + RideItem *_ride; + int month, year; + + QVBoxLayout *layout; + + GcLabel *left, *right; // < ... > + GcLabel *monthName; // January 2012 + GcLabel *dayNames[7]; // Mon .. Sun + + QList dayLabels; // 1 .. 31 + + QSignalMapper *signalMapper; // for mapping dayLabels "clicked" + + QPalette black, grey, white; + QList fieldDefinitions; + GcCalendarModel *calendarModel; +}; + class GcCalendar : public QWidget // not a GcWindow - belongs on sidebar { Q_OBJECT diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 20a2e8a64..2fb0d2834 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -659,12 +659,16 @@ MainWindow::MainWindow(const QDir &home) : intervalSplitter->setCollapsible(0, false); intervalSplitter->setCollapsible(1, false); + GcSplitterItem *calendarItem = new GcSplitterItem(tr("Calendar"), iconFromPNG(":images/sidebar/calendar.png"), this); + gcMiniCalendar = new GcMiniCalendar(this); + calendarItem->addWidget(gcMiniCalendar); + analItem = new GcSplitterItem(tr("Activities"), iconFromPNG(":images/sidebar/folder.png"), this); QAction *moreAnalAct = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this); analItem->addAction(moreAnalAct); connect(moreAnalAct, SIGNAL(triggered(void)), this, SLOT(analysisPopup())); - analItem->addWidget(activityHistory); + intervalItem = new GcSplitterItem(tr("Intervals"), iconFromPNG(":images/mac/stop.png"), this); QAction *moreIntervalAct = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this); intervalItem->addAction(moreIntervalAct); @@ -672,6 +676,7 @@ MainWindow::MainWindow(const QDir &home) : intervalItem->addWidget(intervalSplitter); analSidebar = new GcSplitter(Qt::Vertical); + analSidebar->addWidget(calendarItem); analSidebar->addWidget(analItem); analSidebar->addWidget(intervalItem); analSidebar->prepare(cyclist, "analysis"); @@ -1235,6 +1240,7 @@ MainWindow::rideTreeWidgetSelectionChanged() diaryWindow->setProperty("ride", QVariant::fromValue(dynamic_cast(ride))); trainWindow->setProperty("ride", QVariant::fromValue(dynamic_cast(ride))); gcCalendar->setRide(ride); + gcMiniCalendar->setRide(ride); enableSaveButton(); // should it be enabled or not? diff --git a/src/MainWindow.h b/src/MainWindow.h index 4f941c168..243fb1245 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -57,6 +57,7 @@ class IntervalSummaryWindow; class RideNavigator; class GcToolBar; class GcCalendar; +class GcMiniCalendar; class GcBubble; class LTMSidebar; class LionFullScreen; @@ -415,6 +416,7 @@ class MainWindow : public QMainWindow QMenu *windowMenu; GcBubble *bubble; GcCalendar *gcCalendar; + GcMiniCalendar *gcMiniCalendar; // each view has its own controls XXX more to come QStackedWidget *masterControls, diff --git a/src/RideNavigator.h b/src/RideNavigator.h index 3972497a9..f4e459713 100644 --- a/src/RideNavigator.h +++ b/src/RideNavigator.h @@ -39,6 +39,7 @@ class SearchFilterBox; class DiaryWindow; class BUGFIXQSortFilterProxyModel; class DataFilter; +class GcMiniCalendar; // // The RideNavigator @@ -62,6 +63,7 @@ class RideNavigator : public GcWindow friend class ::GroupByModel; friend class ::DiaryWindow; friend class ::GcCalendar; + friend class ::GcMiniCalendar; friend class ::DataFilter; public: