NewSideBar Button ids as an enum class and View Stack Ids (#4688)

Updates the NewSideBar button ids to use an enum class, and viewStack identifiers to provide strong typing, and aid the clarity of the code.
This commit is contained in:
Paul Johnson
2025-08-22 21:47:59 +01:00
committed by GitHub
parent b312996e17
commit cd780b2247
6 changed files with 146 additions and 96 deletions

View File

@@ -211,7 +211,7 @@ AthleteTab::rideSelected(RideItem*)
// as important to be aware that perspectives are loaded
// when the view is selected by the user and no earlier
if (analysisView->page() != NULL) {
context->mainWindow->newSidebar()->setItemSelected(3, true);
context->mainWindow->newSidebar()->setItemSelected(GcSideBarBtnId::ACTIVITIES_BTN, true);
selectView(1);
}
}

View File

@@ -81,7 +81,6 @@
// GUI Widgets
#include "AthleteTab.h"
#include "GcToolBar.h"
#include "NewSideBar.h"
#include "HelpWindow.h"
#include "Perspective.h"
#include "PerspectiveDialog.h"
@@ -115,6 +114,12 @@
#include "WindowsCrashHandler.cpp"
#endif
// The order of the GcViewStackIdx values below must match the viewStack widget's tab order, see the MainWindow's constructor below.
namespace GcViewStackIdx {
// use constexpr instead of enum class to prevent unecessary casting
constexpr int SELECT_ATHLETE_VIEW = 0;
constexpr int ATHLETE_TAB_STACK = 1;
};
// We keep track of all theopen mainwindows
QList<MainWindow *> mainwindows;
@@ -207,34 +212,34 @@ MainWindow::MainWindow(const QDir &home)
HelpWhatsThis *helpNewSideBar = new HelpWhatsThis(sidebar);
sidebar->setWhatsThis(helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar));
sidebar->addItem(QImage(":sidebar/athlete.png"), tr("athletes"), 0, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Athletes));
sidebar->setItemEnabled(1, false);
// The ids of the sidebar buttons below are defined in NewSideBar.h
sidebar->addItem(QImage(":sidebar/athlete.png"), tr("athletes"), GcSideBarBtnId::SELECT_ATHLETE_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Athletes));
sidebar->addItem(QImage(":sidebar/plan.png"), tr("plan"), 1), tr("Feature not implemented yet");
sidebar->setItemEnabled(1, false);
sidebar->addItem(QImage(":sidebar/plan.png"), tr("plan"), GcSideBarBtnId::PLAN_BTN, tr("Feature not implemented yet"));
sidebar->setItemEnabled(GcSideBarBtnId::PLAN_BTN, false);
sidebar->addItem(QImage(":sidebar/trends.png"), tr("trends"), 2, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Trends));
sidebar->addItem(QImage(":sidebar/assess.png"), tr("activities"), 3, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Rides));
sidebar->setItemSelected(3, true);
sidebar->addItem(QImage(":sidebar/trends.png"), tr("trends"), GcSideBarBtnId::TRENDS_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Trends));
sidebar->addItem(QImage(":sidebar/reflect.png"), tr("reflect"), 4), tr("Feature not implemented yet");
sidebar->setItemEnabled(4, false);
sidebar->addItem(QImage(":sidebar/assess.png"), tr("activities"), GcSideBarBtnId::ACTIVITIES_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Rides));
sidebar->addItem(QImage(":sidebar/train.png"), tr("train"), 5, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Train));
sidebar->addItem(QImage(":sidebar/reflect.png"), tr("reflect"), GcSideBarBtnId::REFLECT_BTN, tr("Feature not implemented yet"));
sidebar->setItemEnabled(GcSideBarBtnId::REFLECT_BTN, false);
sidebar->addItem(QImage(":sidebar/train.png"), tr("train"), GcSideBarBtnId::TRAIN_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Train));
sidebar->addStretch();
sidebar->addItem(QImage(":sidebar/apps.png"), tr("apps"), 6, tr("Feature not implemented yet"));
sidebar->setItemEnabled(6, false);
sidebar->addItem(QImage(":sidebar/apps.png"), tr("apps"), GcSideBarBtnId::APPS_BTN, tr("Feature not implemented yet"));
sidebar->setItemEnabled(GcSideBarBtnId::APPS_BTN, false);
sidebar->addStretch();
// we can click on the quick icons, but they aren't selectable views
sidebar->addItem(QImage(":sidebar/sync.png"), tr("sync"), 7, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Sync));
sidebar->setItemSelectable(7, false);
sidebar->addItem(QImage(":sidebar/prefs.png"), tr("options"), 8, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Options));
sidebar->setItemSelectable(8, false);
sidebar->addItem(QImage(":sidebar/sync.png"), tr("sync"), GcSideBarBtnId::SYNC_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Sync));
sidebar->setItemSelectable(GcSideBarBtnId::SYNC_BTN, false);
sidebar->addItem(QImage(":sidebar/prefs.png"), tr("options"), GcSideBarBtnId::OPTIONS_BTN, helpNewSideBar->getWhatsThisText(HelpWhatsThis::ScopeBar_Options));
sidebar->setItemSelectable(GcSideBarBtnId::OPTIONS_BTN, false);
connect(sidebar, SIGNAL(itemClicked(int)), this, SLOT(sidebarClicked(int)));
connect(sidebar, SIGNAL(itemSelected(int)), this, SLOT(sidebarSelected(int)));
connect(sidebar, SIGNAL(itemClicked(GcSideBarBtnId)), this, SLOT(sidebarClicked(GcSideBarBtnId)));
connect(sidebar, SIGNAL(itemSelected(GcSideBarBtnId)), this, SLOT(sidebarSelected(GcSideBarBtnId)));
/*----------------------------------------------------------------------
* What's this Context Help
@@ -416,6 +421,7 @@ MainWindow::MainWindow(const QDir &home)
tabbar->setDocumentMode(true);
#endif
// Note: The order of the viewStack tabs below, must match the GcViewStackIdx definitions above.
athleteView = new AthleteView(context);
viewStack = new QStackedWidget(this);
viewStack->addWidget(athleteView);
@@ -1217,37 +1223,32 @@ MainWindow::support()
}
void
MainWindow::sidebarClicked(int id)
MainWindow::sidebarClicked(GcSideBarBtnId id)
{
// sync quick link
if (id == 7) checkCloud();
// prefs
if (id == 8) showOptions();
switch (id) {
case GcSideBarBtnId::SYNC_BTN: checkCloud(); break; // sync quick link
case GcSideBarBtnId::OPTIONS_BTN: showOptions(); break; // prefs
}
}
void
MainWindow::sidebarSelected(int id)
MainWindow::sidebarSelected(GcSideBarBtnId id)
{
switch (id) {
case 0: selectAthlete(); break;
case 1: // plan not written yet
break;
case 2: selectTrends(); break;
case 3: selectAnalysis(); break;
case 4: // reflect not written yet
break;
case 5: selectTrain(); break;
case 6: // apps not written yet
break;
case GcSideBarBtnId::SELECT_ATHLETE_BTN: selectAthlete(); break;
case GcSideBarBtnId::PLAN_BTN: break; // plan not written yet
case GcSideBarBtnId::TRENDS_BTN: selectTrends(); break;
case GcSideBarBtnId::ACTIVITIES_BTN: selectAnalysis(); break;
case GcSideBarBtnId::REFLECT_BTN: break; // reflect not written yet
case GcSideBarBtnId::TRAIN_BTN: selectTrain(); break;
case GcSideBarBtnId::APPS_BTN: break;// apps not written yet
}
}
void
MainWindow::selectAthlete()
{
viewStack->setCurrentIndex(0);
viewStack->setCurrentIndex(GcViewStackIdx::SELECT_ATHLETE_VIEW);
back->hide();
forward->hide();
perspectiveSelector->hide();
@@ -1260,8 +1261,8 @@ MainWindow::selectAnalysis()
{
resetPerspective(1);
//currentTab->analysisView->setPerspectives(perspectiveSelector);
viewStack->setCurrentIndex(1);
sidebar->setItemSelected(3, true);
viewStack->setCurrentIndex(GcViewStackIdx::ATHLETE_TAB_STACK);
sidebar->setItemSelected(GcSideBarBtnId::ACTIVITIES_BTN, true);
currentAthleteTab->selectView(1);
back->show();
forward->show();
@@ -1276,8 +1277,8 @@ MainWindow::selectTrain()
{
resetPerspective(3);
//currentTab->trainView->setPerspectives(perspectiveSelector);
viewStack->setCurrentIndex(1);
sidebar->setItemSelected(5, true);
viewStack->setCurrentIndex(GcViewStackIdx::ATHLETE_TAB_STACK);
sidebar->setItemSelected(GcSideBarBtnId::TRAIN_BTN, true);
currentAthleteTab->selectView(3);
back->show();
forward->show();
@@ -1292,7 +1293,7 @@ MainWindow::selectDiary()
{
resetPerspective(2);
//currentTab->diaryView->setPerspectives(perspectiveSelector);
viewStack->setCurrentIndex(1);
viewStack->setCurrentIndex(GcViewStackIdx::ATHLETE_TAB_STACK);
currentAthleteTab->selectView(2);
back->show();
forward->show();
@@ -1307,8 +1308,8 @@ MainWindow::selectTrends()
{
resetPerspective(0);
//currentTab->homeView->setPerspectives(perspectiveSelector);
viewStack->setCurrentIndex(1);
sidebar->setItemSelected(2, true);
viewStack->setCurrentIndex(GcViewStackIdx::ATHLETE_TAB_STACK);
sidebar->setItemSelected(GcSideBarBtnId::TRENDS_BTN, true);
currentAthleteTab->selectView(0);
back->show();
forward->show();
@@ -2269,18 +2270,18 @@ MainWindow::saveGCState(Context *context)
void
MainWindow::restoreGCState(Context *context)
{
if (viewStack->currentIndex() != 0) {
if (viewStack->currentIndex() != GcViewStackIdx::SELECT_ATHLETE_VIEW) {
// not on athlete view...
resetPerspective(currentAthleteTab->currentView()); // will lazy load, hence doing it first
// restore window state from the supplied context
switch(currentAthleteTab->currentView()) {
case 0: sidebar->setItemSelected(2,true); break;
case 1: sidebar->setItemSelected(3,true); break;
case 0: sidebar->setItemSelected(GcSideBarBtnId::TRENDS_BTN,true); break;
case 1: sidebar->setItemSelected(GcSideBarBtnId::ACTIVITIES_BTN,true); break;
case 2: break; // diary not an icon
case 3: sidebar->setItemSelected(5, true); break;
default: sidebar->setItemSelected(0, true); break;
case 3: sidebar->setItemSelected(GcSideBarBtnId::TRAIN_BTN, true); break;
default: sidebar->setItemSelected(GcSideBarBtnId::SELECT_ATHLETE_BTN, true); break;
}
}

View File

@@ -20,6 +20,7 @@
#ifndef _GC_MainWindow_h
#define _GC_MainWindow_h 1
#include "GoldenCheetah.h"
#include "NewSideBar.h"
#include <QDir>
#include <QSqlDatabase>
@@ -175,8 +176,8 @@ class MainWindow : public QMainWindow
void switchAthleteTab(int index); // for switching between one tab and another
// sidebar selecting views and actions
void sidebarClicked(int id);
void sidebarSelected(int id);
void sidebarClicked(GcSideBarBtnId id);
void sidebarSelected(GcSideBarBtnId id);
// Athlete Backup
void setBackupAthleteMenu();

View File

@@ -153,17 +153,12 @@ NavigationModel::action(bool redo, NavigationEvent event)
{
view = redo ? event.after.toInt() : event.before.toInt();
// 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
switch (view) {
case 0: tab->context->mainWindow->selectTrends(); break;
case 1: tab->context->mainWindow->selectAnalysis(); break;
case 2: tab->context->mainWindow->selectDiary(); break;
case 3: tab->context->mainWindow->selectTrain(); break;
}
tab->context->mainWindow->sidebarSelected(id);
}
break;

View File

@@ -1,3 +1,21 @@
/*
* 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 "Context.h"
#include "NewSideBar.h"
#include "Colors.h"
@@ -11,7 +29,7 @@ NewSideBar::NewSideBar(Context *context, QWidget *parent) : QWidget(parent), con
{
setFixedWidth(gl_itemwidth *dpiXFactor);
setAutoFillBackground(true);
lastid=0;
lastid=GcSideBarBtnId::NO_BUTTON_SET;
QVBoxLayout *mainlayout = new QVBoxLayout(this);
mainlayout->setSpacing(0);
@@ -35,18 +53,18 @@ NewSideBar::NewSideBar(Context *context, QWidget *parent) : QWidget(parent), con
}
void
NewSideBar::clicked(int id)
NewSideBar::clicked(GcSideBarBtnId id)
{
// un selectable item was clicked (e.g. symc or settings)
emit itemClicked(id);
}
void
NewSideBar::selected(int id)
NewSideBar::selected(GcSideBarBtnId id)
{
// we selected one, so need to set it selected
// and deselect everyone else
QMapIterator<int,NewSideBarItem*>i(items);
QMapIterator<GcSideBarBtnId,NewSideBarItem*>i(items);
while(i.hasNext()) {
i.next();
if (i.key() == id) i.value()->setSelected(true);
@@ -56,16 +74,15 @@ NewSideBar::selected(int id)
emit itemSelected(id);
}
int
NewSideBar::addItem(QImage icon, QString name, int id, QString whatsThisText)
GcSideBarBtnId
NewSideBar::addItem(QImage icon, const QString& name, GcSideBarBtnId id, const QString& whatsThisText)
{
// allocated an id
if (id == -1) id=lastid++;
NewSideBarItem *add = new NewSideBarItem(this, id, icon, name);
if (!whatsThisText.isEmpty()) add->setWhatsThis(whatsThisText);
layout->addWidget(add);
items.insert(id, add);
if (id != GcSideBarBtnId::NO_BUTTON_SET) {
NewSideBarItem *add = new NewSideBarItem(this, id, icon, name);
if (!whatsThisText.isEmpty()) add->setWhatsThis(whatsThisText);
layout->addWidget(add);
items.insert(id, add);
}
return id;
}
@@ -80,14 +97,14 @@ NewSideBar::addStretch()
// is it shown, is it usable?
void
NewSideBar::setItemVisible(int id, bool x)
NewSideBar::setItemVisible(GcSideBarBtnId id, bool x)
{
NewSideBarItem *item = items.value(id, NULL);
if (item) item->setVisible(x);
}
void
NewSideBar::setItemEnabled(int id, bool x)
NewSideBar::setItemEnabled(GcSideBarBtnId id, bool x)
{
NewSideBarItem *item = items.value(id, NULL);
if (item) item->setEnabled(x);
@@ -95,14 +112,14 @@ NewSideBar::setItemEnabled(int id, bool x)
// can we select it, select it by program?
void
NewSideBar::setItemSelectable(int id, bool x)
NewSideBar::setItemSelectable(GcSideBarBtnId id, bool x)
{
NewSideBarItem *item = items.value(id, NULL);
if (item) item->setSelectable(x);
}
void
NewSideBar::setItemSelected(int id, bool x)
NewSideBar::setItemSelected(GcSideBarBtnId id, bool x)
{
NewSideBarItem *item = items.value(id, NULL);
if (item) item->setSelected(x);
@@ -131,7 +148,7 @@ NewSideBar::configChanged(qint32)
middle->setStyleSheet(style);
}
NewSideBarItem::NewSideBarItem(NewSideBar *sidebar, int id, QImage icon, QString name) : QWidget(sidebar), sidebar(sidebar), id(id), icon(icon), name(name)
NewSideBarItem::NewSideBarItem(NewSideBar *sidebar, GcSideBarBtnId id, QImage icon, QString name) : QWidget(sidebar), sidebar(sidebar), id(id), icon(icon), name(name)
{
clicked = selected = false;
selectable = enabled = true;

View File

@@ -1,13 +1,48 @@
/*
* 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
*/
#ifndef _GC_NewSideBar_h
#define _GC_NewSideBar_h 1
#include <QWidget>
#include <QMap>
#include <QVBoxLayout>
enum class GcSideBarBtnId : int {
NO_BUTTON_SET = -1,
SELECT_ATHLETE_BTN = 0,
PLAN_BTN = 1,
TRENDS_BTN = 2,
ACTIVITIES_BTN = 3,
REFLECT_BTN = 4,
TRAIN_BTN = 5,
APPS_BTN = 6,
SYNC_BTN = 7,
OPTIONS_BTN = 8
};
class Context;
class NewSideBarItem;
class NewSideBar : public QWidget
{
Q_OBJECT
Q_ENUM(GcSideBarBtnId)
friend class ::NewSideBarItem;
@@ -16,32 +51,31 @@ class NewSideBar : public QWidget
public slots:
// managing items - the id can be assigned or will get a default
// it returns the id used
int addItem(QImage icon, QString name, int id=-1, QString whatsThisText="");
// managing items - addItem returns the id of the button added, or NO_BUTTON_SET.
GcSideBarBtnId addItem(QImage icon, const QString& name, GcSideBarBtnId id, const QString& whatsThisText);
// leave a gap- we have main icons, gap, apps, gap, sync, prefs
void addStretch();
// is it shown, is it usable?
void setItemVisible(int id, bool);
void setItemEnabled(int id, bool);
void setItemVisible(GcSideBarBtnId id, bool);
void setItemEnabled(GcSideBarBtnId id, bool);
// can we select it, select it by program?
void setItemSelectable(int id, bool);
void setItemSelected(int id, bool);
void setItemSelectable(GcSideBarBtnId id, bool);
void setItemSelected(GcSideBarBtnId id, bool);
// config changed
void configChanged(qint32);
// called by children
void clicked(int id);
void selected(int id);
void clicked(GcSideBarBtnId id);
void selected(GcSideBarBtnId id);
signals:
void itemSelected(int id);
void itemClicked(int id);
void itemSelected(GcSideBarBtnId id);
void itemClicked(GcSideBarBtnId id);
protected:
Context *context;
@@ -49,9 +83,9 @@ class NewSideBar : public QWidget
private:
QWidget *top, *middle, *bottom; // bars at top and the bottom
QMap<int,NewSideBarItem*> items;
QMap<GcSideBarBtnId,NewSideBarItem*> items;
int lastid; // when autoallocating
GcSideBarBtnId lastid; // when autoallocating
QVBoxLayout *layout;
};
@@ -62,7 +96,7 @@ class NewSideBarItem : public QWidget
public:
NewSideBarItem(NewSideBar *sidebar, int id, QImage icon, QString name);
NewSideBarItem(NewSideBar *sidebar, GcSideBarBtnId id, QImage icon, QString name);
void setSelectable(bool);
void setEnabled(bool);
@@ -87,7 +121,7 @@ class NewSideBarItem : public QWidget
private:
NewSideBar *sidebar; // for emitting signals
int id;
GcSideBarBtnId id;
// pre-rendered/calculated icons and colors
QImage icon;
@@ -103,3 +137,5 @@ class NewSideBarItem : public QWidget
bool enabled;
bool clicked;
};
#endif // _GC_NewSideBar_h