diff --git a/src/Charts/ChartBar.cpp b/src/Charts/ChartBar.cpp index bf256fa71..5dab0211a 100644 --- a/src/Charts/ChartBar.cpp +++ b/src/Charts/ChartBar.cpp @@ -106,7 +106,7 @@ ChartBar::ChartBar(Context *context) : QWidget(context->mainWindow), context(con menuButton->setStyleSheet("QToolButton { border: none; padding: 0px; }"); menuButton->setAutoFillBackground(false); menuButton->setFixedSize(20*dpiXFactor,20*dpiYFactor); - menuButton->setIcon(iconFromPNG(":images/sidebar/extra.png")); + menuButton->setIcon(iconFromPNG(":images/sidebar/plus.png")); menuButton->setIconSize(QSize(10*dpiXFactor,10*dpiYFactor)); menuButton->setFocusPolicy(Qt::NoFocus); mlayout->addWidget(menuButton); @@ -119,13 +119,12 @@ ChartBar::ChartBar(Context *context) : QWidget(context->mainWindow), context(con connect(menuMapper, SIGNAL(mapped(int)), this, SLOT(triggerContextMenu(int))); barMenu = new QMenu("Add"); - chartMenu = barMenu->addMenu(tr("Add Chart")); + chartMenu = barMenu->addMenu(tr("New ")); - barMenu->addAction(tr("Import Chart..."), context->mainWindow, SLOT(importChart())); + barMenu->addAction(tr("Import ..."), context->mainWindow, SLOT(importChart())); #ifdef GC_HAS_CLOUD_DB - barMenu->addAction(tr("Upload Chart..."), context->mainWindow, SLOT(exportChartToCloudDB())); - barMenu->addAction(tr("Download Chart..."), context->mainWindow, SLOT(addChartFromCloudDB())); + barMenu->addAction(tr("Download ..."), context->mainWindow, SLOT(addChartFromCloudDB())); #endif // menu connect(menuButton, SIGNAL(clicked()), this, SLOT(menuPopup())); diff --git a/src/Core/Context.cpp b/src/Core/Context.cpp index 2a8da5ab2..c1e5c4a90 100644 --- a/src/Core/Context.cpp +++ b/src/Core/Context.cpp @@ -20,6 +20,7 @@ #include "Athlete.h" #include "RideMetric.h" +#include "NavigationModel.h" #include "UserMetricSettings.h" #include "UserMetricParser.h" #include "DataFilter.h" diff --git a/src/Core/Context.h b/src/Core/Context.h index 39506a106..ab6205993 100644 --- a/src/Core/Context.h +++ b/src/Core/Context.h @@ -68,6 +68,7 @@ class Context; class Athlete; class MainWindow; class Tab; +class NavigationModel; class Context : public QObject { @@ -78,6 +79,7 @@ class Context : public QObject ~Context(); // mainwindow state + NavigationModel *nav; int viewIndex; bool showSidebar, showLowbar, showToolbar, showTabbar; int style; @@ -169,6 +171,8 @@ class Context : public QObject void notifyStop() { emit stop(); } void notifySeek(long x) { emit seek(x); } + // date range selection + void notifyDateRangeChanged(DateRange x) { dr_=x; emit dateRangeSelected(x); } void notifyWorkoutsChanged() { emit workoutsChanged(); } void notifyVideoSyncChanged() { emit VideoSyncChanged(); } @@ -243,6 +247,7 @@ class Context : public QObject void autoDownloadEnd(); void autoDownloadProgress(QString, double, int, int); + void dateRangeSelected(DateRange); void rideSelected(RideItem*); // we added/deleted/changed an item diff --git a/src/Core/RideCache.h b/src/Core/RideCache.h index 24d67d8a6..305490cd1 100644 --- a/src/Core/RideCache.h +++ b/src/Core/RideCache.h @@ -135,11 +135,16 @@ class RideCache : public QObject friend class ::LTMPlot; // get weekly performances friend class ::Banister; // get weekly performances friend class ::Leaf; // get weekly performances + friend class ::RideItem; // adds to deletelist in destructor + friend class ::NavigationModel; // checks deletelist during redo/undo Context *context; QDir directory, plannedDirectory; - QVector rides_, reverse_, delete_; + // rides and reverse are the main lists + // delete_ is a list of items to garbage collect (delete later) + // deletelist is a list of items that no longer exist (deleted) + QVector rides_, reverse_, delete_, deletelist; RideCacheModel *model_; bool exiting; double progress_; // percent diff --git a/src/Core/RideItem.cpp b/src/Core/RideItem.cpp index 642b07f08..32eb66dc0 100644 --- a/src/Core/RideItem.cpp +++ b/src/Core/RideItem.cpp @@ -17,6 +17,7 @@ */ #include "RideItem.h" +#include "RideCache.h" #include "RideMetric.h" #include "RideFile.h" #include "RideFileCache.h" @@ -238,6 +239,9 @@ RideFile *RideItem::ride(bool open) RideItem::~RideItem() { + // add to the deleted list + if (context->athlete->rideCache) context->athlete->rideCache->deletelist << this; + //qDebug()<<"deleting:"< +#include #include #include #include @@ -46,9 +47,19 @@ class DateRange : QObject DateRange(const DateRange& other); DateRange(QDate from = QDate(), QDate to = QDate(), QString name ="", QColor=QColor(127,127,127)); DateRange& operator=(const DateRange &); + bool operator!=(const DateRange&other) { + if (other.from != from || other.to != to || other.name != name) return true; + return false; + } + bool operator==(const DateRange&other) { + if (other.from == from && other.to == to && other.name == name) return true; + return false; + } + QDate from, to; QString name; QColor color; // used by R code only + QUuid id; // does this date fall in the range selection ? bool pass(QDate date) { diff --git a/src/Gui/LTMSidebar.cpp b/src/Gui/LTMSidebar.cpp index 8325e802f..e2b891f27 100644 --- a/src/Gui/LTMSidebar.cpp +++ b/src/Gui/LTMSidebar.cpp @@ -323,6 +323,33 @@ LTMSidebar::configChanged(qint32) * Selections Made *----------------------------------------------------------------------*/ +void +LTMSidebar::selectDateRange(DateRange dr) +{ + for(int i=0; iseasons.count(); i++) { + Season s = seasons->seasons.at(i); + if (s.start == dr.from && s.end == dr.to && s.name == dr.name) { + // bingo + dateRangeTree->selectionModel()->clearSelection(); // clear selection + allDateRanges->child(i)->setSelected(true); // select ours + return; + } else { + QStringList names=dr.name.split("/"); + if (names.count() == 2 && s.name == names.at(0)) { + for (int j=0; jselectionModel()->clearSelection(); // clear selection + allDateRanges->child(i)->child(j)->setSelected(true); // select ours + return; + } + } + } + } + } +} + void LTMSidebar::dateRangeTreeWidgetSelectionChanged() { diff --git a/src/Gui/LTMSidebar.h b/src/Gui/LTMSidebar.h index b931bd9ee..689cc6295 100644 --- a/src/Gui/LTMSidebar.h +++ b/src/Gui/LTMSidebar.h @@ -55,6 +55,7 @@ class LTMSidebar : public QWidget public slots: // date range selection and editing + void selectDateRange(DateRange); void dateRangeTreeWidgetSelectionChanged(); void dateRangePopup(QPoint); void dateRangePopup(); diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 0610daa0e..3e7fd3af6 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -271,8 +271,26 @@ MainWindow::MainWindow(const QDir &home) lowbarIcon = iconFromPNG(":images/mac/lowbar.png"); tabbedIcon = iconFromPNG(":images/mac/tabbed.png"); tiledIcon = iconFromPNG(":images/mac/tiled.png"); + backIcon = iconFromPNG(":images/mac/back.png"); + forwardIcon = iconFromPNG(":images/mac/forward.png"); QSize isize(19 *dpiXFactor,19 *dpiYFactor); + back = new QPushButton(this); + back->setIcon(backIcon); + back->setFixedHeight(24 *dpiYFactor); + back->setFixedWidth(32 *dpiYFactor); + back->setIconSize(isize); + back->setStyle(toolStyle); + connect(back, SIGNAL(clicked(bool)), this, SIGNAL(backClicked())); + + forward = new QPushButton(this); + forward->setIcon(forwardIcon); + forward->setFixedHeight(24 *dpiYFactor); + forward->setFixedWidth(32 *dpiYFactor); + forward->setIconSize(isize); + forward->setStyle(toolStyle); + connect(forward, SIGNAL(clicked(bool)), this, SIGNAL(forwardClicked())); + lowbar = new QPushButton(this); lowbar->setIcon(lowbarIcon); lowbar->setFixedHeight(24 *dpiYFactor); @@ -324,11 +342,19 @@ MainWindow::MainWindow(const QDir &home) searchBox->setStyle(toolStyle); searchBox->setFixedWidth(400 * dpiXFactor); searchBox->setFixedHeight(28 * dpiYFactor); + + QWidget *space = new QWidget(this); + space->setAutoFillBackground(false); + space->setFixedWidth(5 * dpiYFactor); + + head->addWidget(space); + head->addWidget(back); + head->addWidget(forward); head->addStretch(); head->addWidget(sidelist); head->addWidget(lowbar); head->addWidget(styleSelector); - head->setFixedHeight(searchBox->height() + (10 *dpiXFactor)); + head->setFixedHeight(searchBox->height() + (16 *dpiXFactor)); connect(searchBox, SIGNAL(searchResults(QStringList)), this, SLOT(setFilter(QStringList))); connect(searchBox, SIGNAL(searchClear()), this, SLOT(clearFilter())); @@ -2199,6 +2225,9 @@ MainWindow::configChanged(qint32) searchBox->setStyleSheet(QString("QLineEdit { background: %1; color: %2; }").arg(GColor(CCHROME).name()).arg(GCColor::invertColor(GColor(CCHROME)).name())); #endif + QString buttonstyle = QString("QPushButton { border: none; background-color: %1; }").arg(CCHROME); + back->setStyleSheet(buttonstyle); + forward->setStyleSheet(buttonstyle); // All platforms QPalette tabbarPalette; diff --git a/src/Gui/MainWindow.h b/src/Gui/MainWindow.h index 4948c692a..83d79dd98 100644 --- a/src/Gui/MainWindow.h +++ b/src/Gui/MainWindow.h @@ -93,6 +93,7 @@ class MainWindow : public QMainWindow // currently selected tab Tab *athleteTab() { return currentTab; } + NewSideBar *newSidebar() { return sidebar; } protected: @@ -112,6 +113,10 @@ class MainWindow : public QMainWindow void setSplash(bool first=false); void clearSplash(); + signals: + void backClicked(); + void forwardClicked(); + public slots: bool eventFilter(QObject*,QEvent*); @@ -273,11 +278,12 @@ class MainWindow : public QMainWindow // Not on Mac so use other types QPushButton *sidelist, *lowbar; + QPushButton *back, *forward; QtSegmentControl *styleSelector; GcToolBar *head; // the icons - QIcon sidebarIcon, lowbarIcon, tabbedIcon, tiledIcon; + QIcon backIcon, forwardIcon, sidebarIcon, lowbarIcon, tabbedIcon, tiledIcon; // tab bar (that supports swtitching on drag and drop) DragBar *tabbar; diff --git a/src/Gui/NavigationModel.cpp b/src/Gui/NavigationModel.cpp new file mode 100644 index 000000000..da4aec0fc --- /dev/null +++ b/src/Gui/NavigationModel.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2020 Mark Liversedge (liversedge@gmail.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "NavigationModel.h" + +#include "RideCache.h" +// a little too intertwined with these two, +// probably needs refactoring out at some point. +#include "LTMSidebar.h" +#include "NewSideBar.h" +#include "MainWindow.h" + + +NavigationModel::NavigationModel(Tab *tab) : tab(tab), block(false), viewinit(false), iteminit(false), drinit(false) +{ + connect(tab, SIGNAL(viewChanged(int)), this, SLOT(viewChanged(int))); + connect(tab, SIGNAL(rideItemSelected(RideItem*)), this, SLOT(rideChanged(RideItem*))); + connect(static_cast(tab->view(0))->sidebar, SIGNAL(dateRangeChanged(DateRange)), this, SLOT(dateChanged(DateRange))); + connect(tab->context->mainWindow, SIGNAL(backClicked()), this, SLOT(back())); + connect(tab->context->mainWindow, SIGNAL(forwardClicked()), this, SLOT(forward())); + + stackpointer=-1; +} + +NavigationModel::~NavigationModel() +{ +} + +void +NavigationModel::addToStack(NavigationEvent &event) +{ + if (stackpointer == -1) { + // empty + stack.clear(); + stack << event; + stackpointer++; + + } else if (stackpointer == (stack.count()-1)) { + + // end, just append + stack << event; + stackpointer++; + + } else if (stackpointer < (stack.count()-1)) { + + // middle, truncate + stack.remove(stackpointer+1, stack.count() - (stackpointer+1)); + stack << event; + stackpointer++; + + } +} + +void +NavigationModel::rideChanged(RideItem *x) +{ + if (block) return; + + // initial values + if (iteminit == false) { + iteminit = true; + item = x; + return; + } + + if (item != x) { + + // add to recent + if (!recent.contains(x)) recent << x; + + // add to the stack -- truncate if needed + NavigationEvent add(NavigationEvent::RIDE, x); + add.before.setValue(item); + addToStack(add); + + item = x; + } +} + +void +NavigationModel::dateChanged(DateRange x) +{ + if (block) return; + + // initial values + if (drinit == false) { + drinit = true; + dr = x; + return; + } + + if (dr != x) { + + // add to the stack + NavigationEvent add(NavigationEvent::DATERANGE, x); + add.before.setValue(dr); + addToStack(add); + + dr = x; + } +} + +void +NavigationModel::viewChanged(int x) +{ + if (block) return; + + // initial values + if (viewinit == false) { + viewinit = true; + view = x; + return; + } + + if (view != x) { + + // add to the stack + NavigationEvent add(NavigationEvent::VIEW, x); + add.before.setValue(view); + addToStack(add); + + view = x; + } +} + +void +NavigationModel::action(bool redo, NavigationEvent event) +{ + block = true; // don't observe events during redo/undo + + switch(event.type) { + case NavigationEvent::VIEW: + { + int view = redo ? event.after.toInt() : event.before.toInt(); + tab->selectView(view); + + // new side bar uses a different id, which will + // eventually be refactored to be the only id + // but for now we need to map this + int id=0; + switch(view) { + case 0: id=2; break; // trends + case 1: id=3; break; // analysis + case 2: id=0; break; // diary + case 3: id=5; break; // train + } + tab->context->mainWindow->newSidebar()->setItemSelected(id, true); + } + break; + + case NavigationEvent::RIDE: + { + RideItem *item = redo ? event.after.value() : event.before.value(); + + // don't select deleted rides (!!) + if (!tab->context->athlete->rideCache->deletelist.contains(item)) + tab->context->athlete->selectRideFile(item->fileName); + } + break; + + case NavigationEvent::DATERANGE: + { + DateRange dr = redo ? event.after.value() : event.before.value(); + static_cast(tab->view(0))->sidebar->selectDateRange(dr); + } + break; + } + + block = false; +} + +void +NavigationModel::back() +{ + // are we the current tab? + if (tab->context->mainWindow->athleteTab() == tab) { + if (stackpointer >= 0) { + action(false, stack[stackpointer]); + stackpointer--; + } + } +} + +void +NavigationModel::forward() +{ + // are we the current tab? + if (tab->context->mainWindow->athleteTab() == tab) { + if ((stackpointer+1) < stack.count() && stack.count()) { + stackpointer++; + action(true, stack[stackpointer]); + } + } +} diff --git a/src/Gui/NavigationModel.h b/src/Gui/NavigationModel.h new file mode 100644 index 000000000..6d37d5f12 --- /dev/null +++ b/src/Gui/NavigationModel.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020 Mark Liversedge (liversedge@gmail.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "Tab.h" +#include "TimeUtils.h" +#include "Context.h" +#include "Athlete.h" +#include "RideItem.h" + +class NavigationEvent { + +public: + + // events we observe and replay is a limited subset mostly + // about changing views, dates and ride selections + enum NavigationEventType { VIEW=0, TAB, RIDE, DATERANGE, FILTER } type; + + NavigationEvent(NavigationEventType t, int v) : type(t) { after.setValue(v); } + NavigationEvent(NavigationEventType t, DateRange v) : type(t) { after.setValue(v); } + NavigationEvent(NavigationEventType t, RideItem* v) : type(t) { after.setValue(v); } + NavigationEvent(NavigationEventType t, QString v) : type(t) { after.setValue(v); } + + // before is updated by the navigation model + QVariant before, after; +}; + +// +// Navigation is for the athlete tab -- not mainwindow. +// Remember: multiple athletes can be opened at once. +// +class NavigationModel : public QObject +{ + Q_OBJECT + +public: + + NavigationModel(Tab *tab); + ~NavigationModel(); + + // keep a track of the rides we've looked + // at recently-- might want to quick link + // to these in the future ... + QVector recent; + +public slots: + + void viewChanged(int); + void rideChanged(RideItem*); + void dateChanged(DateRange dr); + + void back(); + void forward(); + void action(bool redo, NavigationEvent); // redo/undo the event + +private: + + Tab *tab; + + // block observer when undo/redo is active + bool block; + + // current state, before an event arrives + int view; // which view is selected + DateRange dr; + RideItem *item; + + // have we seen first values for: + bool viewinit, drinit, iteminit; + + // the stack + void addToStack(NavigationEvent&); // truncates stack if needed + int stackpointer; + QVector stack; +}; diff --git a/src/Gui/Tab.cpp b/src/Gui/Tab.cpp index 7eb79b557..1d66473e8 100644 --- a/src/Gui/Tab.cpp +++ b/src/Gui/Tab.cpp @@ -25,6 +25,7 @@ #include "IntervalTreeView.h" #include "MainWindow.h" #include "Colors.h" +#include "NavigationModel.h" #include @@ -88,6 +89,12 @@ Tab::Tab(Context *context) : QWidget(context->mainWindow), context(context) chartSettings->setMaximumHeight(600); chartSettings->hide(); + // navigation model after main items as it uses the observer + // pattern on views etc, so they need to be created first + // but we need to get setup before ride selection happens + // below, so we can observe the iniital ride select + nav = new NavigationModel(this); + // cpx aggregate cache check connect(context,SIGNAL(rideSelected(RideItem*)), this, SLOT(rideSelected(RideItem*))); @@ -100,9 +107,11 @@ Tab::Tab(Context *context) : QWidget(context->mainWindow), context(context) break; } } + // otherwise just the latest - if (context->currentRideItem() == NULL && context->athlete->rideCache->rides().count() != 0) + if (context->currentRideItem() == NULL && context->athlete->rideCache->rides().count() != 0) { context->athlete->selectRideFile(context->athlete->rideCache->rides().last()->fileName); + } } Tab::~Tab() @@ -112,6 +121,7 @@ Tab::~Tab() delete trainView; delete diaryView; delete views; + delete nav; } RideNavigator * @@ -174,6 +184,8 @@ Tab::view(int index) void Tab::selectView(int index) { + emit viewChanged(index); + // first we deselect the current view(views->currentIndex())->setSelected(false); @@ -187,6 +199,8 @@ Tab::selectView(int index) void Tab::rideSelected(RideItem*) { + emit rideItemSelected(context->ride); + // update the ride property on all widgets // to let them know they need to replot new // selected ride (now the tree is up to date) diff --git a/src/Gui/Tab.h b/src/Gui/Tab.h index 36b0c0612..7638aae54 100644 --- a/src/Gui/Tab.h +++ b/src/Gui/Tab.h @@ -26,6 +26,7 @@ class RideNavigator; class MainWindow; class ProgressLine; class QPaintEvent; +class NavigationModel; class Tab: public QWidget { @@ -41,15 +42,21 @@ class Tab: public QWidget int currentView() { return views->currentIndex(); } TabView *view(int index); + NavigationModel *nav; // back/forward for this tab RideNavigator *rideNavigator(); // to get logical headings protected: friend class ::MainWindow; + friend class ::NavigationModel; Context *context; signals: + void viewChanged(int); + void rideItemSelected(RideItem*); + void dateRangeSelected(DateRange); + public slots: void rideSelected(RideItem*); diff --git a/src/Gui/Views.cpp b/src/Gui/Views.cpp index 5745f4d3a..2714508aa 100644 --- a/src/Gui/Views.cpp +++ b/src/Gui/Views.cpp @@ -117,7 +117,7 @@ DiaryView::setRide(RideItem*ride) void DiaryView::dateRangeChanged(DateRange dr) { - context->dr_ = dr; + //context->notifyDateRangeChanged(dr); // diary view deprecated and not part of navigation model page()->setProperty("dateRange", QVariant::fromValue(dr)); } @@ -130,18 +130,18 @@ DiaryView::isBlank() HomeView::HomeView(Context *context, QStackedWidget *controls) : TabView(context, VIEW_HOME) { - LTMSidebar *s = new LTMSidebar(context); + sidebar = new LTMSidebar(context); HomeWindow *h = new HomeWindow(context, "home", "Trends"); controls->addWidget(h->controls()); controls->setCurrentIndex(0); BlankStateHomePage *b = new BlankStateHomePage(context); - setSidebar(s); + setSidebar(sidebar); setPage(h); setBlank(b); setBottom(new ComparePane(context, this, ComparePane::season)); - connect(s, SIGNAL(dateRangeChanged(DateRange)), this, SLOT(dateRangeChanged(DateRange))); + connect(sidebar, SIGNAL(dateRangeChanged(DateRange)), this, SLOT(dateRangeChanged(DateRange))); connect(this, SIGNAL(onSelectionChanged()), this, SLOT(justSelected())); connect(bottomSplitter(), SIGNAL(compareChanged(bool)), this, SLOT(compareChanged(bool))); connect(bottomSplitter(), SIGNAL(compareClear()), bottom(), SLOT(clear())); @@ -161,7 +161,8 @@ HomeView::compareChanged(bool state) void HomeView::dateRangeChanged(DateRange dr) { - context->dr_ = dr; + emit dateChanged(dr); + context->notifyDateRangeChanged(dr); page()->setProperty("dateRange", QVariant::fromValue(dr)); } bool @@ -176,7 +177,7 @@ HomeView::justSelected() { if (isSelected()) { // force date range refresh - static_cast(sidebar())->dateRangeTreeWidgetSelectionChanged(); + static_cast(sidebar)->dateRangeTreeWidgetSelectionChanged(); } } diff --git a/src/Gui/Views.h b/src/Gui/Views.h index 66f5cabf7..048a07e19 100644 --- a/src/Gui/Views.h +++ b/src/Gui/Views.h @@ -92,6 +92,7 @@ private slots: void onAutoHideChanged(bool enabled); }; +class LTMSidebar; class HomeView : public TabView { Q_OBJECT @@ -101,6 +102,10 @@ class HomeView : public TabView HomeView(Context *context, QStackedWidget *controls); ~HomeView(); + LTMSidebar *sidebar; + + signals: + void dateChanged(DateRange); public slots: diff --git a/src/Resources/application.qrc b/src/Resources/application.qrc index 468f6a68d..9761c95d4 100644 --- a/src/Resources/application.qrc +++ b/src/Resources/application.qrc @@ -139,6 +139,8 @@ images/toolbar/popbutton.png images/toolbar/flipbutton.png images/splashscreen.png + images/mac/back.png + images/mac/forward.png images/mac/compose.png images/mac/download.png images/mac/share.png diff --git a/src/Resources/images/mac/back.png b/src/Resources/images/mac/back.png new file mode 100644 index 000000000..9b043b867 Binary files /dev/null and b/src/Resources/images/mac/back.png differ diff --git a/src/Resources/images/mac/forward.png b/src/Resources/images/mac/forward.png new file mode 100644 index 000000000..1fba38c09 Binary files /dev/null and b/src/Resources/images/mac/forward.png differ diff --git a/src/src.pro b/src/src.pro index 1f8a71271..0e92db2a8 100644 --- a/src/src.pro +++ b/src/src.pro @@ -723,7 +723,7 @@ HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/C Gui/SaveDialogs.h Gui/SearchBox.h Gui/SearchFilterBox.h Gui/SolveCPDialog.h Gui/Tab.h Gui/TabView.h Gui/ToolsRhoEstimator.h \ Gui/Views.h Gui/BatchExportDialog.h Gui/DownloadRideDialog.h Gui/ManualRideDialog.h Gui/NewMainWindow.h Gui/NewSideBar.h \ Gui/MergeActivityWizard.h Gui/RideImportWizard.h Gui/SplitActivityWizard.h Gui/SolverDisplay.h Gui/MetricSelect.h \ - Gui/AddChartWizard.h + Gui/AddChartWizard.h Gui/NavigationModel.h # metrics and models HEADERS += Metrics/Banister.h Metrics/CPSolver.h Metrics/Estimator.h Metrics/ExtendedCriticalPower.h Metrics/HrZones.h Metrics/PaceZones.h \ @@ -818,7 +818,7 @@ SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.cpp Gui/SearchBox.cpp Gui/SearchFilterBox.cpp Gui/SolveCPDialog.cpp Gui/Tab.cpp Gui/TabView.cpp Gui/ToolsRhoEstimator.cpp Gui/Views.cpp \ Gui/BatchExportDialog.cpp Gui/DownloadRideDialog.cpp Gui/ManualRideDialog.cpp Gui/EditUserMetricDialog.cpp Gui/NewMainWindow.cpp Gui/NewSideBar.cpp \ Gui/MergeActivityWizard.cpp Gui/RideImportWizard.cpp Gui/SplitActivityWizard.cpp Gui/SolverDisplay.cpp Gui/MetricSelect.cpp \ - Gui/AddChartWizard.cpp + Gui/AddChartWizard.cpp Gui/NavigationModel.cpp ## Models and Metrics SOURCES += Metrics/aBikeScore.cpp Metrics/aCoggan.cpp Metrics/AerobicDecoupling.cpp Metrics/Banister.cpp Metrics/BasicRideMetrics.cpp \