From d4eaf99a3ffe63d386ae1e8ffb855b9086a0baee Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sat, 5 Feb 2011 12:46:54 +0000 Subject: [PATCH] Improved Season Support This fixes issues with date range editing in the Metrics controls and provides support for Season load planning (under development). Creating and selecting seasons is largely managed within the Metrics tool. This has not been changed with this patch. Athlete seasons are now managed as a member of the MainWindow class (although this will move to an Athlete/Cyclist class when MainWindow is refactored). A Season identifier (UUID) has been introduced to enable Seasons to be referenced independently of their name or date ranges. The LTM tool now keeps track of changes to Seasons (when new seasons are created, changed, deleted). Additionally, the Season XML file now supports storage of a Season Load Plan. --- src/GoldenCheetah.cpp | 3 +- src/LTMPlot.cpp | 10 +- src/LTMPlot.h | 9 +- src/LTMTool.cpp | 372 +++++++++++++++++------------------------- src/LTMTool.h | 6 +- src/LTMWindow.cpp | 3 +- src/LTMWindow.h | 12 +- src/MainWindow.cpp | 3 + src/MainWindow.h | 4 + src/Season.cpp | 145 ++++++++++++++++ src/Season.h | 37 ++++- src/SeasonParser.cpp | 33 +++- src/SeasonParser.h | 1 + 13 files changed, 390 insertions(+), 248 deletions(-) diff --git a/src/GoldenCheetah.cpp b/src/GoldenCheetah.cpp index 707212a32..74c2fdd6b 100644 --- a/src/GoldenCheetah.cpp +++ b/src/GoldenCheetah.cpp @@ -315,7 +315,8 @@ GcWindow::spotHotSpot(QMouseEvent *e) else if (_x >= (_width-borderWidth)) return (Right); else if (_y <= borderWidth) return (Top); else if (_y >= (_height-borderWidth)) return (Bottom); - else return (Move); + else if (_y <= contentsMargins().top()) return (Move); + else return (None); } void diff --git a/src/LTMPlot.cpp b/src/LTMPlot.cpp index db68f2c4d..ee24d36c9 100644 --- a/src/LTMPlot.cpp +++ b/src/LTMPlot.cpp @@ -43,7 +43,7 @@ static int supported_axes[] = { QwtPlot::yLeft, QwtPlot::yRight, QwtPlot::yLeft1, QwtPlot::yRight1, QwtPlot::yLeft2, QwtPlot::yRight2, QwtPlot::yLeft3, QwtPlot::yRight3 }; -LTMPlot::LTMPlot(LTMWindow *parent, MainWindow *main, QDir home) : bg(NULL), parent(parent), main(main), +LTMPlot::LTMPlot(LTMPlotContainer *parent, MainWindow *main, QDir home) : bg(NULL), parent(parent), main(main), home(home), highlighter(NULL) { setInstanceName("Metric Plot"); @@ -1186,6 +1186,13 @@ LTMPlot::aggregateCurves(QVector &a, QVector&w) for(int i=0; iattach(this); } - diff --git a/src/LTMPlot.h b/src/LTMPlot.h index 2ba5af5a6..4faa9723c 100644 --- a/src/LTMPlot.h +++ b/src/LTMPlot.h @@ -35,7 +35,7 @@ class LTMPlotBackground; class LTMPlotZoneLabel; - +class LTMPlotContainer; class LTMScaleDraw; class LTMPlot : public QwtPlot @@ -45,14 +45,15 @@ class LTMPlot : public QwtPlot public: - LTMPlot(LTMWindow *, MainWindow *main, QDir home); + LTMPlot(LTMPlotContainer *, MainWindow *main, QDir home); ~LTMPlot(); void setData(LTMSettings *); void setAxisTitle(int axis, QString label); public slots: void pointHover(QwtPlotCurve*, int); - void pointClicked(QwtPlotCurve*, int); + void pointClicked(QwtPlotCurve*, int); // point clicked + void changeValue(QwtPlotCurve*, int, double); // point moved void pickerMoved(QPoint); void pickerAppended(QPoint); void configUpdate(); @@ -64,7 +65,7 @@ class LTMPlot : public QwtPlot LTMPlotBackground *bg; QList zoneLabels; - LTMWindow *parent; + LTMPlotContainer *parent; double minY[10], maxY[10], maxX; // for all possible 10 curves private: diff --git a/src/LTMTool.cpp b/src/LTMTool.cpp index e03a13d2b..763e2477c 100644 --- a/src/LTMTool.cpp +++ b/src/LTMTool.cpp @@ -34,7 +34,7 @@ #include "RideMetadata.h" #include "SpecialFields.h" -LTMTool::LTMTool(MainWindow *parent, const QDir &home, bool multi) : QWidget(parent), home(home), main(parent) +LTMTool::LTMTool(MainWindow *parent, const QDir &home, bool multi) : QWidget(parent), home(home), main(parent), active(false) { // get application settings useMetricUnits = appsettings->value(this, GC_UNIT).toString() == "Metric"; @@ -50,10 +50,13 @@ LTMTool::LTMTool(MainWindow *parent, const QDir &home, bool multi) : QWidget(par dateRangeTree->setIndentation(5); allDateRanges = new QTreeWidgetItem(dateRangeTree, ROOT_TYPE); allDateRanges->setText(0, tr("Date Range")); - readSeasons(); + dateRangeTree->expandItem(allDateRanges); dateRangeTree->setContextMenuPolicy(Qt::CustomContextMenu); + seasons = parent->seasons; + resetSeasons(); // reset the season list + metricTree = new QTreeWidget; metricTree->setColumnCount(1); if (multi) @@ -466,6 +469,7 @@ LTMTool::LTMTool(MainWindow *parent, const QDir &home, bool multi) : QWidget(par this, SLOT(metricTreePopup(const QPoint &))); connect(dateRangeTree,SIGNAL(itemChanged(QTreeWidgetItem *,int)), this, SLOT(dateRangeChanged(QTreeWidgetItem*, int))); + connect(seasons, SIGNAL(seasonsChanged()), this, SLOT(resetSeasons())); } void @@ -511,7 +515,7 @@ LTMTool::_dateRange() const if (dateRangeTree->selectedItems().isEmpty()) return QString(""); else { QTreeWidgetItem *which = dateRangeTree->selectedItems().first(); - return which->text(0); + return seasons->seasons[allDateRanges->indexOfChild(which)].id().toString(); } } @@ -521,8 +525,10 @@ LTMTool::setDateRange(QString s) // clear current selection dateRangeTree->clearSelection(); - for(int i=0; ichildCount(); i++) { - if (allDateRanges->child(i)->text(0) == s) { + QUuid find(s); + + for(int i=0; iseasons.count(); i++) { + if (seasons->seasons[i].id() == find) { allDateRanges->child(i)->setSelected(true); return; } @@ -536,11 +542,13 @@ LTMTool::setDateRange(QString s) void LTMTool::dateRangeTreeWidgetSelectionChanged() { + if (active == true) return; + if (dateRangeTree->selectedItems().isEmpty()) dateRange = NULL; else { QTreeWidgetItem *which = dateRangeTree->selectedItems().first(); if (which != allDateRanges) { - dateRange = &seasons.at(allDateRanges->indexOfChild(which)); + dateRange = &seasons->seasons.at(allDateRanges->indexOfChild(which)); } else { dateRange = NULL; } @@ -555,102 +563,8 @@ LTMTool::metricTreeWidgetSelectionChanged() } /*---------------------------------------------------------------------- - * Date ranges from Seasons.xml + * Metric settings *--------------------------------------------------------------------*/ -void LTMTool::readSeasons() -{ - QFile seasonFile(home.absolutePath() + "/seasons.xml"); - QXmlInputSource source( &seasonFile ); - QXmlSimpleReader xmlReader; - SeasonParser( handler ); - xmlReader.setContentHandler(&handler); - xmlReader.setErrorHandler(&handler); - xmlReader.parse( source ); - seasons = handler.getSeasons(); - - int i; - for (i=0; i setText(0, season.getName()); - } - Season season; - QDate today = QDate::currentDate(); - QDate eom = QDate(today.year(), today.month(), today.daysInMonth()); - - // add Default Date Ranges - season.setName(tr("All Dates")); - season.setType(Season::temporary); - season.setStart(QDate::currentDate().addYears(-50)); - season.setEnd(QDate::currentDate().addYears(50)); - seasons.append(season); - - season.setName(tr("This Year")); - season.setType(Season::temporary); - season.setStart(QDate(today.year(), 1,1)); - season.setEnd(QDate(today.year(), 12, 31)); - seasons.append(season); - - season.setName(tr("This Month")); - season.setType(Season::temporary); - season.setStart(QDate(today.year(), today.month(),1)); - season.setEnd(eom); - seasons.append(season); - - season.setName(tr("This Week")); - season.setType(Season::temporary); - // from Mon-Sun - QDate wstart = QDate::currentDate(); - wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek()); - QDate wend = wstart.addDays(6); // first day + 6 more - season.setStart(wstart); - season.setEnd(wend); - seasons.append(season); - - season.setName(tr("Last 7 days")); - season.setType(Season::temporary); - season.setStart(today.addDays(-6)); // today plus previous 6 - season.setEnd(today); - seasons.append(season); - - season.setName(tr("Last 14 days")); - season.setType(Season::temporary); - season.setStart(today.addDays(-13)); - season.setEnd(today); - seasons.append(season); - - season.setName(tr("Last 28 days")); - season.setType(Season::temporary); - season.setStart(today.addDays(-27)); - season.setEnd(today); - seasons.append(season); - - season.setName(tr("Last 3 months")); - season.setType(Season::temporary); - season.setEnd(today); - season.setStart(today.addMonths(-3)); - seasons.append(season); - - season.setName(tr("Last 6 months")); - season.setType(Season::temporary); - season.setEnd(today); - season.setStart(today.addMonths(-6)); - seasons.append(season); - - season.setName(tr("Last 12 months")); - season.setType(Season::temporary); - season.setEnd(today); - season.setStart(today.addMonths(-12)); - seasons.append(season); - - for (;i setText(0, season.getName()); - } - dateRangeTree->expandItem(allDateRanges); -} - QString LTMTool::metricName(QTreeWidgetItem *item) { @@ -677,129 +591,6 @@ LTMTool::metricDetails(QTreeWidgetItem *item) } -int -LTMTool::newSeason(QString name, QDate start, QDate end, int type) -{ - Season add; - add.setName(name); - add.setStart(start); - add.setEnd(end); - add.setType(type); - seasons.insert(0, add); - - // save changes away - writeSeasons(); - - QTreeWidgetItem *item = new QTreeWidgetItem(USER_DATE); - item->setText(0, add.getName()); - allDateRanges->insertChild(0, item); - return 0; // always add at the top -} - -void -LTMTool::updateSeason(int index, QString name, QDate start, QDate end, int type) -{ - seasons[index].setName(name); - seasons[index].setStart(start); - seasons[index].setEnd(end); - seasons[index].setType(type); - allDateRanges->child(index)->setText(0, name); - - // save changes away - writeSeasons(); - -} - -void -LTMTool::dateRangePopup(QPoint pos) -{ - QTreeWidgetItem *item = dateRangeTree->itemAt(pos); - if (item != NULL && item->type() != ROOT_TYPE && item->type() != SYS_DATE) { - - // save context - activeDateRange = item; - - // create context menu - QMenu menu(dateRangeTree); - QAction *rename = new QAction(tr("Rename range"), dateRangeTree); - QAction *edit = new QAction(tr("Edit details"), dateRangeTree); - QAction *del = new QAction(tr("Delete range"), dateRangeTree); - menu.addAction(rename); - menu.addAction(edit); - menu.addAction(del); - - // connect menu to functions - connect(rename, SIGNAL(triggered(void)), this, SLOT(renameRange(void))); - connect(edit, SIGNAL(triggered(void)), this, SLOT(editRange(void))); - connect(del, SIGNAL(triggered(void)), this, SLOT(deleteRange(void))); - - // execute the menu - menu.exec(dateRangeTree->mapToGlobal(pos)); - } -} - -void -LTMTool::renameRange() -{ - // go edit the name - activeDateRange->setFlags(activeDateRange->flags() | Qt::ItemIsEditable); - dateRangeTree->editItem(activeDateRange, 0); -} - -void -LTMTool::dateRangeChanged(QTreeWidgetItem*item, int) -{ - if (item != activeDateRange) return; - - int index = allDateRanges->indexOfChild(item); - seasons[index].setName(item->text(0)); - - // save changes away - writeSeasons(); - - // signal date selected changed - dateRangeSelected(&seasons[index]); -} - -void -LTMTool::editRange() -{ - // throw up modal dialog box to edit all the season - // fields. - int index = allDateRanges->indexOfChild(activeDateRange); - EditSeasonDialog dialog(main, &seasons[index]); - - if (dialog.exec()) { - // update name - activeDateRange->setText(0, seasons[index].getName()); - - // save changes away - writeSeasons(); - - // signal its changed! - dateRangeSelected(&seasons[index]); - } -} - -void -LTMTool::deleteRange() -{ - // now delete! - int index = allDateRanges->indexOfChild(activeDateRange); - delete allDateRanges->takeChild(index); - seasons.removeAt(index); - - // now update season.xml - writeSeasons(); -} - -void -LTMTool::writeSeasons() -{ - // update seasons.xml - QString file = QString(home.absolutePath() + "/seasons.xml"); - SeasonParser::serialize(file, seasons); -} void LTMTool::metricTreePopup(QPoint pos) @@ -1122,3 +913,136 @@ EditMetricDetailDialog::setButtonIcon(QColor color) curveColor->setContentsMargins(2,2,2,2); curveColor->setFixedWidth(34); } + +/*---------------------------------------------------------------------- + * Seasons stuff + *--------------------------------------------------------------------*/ + +void +LTMTool::resetSeasons() +{ + if (active) return; + + QString now = _dateRange(); // remeber now + + active = true; + int i; + for (i=allDateRanges->childCount(); i > 0; i--) { + delete allDateRanges->takeChild(0); + } + for (i=0; i seasons.count(); i++) { + Season season = seasons->seasons.at(i); + QTreeWidgetItem *add = new QTreeWidgetItem(allDateRanges, season.getType()); + add->setText(0, season.getName()); + } + setDateRange(now); // reselect now + active = false; +} + +int +LTMTool::newSeason(QString name, QDate start, QDate end, int type) +{ + seasons->newSeason(name, start, end, type); + + QTreeWidgetItem *item = new QTreeWidgetItem(USER_DATE); + item->setText(0, name); + allDateRanges->insertChild(0, item); + return 0; // always add at the top +} + +void +LTMTool::updateSeason(int index, QString name, QDate start, QDate end, int type) +{ + seasons->updateSeason(index, name, start, end, type); + allDateRanges->child(index)->setText(0, name); +} + +void +LTMTool::dateRangePopup(QPoint pos) +{ + QTreeWidgetItem *item = dateRangeTree->itemAt(pos); + if (item != NULL && item->type() != ROOT_TYPE && item->type() != SYS_DATE) { + + // out of bounds or not user defined + int index = allDateRanges->indexOfChild(item); + if (index == -1 || index >= seasons->seasons.count() + || seasons->seasons[index].getType() == Season::temporary) + return; + + // save context + activeDateRange = item; + + // create context menu + QMenu menu(dateRangeTree); + QAction *rename = new QAction(tr("Rename range"), dateRangeTree); + QAction *edit = new QAction(tr("Edit details"), dateRangeTree); + QAction *del = new QAction(tr("Delete range"), dateRangeTree); + menu.addAction(rename); + menu.addAction(edit); + menu.addAction(del); + + // connect menu to functions + connect(rename, SIGNAL(triggered(void)), this, SLOT(renameRange(void))); + connect(edit, SIGNAL(triggered(void)), this, SLOT(editRange(void))); + connect(del, SIGNAL(triggered(void)), this, SLOT(deleteRange(void))); + + // execute the menu + menu.exec(dateRangeTree->mapToGlobal(pos)); + } +} + +void +LTMTool::renameRange() +{ + // go edit the name + activeDateRange->setFlags(activeDateRange->flags() | Qt::ItemIsEditable); + dateRangeTree->editItem(activeDateRange, 0); +} + +void +LTMTool::dateRangeChanged(QTreeWidgetItem*item, int) +{ + if (item != activeDateRange || active == true) return; + + int index = allDateRanges->indexOfChild(item); + seasons->seasons[index].setName(item->text(0)); + + // save changes away + active = true; + seasons->writeSeasons(); + active = false; + + // signal date selected changed + //dateRangeSelected(&seasons->seasons[index]); +} + +void +LTMTool::editRange() +{ + // throw up modal dialog box to edit all the season + // fields. + int index = allDateRanges->indexOfChild(activeDateRange); + EditSeasonDialog dialog(main, &seasons->seasons[index]); + + if (dialog.exec()) { + // update name + activeDateRange->setText(0, seasons->seasons[index].getName()); + + // save changes away + active = true; + seasons->writeSeasons(); + active = false; + + // signal its changed! + dateRangeSelected(&seasons->seasons[index]); + } +} + +void +LTMTool::deleteRange() +{ + // now delete! + int index = allDateRanges->indexOfChild(activeDateRange); + delete allDateRanges->takeChild(index); + seasons->deleteSeason(index); +} diff --git a/src/LTMTool.h b/src/LTMTool.h index 66da95c49..12bbfee9f 100644 --- a/src/LTMTool.h +++ b/src/LTMTool.h @@ -84,8 +84,7 @@ class LTMTool : public QWidget void colorPicker(); void editMetric(); void configChanged(); - void readSeasons(); - void writeSeasons(); + void resetSeasons(); // rebuild the seasons list if it changes private: @@ -95,8 +94,9 @@ class LTMTool : public QWidget const QDir home; MainWindow *main; bool useMetricUnits; + bool active; // ignore season changed signals since we triggered them - QList seasons; + Seasons *seasons; QTreeWidget *dateRangeTree; QTreeWidgetItem *allDateRanges; const Season *dateRange; diff --git a/src/LTMWindow.cpp b/src/LTMWindow.cpp index 8a720cda8..05516193b 100644 --- a/src/LTMWindow.cpp +++ b/src/LTMWindow.cpp @@ -35,9 +35,10 @@ #include LTMWindow::LTMWindow(MainWindow *parent, bool useMetricUnits, const QDir &home) : - GcWindow(parent), main(parent), home(home), + LTMPlotContainer(parent), home(home), useMetricUnits(useMetricUnits), active(false), dirty(true) { + main = parent; setInstanceName("Metric Window"); // the plot diff --git a/src/LTMWindow.h b/src/LTMWindow.h index bdb674556..c50cdff05 100644 --- a/src/LTMWindow.h +++ b/src/LTMWindow.h @@ -69,7 +69,16 @@ class LTMToolTip : public QwtPlotPicker QString tip; }; -class LTMWindow : public GcWindow +class LTMPlotContainer : public GcWindow +{ + public: + LTMPlotContainer(QWidget *parent) : GcWindow(parent) {} + virtual LTMToolTip *toolTip() = 0; + virtual void pointClicked(QwtPlotCurve *, int) = 0; + MainWindow *main; +}; + +class LTMWindow : public LTMPlotContainer { Q_OBJECT G_OBJECT @@ -83,7 +92,6 @@ class LTMWindow : public GcWindow public: - MainWindow *main; // used by zones shader LTMWindow(MainWindow *, bool, const QDir &); ~LTMWindow(); LTMToolTip *toolTip() { return picker; } diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 568f86e98..19eefa6e9 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -175,6 +175,9 @@ MainWindow::MainWindow(const QDir &home) : QMessageBox::warning(this, tr("Reading HR Zones File"), hrzones_->warningString()); } + // Get athlete seasons + seasons = new Seasons(home); + QVariant geom = appsettings->value(this, GC_SETTINGS_MAIN_GEOM); if (geom == QVariant()) resize(640, 480); diff --git a/src/MainWindow.h b/src/MainWindow.h index db8e08a04..c258cf732 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -65,6 +65,7 @@ class GcWindowTool; class HomeWindow; class ICalendar; class CalDAV; +class Seasons; class MainWindow : public QMainWindow { @@ -111,6 +112,8 @@ class MainWindow : public QMainWindow // db connections to cyclistdir/metricDB - one per active MainWindow QSqlDatabase db; MetricAggregator *metricDB; + Seasons *seasons; + int session; bool isclean; QString cyclist; // the cyclist name @@ -139,6 +142,7 @@ class MainWindow : public QMainWindow void intervalSelected(); void intervalsChanged(); void zonesChanged(); + void seasonsChanged(); void configChanged(); void viewChanged(int); void rideAdded(RideItem *); diff --git a/src/Season.cpp b/src/Season.cpp index 5bba8aa68..4a5c140b0 100644 --- a/src/Season.cpp +++ b/src/Season.cpp @@ -23,9 +23,12 @@ #include "SeasonParser.h" #include +#define tr(s) QObject::tr(s) + Season::Season() { type = season; // by default seasons are of type season + _id = QUuid::createUuid(); // in case it isn't set yet } QString Season::getName() { @@ -139,3 +142,145 @@ EditSeasonDialog::cancelClicked() { reject(); } + +// +// Manage the seasons array +// +void +Seasons::readSeasons() +{ + QFile seasonFile(home.absolutePath() + "/seasons.xml"); + QXmlInputSource source( &seasonFile ); + QXmlSimpleReader xmlReader; + SeasonParser( handler ); + xmlReader.setContentHandler(&handler); + xmlReader.setErrorHandler(&handler); + xmlReader.parse( source ); + seasons = handler.getSeasons(); + + Season season; + QDate today = QDate::currentDate(); + QDate eom = QDate(today.year(), today.month(), today.daysInMonth()); + + // add Default Date Ranges + season.setName(tr("All Dates")); + season.setType(Season::temporary); + season.setStart(QDate::currentDate().addYears(-50)); + season.setEnd(QDate::currentDate().addYears(50)); + season.setId(QUuid("{00000000-0000-0000-0000-000000000001}")); + seasons.append(season); + + season.setName(tr("This Year")); + season.setType(Season::temporary); + season.setStart(QDate(today.year(), 1,1)); + season.setEnd(QDate(today.year(), 12, 31)); + season.setId(QUuid("{00000000-0000-0000-0000-000000000002}")); + seasons.append(season); + + season.setName(tr("This Month")); + season.setType(Season::temporary); + season.setStart(QDate(today.year(), today.month(),1)); + season.setEnd(eom); + season.setId(QUuid("{00000000-0000-0000-0000-000000000003}")); + seasons.append(season); + + season.setName(tr("This Week")); + season.setType(Season::temporary); + // from Mon-Sun + QDate wstart = QDate::currentDate(); + wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek()); + QDate wend = wstart.addDays(6); // first day + 6 more + season.setStart(wstart); + season.setEnd(wend); + season.setId(QUuid("{00000000-0000-0000-0000-000000000004}")); + seasons.append(season); + + season.setName(tr("Last 7 days")); + season.setType(Season::temporary); + season.setStart(today.addDays(-6)); // today plus previous 6 + season.setEnd(today); + season.setId(QUuid("{00000000-0000-0000-0000-000000000005}")); + seasons.append(season); + + season.setName(tr("Last 14 days")); + season.setType(Season::temporary); + season.setStart(today.addDays(-13)); + season.setEnd(today); + season.setId(QUuid("{00000000-0000-0000-0000-000000000006}")); + seasons.append(season); + + season.setName(tr("Last 28 days")); + season.setType(Season::temporary); + season.setStart(today.addDays(-27)); + season.setEnd(today); + season.setId(QUuid("{00000000-0000-0000-0000-000000000007}")); + seasons.append(season); + + season.setName(tr("Last 3 months")); + season.setType(Season::temporary); + season.setEnd(today); + season.setStart(today.addMonths(-3)); + season.setId(QUuid("{00000000-0000-0000-0000-000000000008}")); + seasons.append(season); + + season.setName(tr("Last 6 months")); + season.setType(Season::temporary); + season.setEnd(today); + season.setStart(today.addMonths(-6)); + season.setId(QUuid("{00000000-0000-0000-0000-000000000009}")); + seasons.append(season); + + season.setName(tr("Last 12 months")); + season.setType(Season::temporary); + season.setEnd(today); + season.setStart(today.addMonths(-12)); + season.setId(QUuid("{00000000-0000-0000-0000-000000000010}")); + seasons.append(season); +} + +int +Seasons::newSeason(QString name, QDate start, QDate end, int type) +{ + Season add; + add.setName(name); + add.setStart(start); + add.setEnd(end); + add.setType(type); + seasons.insert(0, add); + + // save changes away + writeSeasons(); + + return 0; // always add at the top +} + +void +Seasons::updateSeason(int index, QString name, QDate start, QDate end, int type) +{ + seasons[index].setName(name); + seasons[index].setStart(start); + seasons[index].setEnd(end); + seasons[index].setType(type); + + // save changes away + writeSeasons(); + +} + +void +Seasons::deleteSeason(int index) +{ + // now delete! + seasons.removeAt(index); + writeSeasons(); +} + +void +Seasons::writeSeasons() +{ + // update seasons.xml + QString file = QString(home.absolutePath() + "/seasons.xml"); + SeasonParser::serialize(file, seasons); + + seasonsChanged(); // signal! +} diff --git a/src/Season.h b/src/Season.h index 48c80500f..46ea7e164 100644 --- a/src/Season.h +++ b/src/Season.h @@ -36,6 +36,7 @@ class Season QDate getStart(); QDate getEnd(); QString getName(); + int days() { return _days; } // how many days in the season, -1 if never ending int getType(); @@ -43,12 +44,21 @@ class Season void setEnd(QDate _end); void setName(QString _name); void setType(int _type); + QUuid id() const { return _id; } + void setId(QUuid x) { _id = x; } + QVector &load() { return _load; } + private: - QDate start; - QDate end; - QString name; + QDate start; // first day of the season + QDate end; // last day of the season + int _days; // how many days in this season? + QUuid _id; // unique id + + QString name; // name, typically users name them by year e.g. "2011 Season" int type; + + QVector _load; // array of daily planned load }; class EditSeasonDialog : public QDialog @@ -73,4 +83,25 @@ class EditSeasonDialog : public QDialog QComboBox *typeEdit; QDateEdit *fromEdit, *toEdit; }; + +class Seasons : public QObject { + + Q_OBJECT; + + public: + Seasons(QDir home) : home(home) { readSeasons(); } + void readSeasons(); + int newSeason(QString name, QDate start, QDate end, int type); + void updateSeason(int index, QString name, QDate start, QDate end, int type); + void deleteSeason(int); + void writeSeasons(); + QList seasons; + + signals: + void seasonsChanged(); + + + private: + QDir home; +}; #endif /* SEASON_H_ */ diff --git a/src/SeasonParser.cpp b/src/SeasonParser.cpp index 2d49f9152..1af8fee03 100644 --- a/src/SeasonParser.cpp +++ b/src/SeasonParser.cpp @@ -37,8 +37,14 @@ bool SeasonParser::endElement( const QString&, const QString&, const QString &qN season.setEnd(seasonDateToDate(buffer.trimmed())); else if (qName == "type") season.setType(buffer.trimmed().toInt()); - else if(qName == "season") - { + else if (qName == "id") + season.setId(QUuid(buffer.trimmed())); + else if (qName == "load") { + season.load().resize(loadcount+1); + season.load()[loadcount] = buffer.trimmed().toInt(); + loadcount++; + } else if(qName == "season") { + if(seasons.size() >= 1) { // only set end date for previous season if // it is not null @@ -53,8 +59,10 @@ bool SeasonParser::endElement( const QString&, const QString&, const QString &qN bool SeasonParser::startElement( const QString&, const QString&, const QString &name, const QXmlAttributes & ) { buffer.clear(); - if(name == "season") + if(name == "season") { season = Season(); + loadcount = 0; + } return TRUE; } @@ -115,16 +123,25 @@ SeasonParser::serialize(QString filename, QListSeasons) // write out to file foreach (Season season, Seasons) { if (season.getType() != Season::temporary) { + + // main attributes out<\n" "\t\t%1\n" "\t\t%2\n" "\t\t%3\n" "\t\t%4\n" - "\t\n") - .arg(season.getName()) - .arg(season.getStart().toString("yyyy-MM-dd")) - .arg(season.getEnd().toString("yyyy-MM-dd")) - .arg(season.getType()); + "\t\t%5\n") .arg(season.getName()) + .arg(season.getStart().toString("yyyy-MM-dd")) + .arg(season.getEnd().toString("yyyy-MM-dd")) + .arg(season.getType()) + .arg(season.id().toString()); + + + // load profile + for (int i=9; i%1\n").arg(season.load()[i]); + + out <\n"); } } diff --git a/src/SeasonParser.h b/src/SeasonParser.h index 93b8145bb..cb3c0b4b3 100644 --- a/src/SeasonParser.h +++ b/src/SeasonParser.h @@ -43,6 +43,7 @@ protected: QDate seasonDateToDate(QString); Season season; QList seasons; + int loadcount; }; #endif //SeasonParser