Reinstate mini calendar on sidebar

This is the first step to reinstating the calendar on the analysis view
sidebar. Next step is to enhance it to show multiple months and then to
refactor the diary sidebar GcCalendar to use it.
This commit is contained in:
Mark Liversedge
2013-03-11 12:14:43 +00:00
parent 7b9a4744f6
commit 3cfa9048cf
5 changed files with 409 additions and 1 deletions

View File

@@ -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"<<e->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<QHelpEvent*>(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<QDateTime> 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<QDateTime> 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<allDates.count(); i++) {
if (allDates.at(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<QColor> colors = p.data(Qt::BackgroundRole).value<QList<QColor> >();
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();
}

View File

@@ -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<GcLabel*> dayLabels; // 1 .. 31
QSignalMapper *signalMapper; // for mapping dayLabels "clicked"
QPalette black, grey, white;
QList<FieldDefinition> fieldDefinitions;
GcCalendarModel *calendarModel;
};
class GcCalendar : public QWidget // not a GcWindow - belongs on sidebar
{
Q_OBJECT

View File

@@ -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<RideItem*>(dynamic_cast<RideItem*>(ride)));
trainWindow->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
gcCalendar->setRide(ride);
gcMiniCalendar->setRide(ride);
enableSaveButton(); // should it be enabled or not?

View File

@@ -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,

View File

@@ -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: