Add Calendar

This commit is contained in:
Berend De Schouwer
2009-08-30 18:55:03 +02:00
committed by Sean Rhea
parent 55f0b19ff5
commit ec8d3e9949
6 changed files with 203 additions and 11 deletions

View File

@@ -44,7 +44,7 @@
#include <qwt_data.h>
#include <boost/scoped_ptr.hpp>
#include "DaysScaleDraw.h"
#include "RideCalendar.h"
#include "DatePickerDialog.h"
#include "ToolsDialog.h"
#include "MetricAggregator.h"
@@ -136,6 +136,9 @@ MainWindow::MainWindow(const QDir &home) :
setCentralWidget(splitter);
splitter->setContentsMargins(10, 20, 10, 10); // attempting to follow some UI guides
calendar = new RideCalendar;
calendar->setFirstDayOfWeek(Qt::Monday);
treeWidget = new QTreeWidget;
treeWidget->setColumnCount(3);
treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
@@ -143,7 +146,7 @@ MainWindow::MainWindow(const QDir &home) :
treeWidget->header()->resizeSection(0,70);
treeWidget->header()->resizeSection(1,95);
treeWidget->header()->resizeSection(2,70);
treeWidget->setMaximumWidth(250);
//treeWidget->setMaximumWidth(250);
treeWidget->header()->hide();
treeWidget->setAlternatingRowColors (true);
treeWidget->setIndentation(5);
@@ -151,7 +154,19 @@ MainWindow::MainWindow(const QDir &home) :
allRides = new QTreeWidgetItem(treeWidget, FOLDER_TYPE);
allRides->setText(0, tr("All Rides"));
treeWidget->expandItem(allRides);
splitter->addWidget(treeWidget);
leftLayout = new QSplitter;
leftLayout->setOrientation(Qt::Vertical);
leftLayout->addWidget(calendar);
leftLayout->setCollapsible(0, false);
leftLayout->addWidget(treeWidget);
leftLayout->setCollapsible(1, false);
splitter->addWidget(leftLayout);
splitter->setCollapsible(0, false);
QVariant calendarSizes = settings->value(GC_SETTINGS_CALENDAR_SIZES);
if (calendarSizes != QVariant()) {
leftLayout->restoreState(calendarSizes.toByteArray());
}
QTreeWidgetItem *last = NULL;
QStringListIterator i(RideFileFactory::instance().listRideFiles(home));
@@ -162,6 +177,39 @@ MainWindow::MainWindow(const QDir &home) :
last = new RideItem(RIDE_TYPE, home.path(),
name, dt, &zones, notesFileName);
allRides->addChild(last);
/*
* We want to display these things inside the Calendar.
* Pick a colour (this should really be configurable)
* - red for races
* - yellow for sick days
* - green for rides
*/
QString notesPath = home.absolutePath() + "/" + notesFileName;
QFile notesFile(notesPath);
QColor color(Qt::green);
QString line("Ride");
if (notesFile.exists()) {
if (notesFile.open(QFile::ReadOnly | QFile::Text)) {
QTextStream in(&notesFile);
line = in.readLine();
notesFile.close();
if (line.contains("race", Qt::CaseInsensitive)) {
color = QColor(Qt::red);
line = "RACE";
}
if (line.contains("sick", Qt::CaseInsensitive)) {
color = QColor(Qt::red);
}
if (line.contains("swim", Qt::CaseInsensitive)) {
color = QColor(Qt::blue);
}
if (line.contains("gym", Qt::CaseInsensitive)) {
color = QColor(Qt::gray);
}
}
}
calendar->addEvent(dt.date(), line, color);
}
}
@@ -260,6 +308,7 @@ MainWindow::MainWindow(const QDir &home) :
tabWidget->addTab(window, "Ride Plot");
splitter->addWidget(tabWidget);
splitter->setCollapsible(1, false);
QVariant splitterSizes = settings->value(GC_SETTINGS_SPLITTER_SIZES);
if (splitterSizes != QVariant())
@@ -505,6 +554,10 @@ MainWindow::MainWindow(const QDir &home) :
////////////////////////////// Signals //////////////////////////////
connect(calendar, SIGNAL(clicked(const QDate &)),
this, SLOT(dateChanged(const QDate &)));
connect(leftLayout, SIGNAL(splitterMoved(int,int)),
this, SLOT(leftLayoutMoved()));
connect(treeWidget, SIGNAL(itemSelectionChanged()),
this, SLOT(rideSelected()));
connect(splitter, SIGNAL(splitterMoved(int,int)),
@@ -1130,6 +1183,7 @@ MainWindow::rideSelected()
}
ride = (RideItem*) which;
calendar->setSelectedDate(ride->dateTime.date());
rideSummary->setHtml(ride->htmlSummary());
rideSummary->setAlignment(Qt::AlignCenter);
if (ride) {
@@ -1186,7 +1240,7 @@ void MainWindow::getBSFactors(float &timeBS, float &distanceBS)
BSdays.setValue(30); // by default look back no more than 30 days
// if there are rides, find most recent ride so we count back from there:
if (allRides->childCount() > 0)
if (allRides->childCount() > 0)
lastRideItem = (RideItem*) allRides->child(allRides->childCount() - 1);
else
lastRideItem = ride; // not enough rides, use current ride
@@ -1553,7 +1607,7 @@ void MainWindow::generateWeeklySummary()
// Now open any notes associated with the new ride.
rideNotes->setPlainText("");
QString notesPath = home.absolutePath() + "/" + ride->notesFileName;
QString notesPath = home.absolutePath() + "/" + ride->notesFileName;
QFile notesFile(notesPath);
if (notesFile.exists()) {
@@ -1561,7 +1615,7 @@ void MainWindow::generateWeeklySummary()
QTextStream in(&notesFile);
rideNotes->setPlainText(in.readAll());
notesFile.close();
}
}
else {
QMessageBox::critical(
this, tr("Read Error"),
@@ -1569,7 +1623,7 @@ void MainWindow::generateWeeklySummary()
}
}
currentNotesFile = ride->notesFileName;
currentNotesFile = ride->notesFileName;
currentNotesChanged = false;
}
@@ -1591,7 +1645,7 @@ void MainWindow::saveNotes()
tr("Can't rename %1 to %2")
.arg(tmpPath).arg(notesPath));
}
}
}
else {
QMessageBox::critical(
this, tr("Write Error"),
@@ -1647,7 +1701,13 @@ MainWindow::closeEvent(QCloseEvent*)
saveNotes();
}
void
void
MainWindow::leftLayoutMoved()
{
settings->setValue(GC_SETTINGS_CALENDAR_SIZES, leftLayout->saveState());
}
void
MainWindow::splitterMoved()
{
settings->setValue(GC_SETTINGS_SPLITTER_SIZES, splitter->saveState());
@@ -2112,3 +2172,23 @@ void MainWindow::setHistWidgets(RideItem *rideItem)
withZerosCheckBox->setEnabled(false);
lnYHistCheckBox->setEnabled(false);
}
/*
* This slot gets called when the user picks a new date, using the mouse,
* in the calendar. We have to adjust TreeView to match.
*/
void MainWindow::dateChanged(const QDate &date)
{
for (int i = 0; i < allRides->childCount(); i++)
{
ride = (RideItem*) allRides->child(i);
if (ride->dateTime.date() == date) {
treeWidget->scrollToItem(allRides->child(i),
QAbstractItemView::EnsureVisible);
treeWidget->setCurrentItem(allRides->child(i));
i = allRides->childCount();
}
}
}

View File

@@ -34,6 +34,7 @@ class QwtPlotPicker;
class QwtPlotZoomer;
class RideFile;
class Zones;
class RideCalendar;
class MainWindow : public QMainWindow
{
@@ -54,6 +55,7 @@ class MainWindow : public QMainWindow
private slots:
void rideSelected();
void leftLayoutMoved();
void splitterMoved();
void newCyclist();
void openCyclist();
@@ -93,6 +95,7 @@ class MainWindow : public QMainWindow
void importRideToDB();
void scanForMissing();
void generateWeeklySummary();
void dateChanged(const QDate &);
protected:
@@ -105,6 +108,7 @@ class MainWindow : public QMainWindow
QSettings *settings;
RideCalendar *calendar;
QSplitter *splitter;
QTreeWidget *treeWidget;
QTabWidget *tabWidget;
@@ -140,6 +144,7 @@ class MainWindow : public QMainWindow
QwtPlotCurve *weeklyBaselineCurve;
QwtPlotCurve *weeklyBSBaselineCurve;
QwtPlot *weeklyBSPlot;
QSplitter *leftLayout;
QwtPlotCurve *weeklyBSCurve;
QwtPlotCurve *weeklyRICurve;

79
src/RideCalendar.cpp Normal file
View File

@@ -0,0 +1,79 @@
#include <QCalendarWidget>
#include <QMultiMap>
#include <QPainter>
#include <QObject>
#include <QDate>
#include <QAbstractItemView>
#include <QSize>
#include <QTextCharFormat>
#include <QPen>
#include "RideCalendar.h"
RideCalendar::RideCalendar(QWidget *parent)
: QCalendarWidget(parent)
{
};
void RideCalendar::addEvent(QDate date, QString string, QColor color)
{
_text[date] = string;
_color[date] = color;
update();
}
void RideCalendar::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
{
if (_text.contains(date)) {
painter->save();
/*
* Draw a rectangle in the color specified. If this is the
* currently selected date, draw a black outline.
*/
QPen pen(Qt::SolidLine);
pen.setCapStyle(Qt::SquareCap);
painter->setBrush(_color[date]);
if (date == selectedDate()) {
pen.setColor(Qt::black);
pen.setWidth(1);
} else {
pen.setColor(_color[date]);
}
painter->setPen(pen);
/*
* We have to draw to height-1 and width-1 because Qt draws outlines
* outside the box by default.
*/
painter->drawRect(rect.x(), rect.y(), rect.width() - 1, rect.height() - 1);
/*
* Display the text.
*/
pen.setColor(Qt::black);
painter->setPen(pen);
QString text = QString::number(date.day());
text = text + "\n" + _text[date];
QFont font = painter->font();
font.setPointSize(font.pointSize() - 2);
painter->setFont(font);
painter->drawText(rect, Qt::AlignHCenter | Qt::TextWordWrap, text);
painter->restore();
} else {
QCalendarWidget::paintCell(painter, rect, date);
}
}
/*
* We extend QT's QCalendarWidget's sizeHint() so we claim a little bit of
* extra space.
*/
QSize RideCalendar::sizeHint() const
{
QSize hint = QCalendarWidget::sizeHint();
hint.setHeight(hint.height() * 2);
hint.setWidth(hint.width() * 2);
return hint;
}

25
src/RideCalendar.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef EVENT_CALENDAR_WIDGET_H
#define EVENT_CALENDAR_WIDGET_H
#include <QCalendarWidget>
#include <QMultiMap>
class RideCalendar : public QCalendarWidget
{
Q_OBJECT
public:
RideCalendar(QWidget *parent = 0);
void addEvent(QDate, QString, QColor);
QSize sizeHint() const;
protected:
void paintCell(QPainter *, const QRect &, const QDate &) const;
private:
QMap<QDate, QString> _text;
QMap<QDate, QColor> _color;
};
#endif

View File

@@ -28,6 +28,7 @@
#define GC_SETTINGS_MAIN_Y "mainwindow/y"
#define GC_SETTINGS_MAIN_GEOM "mainwindow/geometry"
#define GC_SETTINGS_SPLITTER_SIZES "mainwindow/splitterSizes"
#define GC_SETTINGS_CALENDAR_SIZES "mainwindow/calendarSizes"
#define GC_DATETIME_FORMAT "ddd MMM dd, yyyy, hh:mm AP"
#define GC_UNIT "unit"
#define GC_SETTINGS_LAST_IMPORT_PATH "mainwindow/lastImportPath"

View File

@@ -75,7 +75,8 @@ HEADERS += \
Settings.h \
XmlRideFile.h \
ManualRideFile.h \
ManualRideDialog.h
ManualRideDialog.h \
RideCalendar.h
SOURCES += \
AllPlot.cpp \
@@ -121,7 +122,8 @@ SOURCES += \
SplitRideDialog.cpp \
XmlRideFile.cpp \
ManualRideFile.cpp \
ManualRideDialog.cpp
ManualRideDialog.cpp \
RideCalendar.cpp
# win32 is after SOURCES and HEADERS so we can remove Serial.h/.cpp
win32 {