New Sidebar and deprecate Scope Bar
.. remove the old scope bar in favour of a more modern sidebar as we transition the UI to a new design. .. the newmainwindow approach is not practical, as making 2 UX coexist at the same time was impossible and would lead to major issues. .. note a number of views are on the sidebar but disabled, they will be added over time.
@@ -290,8 +290,8 @@ GcSplitterHandle::init(QString title, Qt::Orientation orientation,
|
||||
// set handle size according to font metric
|
||||
QFont font;
|
||||
QFontMetrics fm(font);
|
||||
bigHandle = fm.height() + 5;
|
||||
smallHandle = fm.height() + 2;
|
||||
bigHandle = fm.height() + 8;
|
||||
smallHandle = fm.height() + 5;
|
||||
|
||||
// use the sizes as set
|
||||
if (metal) setFixedHeight(bigHandle);
|
||||
@@ -347,7 +347,7 @@ GcSplitterHandle::addActions(QList<QAction*> actions)
|
||||
QToolButton *p = new QToolButton(this);
|
||||
p->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
||||
p->setAutoFillBackground(false);
|
||||
p->setFixedSize(20*dpiXFactor,20*dpiYFactor);
|
||||
p->setFixedSize(22*dpiXFactor,22*dpiYFactor);
|
||||
p->setIcon(action->icon());
|
||||
p->setIconSize(QSize(10*dpiXFactor,10*dpiYFactor));
|
||||
p->setFocusPolicy(Qt::NoFocus);
|
||||
@@ -402,7 +402,7 @@ GcSplitterHandle::paintBackground(QPaintEvent *)
|
||||
GcSplitterControl::GcSplitterControl(QWidget *parent) : QToolBar(parent)
|
||||
{
|
||||
setContentsMargins(0,0,0,0);
|
||||
setFixedHeight(20 *dpiYFactor);
|
||||
setFixedHeight(22 *dpiYFactor);
|
||||
setIconSize(QSize(14 *dpiXFactor,14 *dpiYFactor));
|
||||
setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||
setAutoFillBackground(false);
|
||||
@@ -429,8 +429,8 @@ GcSplitterControl::paintBackground(QPaintEvent *)
|
||||
// setup a painter and the area to paint
|
||||
QPainter painter(this);
|
||||
|
||||
QLinearGradient active = GCColor::linearGradient(20 *dpiYFactor, true);
|
||||
QLinearGradient inactive = GCColor::linearGradient(20 *dpiYFactor, false);
|
||||
QLinearGradient active = GCColor::linearGradient(22 *dpiYFactor, true);
|
||||
QLinearGradient inactive = GCColor::linearGradient(22 *dpiYFactor, false);
|
||||
|
||||
// fill with a linear gradient
|
||||
painter.setPen(Qt::NoPen);
|
||||
|
||||
@@ -24,7 +24,7 @@ GcToolBar::GcToolBar(QWidget *parent) : QWidget(parent)
|
||||
//Height will be set when widget is added in MainWindow
|
||||
setContentsMargins(0,0,0,0);
|
||||
layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(10 *dpiXFactor);
|
||||
layout->setSpacing(5 *dpiXFactor);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QAction>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include "Colors.h"
|
||||
|
||||
class GcToolBar : public QWidget
|
||||
{
|
||||
@@ -48,10 +49,10 @@ class Spacer : public QWidget
|
||||
{
|
||||
public:
|
||||
Spacer(QWidget *parent) : QWidget(parent) {
|
||||
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
setSizePolicy(sizePolicy);
|
||||
}
|
||||
QSize sizeHint() const { return QSize(10, 1); }
|
||||
QSize sizeHint() const { return QSize(40*dpiXFactor, 1); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -88,9 +88,9 @@
|
||||
// GUI Widgets
|
||||
#include "Tab.h"
|
||||
#include "GcToolBar.h"
|
||||
#include "NewSideBar.h"
|
||||
#include "HelpWindow.h"
|
||||
#include "HomeWindow.h"
|
||||
#include "GcScopeBar.h"
|
||||
#if !defined(Q_OS_MAC)
|
||||
#include "QTFullScreen.h" // not mac!
|
||||
#endif
|
||||
@@ -214,14 +214,38 @@ MainWindow::MainWindow(const QDir &home)
|
||||
appsettings->setValue(GC_SETTINGS_LAST, context->athlete->home->root().dirName());
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* ScopeBar
|
||||
* ScopeBar as sidebar from v3.6
|
||||
*--------------------------------------------------------------------*/
|
||||
scopebar = new GcScopeBar(context);
|
||||
connect(scopebar, SIGNAL(selectDiary()), this, SLOT(selectDiary()));
|
||||
connect(scopebar, SIGNAL(selectHome()), this, SLOT(selectHome()));
|
||||
connect(scopebar, SIGNAL(selectAnal()), this, SLOT(selectAnalysis()));
|
||||
connect(scopebar, SIGNAL(selectTrain()), this, SLOT(selectTrain()));
|
||||
connect(scopebar, SIGNAL(selectInterval()), this, SLOT(selectInterval()));
|
||||
|
||||
sidebar = new NewSideBar(context, this);
|
||||
sidebar->addItem(QImage(":sidebar/athlete.png"), tr("athletes"), 0);
|
||||
sidebar->setItemEnabled(0, false);
|
||||
|
||||
sidebar->addItem(QImage(":sidebar/plan.png"), tr("plan"), 1);
|
||||
sidebar->setItemEnabled(1, false);
|
||||
|
||||
sidebar->addItem(QImage(":sidebar/trends.png"), tr("trends"), 2);
|
||||
sidebar->addItem(QImage(":sidebar/assess.png"), tr("activities"), 3);
|
||||
sidebar->setItemSelected(3, true);
|
||||
|
||||
sidebar->addItem(QImage(":sidebar/reflect.png"), tr("reflect"), 4);
|
||||
sidebar->setItemEnabled(4, false);
|
||||
|
||||
sidebar->addItem(QImage(":sidebar/train.png"), tr("train"), 5);
|
||||
|
||||
sidebar->addStretch();
|
||||
sidebar->addItem(QImage(":sidebar/apps.png"), tr("apps"), 6);
|
||||
sidebar->setItemEnabled(6, 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);
|
||||
sidebar->setItemSelectable(7, false);
|
||||
sidebar->addItem(QImage(":sidebar/prefs.png"), tr("settings"), 8);
|
||||
sidebar->setItemSelectable(8, false);
|
||||
|
||||
connect(sidebar, SIGNAL(itemClicked(int)), this, SLOT(sidebarClicked(int)));
|
||||
connect(sidebar, SIGNAL(itemSelected(int)), this, SLOT(sidebarSelected(int)));
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* What's this Context Help
|
||||
@@ -266,16 +290,16 @@ MainWindow::MainWindow(const QDir &home)
|
||||
HelpWhatsThis *helpLowBar = new HelpWhatsThis(lowbar);
|
||||
lowbar->setWhatsThis(helpLowBar->getWhatsThisText(HelpWhatsThis::ToolBar_ToggleComparePane));
|
||||
|
||||
sidebar = new QPushButton(this);
|
||||
sidebar->setIcon(sidebarIcon);
|
||||
sidebar->setFixedHeight(24 * dpiYFactor);
|
||||
sidebar->setIconSize(isize);
|
||||
sidebar->setStyle(toolStyle);
|
||||
sidebar->setToolTip(tr("Toggle Sidebar"));
|
||||
sidebar->setPalette(metal);
|
||||
connect(sidebar, SIGNAL(clicked(bool)), this, SLOT(toggleSidebar()));
|
||||
HelpWhatsThis *helpSideBar = new HelpWhatsThis(sidebar);
|
||||
sidebar->setWhatsThis(helpSideBar->getWhatsThisText(HelpWhatsThis::ToolBar_ToggleSidebar));
|
||||
sidelist = new QPushButton(this);
|
||||
sidelist->setIcon(sidebarIcon);
|
||||
sidelist->setFixedHeight(24 * dpiYFactor);
|
||||
sidelist->setIconSize(isize);
|
||||
sidelist->setStyle(toolStyle);
|
||||
sidelist->setToolTip(tr("Toggle Sidebar"));
|
||||
sidelist->setPalette(metal);
|
||||
connect(sidelist, SIGNAL(clicked(bool)), this, SLOT(toggleSidebar()));
|
||||
HelpWhatsThis *helpSideBar = new HelpWhatsThis(sidelist);
|
||||
sidelist->setWhatsThis(helpSideBar->getWhatsThisText(HelpWhatsThis::ToolBar_ToggleSidebar));
|
||||
|
||||
styleSelector = new QtSegmentControl(this);
|
||||
styleSelector->setStyle(toolStyle);
|
||||
@@ -295,37 +319,35 @@ MainWindow::MainWindow(const QDir &home)
|
||||
if (dpiXFactor > 1) {
|
||||
QString nopad = QString("QPushButton { padding-left: 0px; padding-right: 0px; "
|
||||
" padding-top: 0px; padding-bottom: 0px; }");
|
||||
sidebar->setStyleSheet(nopad);
|
||||
sidelist->setStyleSheet(nopad);
|
||||
lowbar->setStyleSheet(nopad);
|
||||
}
|
||||
#endif
|
||||
|
||||
head->addWidget(new Spacer(this));
|
||||
head->addStretch();
|
||||
head->addWidget(scopebar);
|
||||
head->addStretch();
|
||||
head->addWidget(sidebar);
|
||||
head->addWidget(lowbar);
|
||||
head->addWidget(styleSelector);
|
||||
head->setFixedHeight(scopebar->height() + 7);
|
||||
|
||||
// add a search box on far right, but with a little space too
|
||||
searchBox = new SearchFilterBox(this,context,false);
|
||||
anim = new QPropertyAnimation(searchBox, "xwidth", this);
|
||||
|
||||
searchBox->setStyle(toolStyle);
|
||||
searchBox->setFixedWidth(150 * dpiYFactor);
|
||||
head->addWidget(searchBox);
|
||||
searchBox->setFixedWidth(400 * dpiXFactor);
|
||||
searchBox->setFixedHeight(28 * dpiYFactor);
|
||||
head->addStretch();
|
||||
head->addWidget(sidelist);
|
||||
head->addWidget(lowbar);
|
||||
head->addWidget(styleSelector);
|
||||
head->setFixedHeight(searchBox->height() + (10 *dpiXFactor));
|
||||
|
||||
connect(searchBox, SIGNAL(searchResults(QStringList)), this, SLOT(setFilter(QStringList)));
|
||||
connect(searchBox, SIGNAL(searchClear()), this, SLOT(clearFilter()));
|
||||
connect(searchBox->searchbox, SIGNAL(haveFocus()), this, SLOT(searchFocusIn()));
|
||||
connect(searchBox->searchbox, SIGNAL(lostFocus()), this, SLOT(searchFocusOut()));
|
||||
HelpWhatsThis *helpSearchBox = new HelpWhatsThis(searchBox);
|
||||
searchBox->setWhatsThis(helpSearchBox->getWhatsThisText(HelpWhatsThis::SearchFilterBox));
|
||||
|
||||
Spacer *spacer = new Spacer(this);
|
||||
spacer->setFixedWidth(5 *dpiYFactor);
|
||||
head->addWidget(spacer);
|
||||
head->addWidget(searchBox);
|
||||
spacer = new Spacer(this);
|
||||
spacer->setFixedWidth(5 *dpiYFactor);
|
||||
head->addWidget(spacer);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@@ -364,8 +386,17 @@ MainWindow::MainWindow(const QDir &home)
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->setContentsMargins(0,0,0,0);
|
||||
mainLayout->addWidget(head);
|
||||
mainLayout->addWidget(tabbar);
|
||||
mainLayout->addWidget(tabStack);
|
||||
QHBoxLayout *lrlayout = new QHBoxLayout();
|
||||
mainLayout->addLayout(lrlayout);
|
||||
lrlayout->setSpacing(0);
|
||||
lrlayout->setContentsMargins(0,0,0,0);
|
||||
lrlayout->addWidget(sidebar);
|
||||
QVBoxLayout *tablayout = new QVBoxLayout();
|
||||
tablayout->setSpacing(0);
|
||||
tablayout->setContentsMargins(0,0,0,0);
|
||||
lrlayout->addLayout(tablayout);
|
||||
tablayout->addWidget(tabbar);
|
||||
tablayout->addWidget(tabStack);
|
||||
setCentralWidget(central);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@@ -561,7 +592,6 @@ MainWindow::MainWindow(const QDir &home)
|
||||
viewMenu->addSeparator();
|
||||
viewMenu->addAction(tr("Activities"), this, SLOT(selectAnalysis()));
|
||||
viewMenu->addAction(tr("Trends"), this, SLOT(selectHome()));
|
||||
viewMenu->addAction(tr("Train"), this, SLOT(selectTrain()));
|
||||
#ifdef GC_HAVE_ICAL
|
||||
viewMenu->addAction(tr("Diary"), this, SLOT(selectDiary()));
|
||||
#endif
|
||||
@@ -959,6 +989,7 @@ MainWindow::moveEvent(QMoveEvent*)
|
||||
void
|
||||
MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
fprintf(stderr,"window close started\n"); fflush(stderr);
|
||||
QList<Tab*> closing = tabList;
|
||||
bool needtosave = false;
|
||||
bool importrunning = false;
|
||||
@@ -1008,6 +1039,8 @@ MainWindow::closeEvent(QCloseEvent* event)
|
||||
}
|
||||
appsettings->setValue(GC_SETTINGS_MAIN_GEOM, saveGeometry());
|
||||
appsettings->setValue(GC_SETTINGS_MAIN_STATE, saveState());
|
||||
|
||||
fprintf(stderr,"window close compeleted\n"); fflush(stderr);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -1147,6 +1180,34 @@ MainWindow::support()
|
||||
QDesktopServices::openUrl(QUrl("https://groups.google.com/forum/#!forum/golden-cheetah-users"));
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::sidebarClicked(int id)
|
||||
{
|
||||
// sync quick link
|
||||
if (id == 7) checkCloud();
|
||||
|
||||
// prefs
|
||||
if (id == 8) showOptions();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::sidebarSelected(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case 0: // athlete not written yet
|
||||
case 1: // plan not written yet
|
||||
break;
|
||||
case 2: selectHome(); break;
|
||||
case 3: selectAnalysis(); break;
|
||||
case 4: // reflect not written yet
|
||||
break;
|
||||
case 5: selectTrain(); break;
|
||||
case 6: // apps not written yet
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::selectAnalysis()
|
||||
{
|
||||
@@ -1223,12 +1284,9 @@ MainWindow::setToolButtons()
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_MAC // bizarre issue with searchbox focus on tab voew change
|
||||
anim->stop();
|
||||
searchBox->clearFocus();
|
||||
searchFocusOut();
|
||||
scopebar->setFocus(Qt::TabFocusReason);
|
||||
#endif
|
||||
scopebar->setSelected(index);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@@ -1923,7 +1981,6 @@ MainWindow::saveGCState(Context *context)
|
||||
context->showToolbar = showhideToolbar->isChecked();
|
||||
context->searchText = searchBox->text();
|
||||
context->style = styleAction->isChecked();
|
||||
context->setIndex(scopebar->selected());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1934,9 +1991,6 @@ MainWindow::restoreGCState(Context *context)
|
||||
showToolbar(context->showToolbar);
|
||||
//showTabbar(context->showTabbar);
|
||||
showLowbar(context->showLowbar);
|
||||
scopebar->setSelected(context->viewIndex);
|
||||
scopebar->setContext(context);
|
||||
scopebar->setHighlighted(); // to reflect context
|
||||
searchBox->setContext(context);
|
||||
searchBox->setText(context->searchText);
|
||||
}
|
||||
@@ -2266,26 +2320,6 @@ void MainWindow::showCreateFixPyScriptDlg() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// grow/shrink searchbox if there is space...
|
||||
void
|
||||
MainWindow::searchFocusIn()
|
||||
{
|
||||
if (searchBox->searchbox->hasFocus()) {
|
||||
anim->setDuration(300);
|
||||
anim->setEasingCurve(QEasingCurve::InOutQuad);
|
||||
anim->setStartValue(searchBox->width());
|
||||
anim->setEndValue(500 * dpiYFactor);
|
||||
anim->start();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::searchFocusOut()
|
||||
{
|
||||
anim->stop();
|
||||
searchBox->setFixedWidth(150 *dpiYFactor);
|
||||
}
|
||||
|
||||
#ifdef GC_HAS_CLOUD_DB
|
||||
void
|
||||
MainWindow::cloudDBuserEditChart()
|
||||
|
||||
@@ -62,6 +62,7 @@ class QtSegmentControl;
|
||||
class SaveSingleDialogWidget;
|
||||
class ChooseCyclistDialog;
|
||||
class SearchFilterBox;
|
||||
class NewSideBar;
|
||||
|
||||
|
||||
class MainWindow;
|
||||
@@ -128,10 +129,6 @@ class MainWindow : public QMainWindow
|
||||
// chart importing
|
||||
void importCharts(QStringList);
|
||||
|
||||
// search box gets and loses focus - make big/small
|
||||
void searchFocusIn();
|
||||
void searchFocusOut();
|
||||
|
||||
// open and closing windows and tabs
|
||||
void closeAll(); // close all windows and tabs
|
||||
|
||||
@@ -149,6 +146,10 @@ class MainWindow : public QMainWindow
|
||||
void removeTab(Tab*); // remove without question
|
||||
void switchTab(int index); // for switching between one tab and another
|
||||
|
||||
// sidebar selecting views and actions
|
||||
void sidebarClicked(int id);
|
||||
void sidebarSelected(int id);
|
||||
|
||||
// Athlete Backup
|
||||
void setBackupAthleteMenu();
|
||||
void backupAthlete(QString name);
|
||||
@@ -263,19 +264,18 @@ class MainWindow : public QMainWindow
|
||||
|
||||
private:
|
||||
|
||||
GcScopeBar *scopebar;
|
||||
NewSideBar *sidebar;
|
||||
Tab *currentTab;
|
||||
QList<Tab*> tabList;
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
QTFullScreen *fullScreen;
|
||||
#endif
|
||||
QPropertyAnimation *anim;
|
||||
|
||||
SearchFilterBox *searchBox;
|
||||
|
||||
// Not on Mac so use other types
|
||||
QPushButton *sidebar, *lowbar;
|
||||
QPushButton *sidelist, *lowbar;
|
||||
QtSegmentControl *styleSelector;
|
||||
GcToolBar *head;
|
||||
|
||||
|
||||
278
src/Gui/NewSideBar.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "Context.h"
|
||||
#include "NewSideBar.h"
|
||||
#include "Colors.h"
|
||||
|
||||
static constexpr int gl_itemwidth = 70;
|
||||
static constexpr int gl_itemheight = 50;
|
||||
static constexpr int gl_margin = 0;
|
||||
|
||||
NewSideBar::NewSideBar(Context *context, QWidget *parent) : QWidget(parent), context(context)
|
||||
|
||||
{
|
||||
setFixedWidth(gl_itemwidth *dpiXFactor);
|
||||
setAutoFillBackground(true);
|
||||
lastid=0;
|
||||
|
||||
QVBoxLayout *mainlayout = new QVBoxLayout(this);
|
||||
mainlayout->setSpacing(0);
|
||||
mainlayout->setContentsMargins(0,0,0,0);
|
||||
top=new QWidget(this);
|
||||
bottom=new QWidget(this);
|
||||
middle=new QWidget(this);
|
||||
middle->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
mainlayout->addWidget(top);
|
||||
mainlayout->addWidget(middle);
|
||||
mainlayout->addWidget(bottom);
|
||||
|
||||
layout = new QVBoxLayout(middle);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0,gl_margin *dpiXFactor,0,gl_margin*dpiYFactor);
|
||||
|
||||
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
||||
configChanged(0);
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBar::clicked(int id)
|
||||
{
|
||||
// un selectable item was clicked (e.g. symc or settings)
|
||||
emit itemClicked(id);
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBar::selected(int id)
|
||||
{
|
||||
// we selected one, so need to set it selected
|
||||
// and deselect everyone else
|
||||
QMapIterator<int,NewSideBarItem*>i(items);
|
||||
while(i.hasNext()) {
|
||||
i.next();
|
||||
if (i.key() == id) i.value()->setSelected(true);
|
||||
else i.value()->setSelected(false);
|
||||
i.value()->update();
|
||||
}
|
||||
emit itemSelected(id);
|
||||
}
|
||||
|
||||
int
|
||||
NewSideBar::addItem(QImage icon, QString name, int id)
|
||||
{
|
||||
// allocated an id
|
||||
if (id == -1) id=lastid++;
|
||||
|
||||
NewSideBarItem *add = new NewSideBarItem(this, id, icon, name);
|
||||
layout->addWidget(add);
|
||||
items.insert(id, add);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// leave a gap- we have main icons, gap, apps, gap, sync, prefs
|
||||
void
|
||||
NewSideBar::addStretch()
|
||||
{
|
||||
layout->addStretch();
|
||||
}
|
||||
|
||||
|
||||
// is it shown, is it usable?
|
||||
void
|
||||
NewSideBar::setItemVisible(int id, bool x)
|
||||
{
|
||||
NewSideBarItem *item = items.value(id, NULL);
|
||||
if (item) item->setVisible(x);
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBar::setItemEnabled(int id, bool x)
|
||||
{
|
||||
NewSideBarItem *item = items.value(id, NULL);
|
||||
if (item) item->setEnabled(x);
|
||||
}
|
||||
|
||||
// can we select it, select it by program?
|
||||
void
|
||||
NewSideBar::setItemSelectable(int id, bool x)
|
||||
{
|
||||
NewSideBarItem *item = items.value(id, NULL);
|
||||
if (item) item->setSelectable(x);
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBar::setItemSelected(int id, bool x)
|
||||
{
|
||||
NewSideBarItem *item = items.value(id, NULL);
|
||||
if (item) item->setSelected(x);
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBar::configChanged(qint32)
|
||||
{
|
||||
QFont font;
|
||||
QFontMetrics fm(font);
|
||||
top->setFixedHeight(fm.height() + 8); // no scaling...
|
||||
bottom->setFixedHeight(fm.height() + 4); // no scaling...
|
||||
QColor col=GColor(CCHROME);
|
||||
QString style=QString("QWidget { background: rgb(%1,%2,%3); }").arg(col.red()).arg(col.green()).arg(col.blue());
|
||||
top->setStyleSheet(style);
|
||||
bottom->setStyleSheet(style);
|
||||
col=GColor(CPLOTBACKGROUND);
|
||||
col=GCColor::invertColor(col); // invert makes dark white, light black
|
||||
col=GCColor::invertColor(col); // invert again, so now its white or black
|
||||
style=QString("QWidget { background: rgb(%1,%2,%3); }").arg(col.red()).arg(col.green()).arg(col.blue());
|
||||
middle->setStyleSheet(style);
|
||||
}
|
||||
|
||||
NewSideBarItem::NewSideBarItem(NewSideBar *sidebar, int id, QImage icon, QString name) : QWidget(sidebar), sidebar(sidebar), id(id), icon(icon), name(name)
|
||||
{
|
||||
clicked = selected = false;
|
||||
selectable = enabled = true;
|
||||
|
||||
// some basics
|
||||
setFixedSize(gl_itemwidth *dpiXFactor,gl_itemheight *dpiYFactor);
|
||||
setAutoFillBackground(true);
|
||||
|
||||
// trap events
|
||||
installEventFilter(this);
|
||||
connect(sidebar->context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
||||
|
||||
configChanged(0);
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBarItem::setSelectable(bool x)
|
||||
{
|
||||
selectable = x;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBarItem::setEnabled(bool x)
|
||||
{
|
||||
enabled = x;
|
||||
update();
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBarItem::setSelected(bool x)
|
||||
{
|
||||
selected = x;
|
||||
update();
|
||||
}
|
||||
|
||||
// trap all events for me
|
||||
bool
|
||||
NewSideBarItem::eventFilter(QObject *, QEvent *e)
|
||||
{
|
||||
switch(e->type()) {
|
||||
case QEvent::Enter:
|
||||
case QEvent::Leave:
|
||||
case QEvent::MouseMove:
|
||||
update();
|
||||
break;
|
||||
|
||||
case QEvent::MouseButtonPress:
|
||||
clicked=true;
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
if (underMouse() && clicked) {
|
||||
// user clicked on us!
|
||||
if (enabled && selectable && !selected) sidebar->selected(id);
|
||||
else if (enabled && !selectable) sidebar->clicked(id);
|
||||
}
|
||||
clicked=false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static QImage imageRGB(QImage &source, QColor target)
|
||||
{
|
||||
QImage returning = source;
|
||||
|
||||
if (target == QColor(Qt::white)) target = QColor(255,255,254, 255); // white is the alpha
|
||||
|
||||
for(int x=0; x< returning.width(); x++)
|
||||
for(int y=0; y< returning.height(); y++) {
|
||||
QColor v = returning.pixelColor(x,y);
|
||||
if (v.red() == 0 && v.blue() == 0 && v.green() == 0)
|
||||
returning.setPixelColor(x,y,target);
|
||||
}
|
||||
|
||||
return returning;
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBarItem::configChanged(qint32)
|
||||
{
|
||||
QColor col(Qt::darkGray);
|
||||
QString style=QString("QWidget { background: rgb(%1,%2,%3); }").arg(col.red()).arg(col.green()).arg(col.blue());
|
||||
setStyleSheet(style);
|
||||
|
||||
// set foreground colors
|
||||
fg_normal = GCColor::invertColor(GColor(CPLOTBACKGROUND));
|
||||
|
||||
// if foreground is white then we're "dark" if its
|
||||
// black the we're "light" so this controls palette
|
||||
bool dark = (fg_normal == QColor(Qt::white));
|
||||
|
||||
if (dark) fg_disabled = QColor(80,80,80);
|
||||
else fg_disabled = QColor(180,180,180);
|
||||
|
||||
// set background colors
|
||||
col=GColor(CPLOTBACKGROUND);
|
||||
bool isblack = (col == QColor(Qt::black)); // e.g. mustang theme
|
||||
col=GCColor::invertColor(col); // invert makes dark white, light black
|
||||
col=GCColor::invertColor(col); // invert again, so now its white or black
|
||||
bg_normal = col;
|
||||
|
||||
// on select
|
||||
bg_select =GColor(CPLOTBACKGROUND);
|
||||
if (dark) bg_select = bg_select.lighter(200);
|
||||
else bg_select = bg_select.darker(200);
|
||||
if (isblack) bg_select = QColor(30,30,30);
|
||||
|
||||
// on hover
|
||||
bg_hover =GColor(CPLOTBACKGROUND);
|
||||
if (dark) bg_hover = bg_hover.lighter(300);
|
||||
else bg_hover = bg_hover.darker(300);
|
||||
if (isblack) bg_hover = QColor(50,50,50);
|
||||
|
||||
iconNormal = QPixmap::fromImage(imageRGB(icon, fg_normal), Qt::ColorOnly|Qt::PreferDither|Qt::DiffuseAlphaDither);
|
||||
iconDisabled = QPixmap::fromImage(imageRGB(icon, fg_disabled), Qt::ColorOnly|Qt::PreferDither|Qt::DiffuseAlphaDither);
|
||||
}
|
||||
|
||||
void
|
||||
NewSideBarItem::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
// background is normal, unless selected or hovering
|
||||
QBrush brush(bg_normal);
|
||||
if (selected) brush = QBrush(bg_select);
|
||||
else if (underMouse() && enabled) brush = QBrush(bg_hover);
|
||||
painter.fillRect(QRectF(0,0,gl_itemwidth*dpiXFactor, gl_itemheight*dpiXFactor), brush);
|
||||
|
||||
// icon is normal or disabled
|
||||
if (enabled) painter.drawPixmap(27*dpiXFactor,6*dpiXFactor,24*dpiXFactor,24*dpiXFactor,iconNormal);
|
||||
else painter.drawPixmap(27*dpiXFactor,6*dpiXFactor,24*dpiXFactor,24*dpiXFactor,iconDisabled);
|
||||
|
||||
// block
|
||||
if (selected) painter.fillRect(QRectF(0,0,3*dpiXFactor,gl_itemheight*dpiXFactor), QBrush(GColor(CPLOTMARKER)));
|
||||
|
||||
// draw name
|
||||
QPen pen(fg_normal);
|
||||
if (!enabled) pen = QPen(fg_disabled);
|
||||
QFont f;
|
||||
f.setPixelSize(12*dpiYFactor);
|
||||
painter.setFont(f);
|
||||
painter.setPen(pen);
|
||||
painter.drawText(QRect(5*dpiXFactor,24*dpiYFactor,(gl_itemwidth-5)*dpiXFactor,20*dpiYFactor), Qt::AlignCenter| Qt::AlignBottom, name);
|
||||
}
|
||||
105
src/Gui/NewSideBar.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#include <QWidget>
|
||||
#include <QMap>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
class Context;
|
||||
class NewSideBarItem;
|
||||
class NewSideBar : public QWidget
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
friend class ::NewSideBarItem;
|
||||
|
||||
public:
|
||||
NewSideBar(Context *context, QWidget *parent);
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// can we select it, select it by program?
|
||||
void setItemSelectable(int id, bool);
|
||||
void setItemSelected(int id, bool);
|
||||
|
||||
// config changed
|
||||
void configChanged(qint32);
|
||||
|
||||
// called by children
|
||||
void clicked(int id);
|
||||
void selected(int id);
|
||||
|
||||
signals:
|
||||
|
||||
void itemSelected(int id);
|
||||
void itemClicked(int id);
|
||||
|
||||
protected:
|
||||
Context *context;
|
||||
|
||||
private:
|
||||
|
||||
QWidget *top, *middle, *bottom; // bars at top and the bottom
|
||||
QMap<int,NewSideBarItem*> items;
|
||||
|
||||
int lastid; // when autoallocating
|
||||
QVBoxLayout *layout;
|
||||
};
|
||||
|
||||
// tightly bound with parent
|
||||
class NewSideBarItem : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
NewSideBarItem(NewSideBar *sidebar, int id, QImage icon, QString name);
|
||||
|
||||
void setSelectable(bool);
|
||||
void setEnabled(bool);
|
||||
void setSelected(bool);
|
||||
//void setVisible(bool); - standard qwidget method, we do not need to implement
|
||||
|
||||
bool isSelected() const { return selected; }
|
||||
bool isEnabled() const { return enabled; }
|
||||
bool isSelectable() const { return selectable; }
|
||||
//bool isVisible() const { return QWidget::isVisible(); } - standard qwidget method
|
||||
|
||||
// trap all events for me
|
||||
bool eventFilter(QObject *oj, QEvent *e);
|
||||
|
||||
public slots:
|
||||
|
||||
// config changed
|
||||
void configChanged(qint32);
|
||||
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
NewSideBar *sidebar; // for emitting signals
|
||||
int id;
|
||||
|
||||
// pre-rendered/calculated icons and colors
|
||||
QImage icon;
|
||||
QPixmap iconNormal, iconDisabled;
|
||||
QColor fg_normal, fg_disabled;
|
||||
QColor bg_normal, bg_hover, bg_select, bg_disable;
|
||||
QFont textfont;
|
||||
|
||||
QString name;
|
||||
|
||||
bool selected;
|
||||
bool selectable;
|
||||
bool enabled;
|
||||
bool clicked;
|
||||
};
|
||||
@@ -56,7 +56,7 @@ RideNavigator::RideNavigator(Context *context, bool mainwindow) : GcChartWindow(
|
||||
mainLayout = new QVBoxLayout;
|
||||
setChartLayout(mainLayout);
|
||||
mainLayout->setSpacing(0);
|
||||
if (mainwindow) mainLayout->setContentsMargins(0,0,0,0);
|
||||
if (mainwindow) mainLayout->setContentsMargins(5*dpiXFactor,0,0,0);
|
||||
else mainLayout->setContentsMargins(2,2,2,2); // so we can resize!
|
||||
|
||||
searchFilter = new SearchFilter(this);
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
SearchBox::SearchBox(Context *context, QWidget *parent, bool nochooser)
|
||||
: QLineEdit(parent), context(context), parent(parent), filtered(false), nochooser(nochooser), active(false)
|
||||
{
|
||||
setFixedHeight(21 *dpiYFactor);
|
||||
//setFixedHeight(21 *dpiYFactor);
|
||||
//clear button
|
||||
clearButton = new QToolButton(this);
|
||||
clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
||||
|
||||
@@ -35,6 +35,7 @@ SearchFilterBox::SearchFilterBox(QWidget *parent, Context *context, bool nochoos
|
||||
|
||||
// no column chooser if my parent widget is a modal widget
|
||||
searchbox = new SearchBox(context, this, nochooser);
|
||||
searchbox->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
contents->addWidget(searchbox);
|
||||
|
||||
freeSearch = new FreeSearch(this, context);
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>webservice/httpserver.ini</file>
|
||||
<file>sidebar/apps.png</file>
|
||||
<file>sidebar/assess.png</file>
|
||||
<file>sidebar/athlete.png</file>
|
||||
<file>sidebar/plan.png</file>
|
||||
<file>sidebar/prefs.png</file>
|
||||
<file>sidebar/reflect.png</file>
|
||||
<file>sidebar/sync.png</file>
|
||||
<file>sidebar/train.png</file>
|
||||
<file>sidebar/trends.png</file>
|
||||
<file>images/devices/garminusb.png</file>
|
||||
<file>images/devices/computrainer.png</file>
|
||||
<file>images/devices/kickr.png</file>
|
||||
|
||||
BIN
src/Resources/sidebar/apps.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src/Resources/sidebar/assess.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/Resources/sidebar/athlete.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/Resources/sidebar/plan.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/Resources/sidebar/prefs.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
src/Resources/sidebar/reflect.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/Resources/sidebar/sync.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/Resources/sidebar/train.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
src/Resources/sidebar/trends.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
@@ -754,7 +754,7 @@ HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/C
|
||||
Gui/GcWindowRegistry.h Gui/GenerateHeatMapDialog.h Gui/GProgressDialog.h Gui/HelpWhatsThis.h Gui/HelpWindow.h \
|
||||
Gui/IntervalTreeView.h Gui/LTMSidebar.h Gui/MainWindow.h Gui/NewCyclistDialog.h Gui/Pages.h Gui/RideNavigator.h Gui/RideNavigatorProxy.h \
|
||||
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/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
|
||||
|
||||
# metrics and models
|
||||
@@ -852,7 +852,7 @@ SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.cpp
|
||||
Gui/GcWindowRegistry.cpp Gui/GenerateHeatMapDialog.cpp Gui/GProgressDialog.cpp Gui/HelpWhatsThis.cpp Gui/HelpWindow.cpp \
|
||||
Gui/IntervalTreeView.cpp Gui/LTMSidebar.cpp Gui/MainWindow.cpp Gui/NewCyclistDialog.cpp Gui/Pages.cpp Gui/RideNavigator.cpp Gui/SaveDialogs.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/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
|
||||
|
||||
## Models and Metrics
|
||||
|
||||