From fb1e3cb7bda7a4bb8385bcaf12a251a2f677d460 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sat, 8 Mar 2014 11:36:05 +0000 Subject: [PATCH] Replace Tabbar with a Scopebar .. Only tested on Linux .. Now going to check on Mac and Qt5 .. Also does not yet support re-ordering tabs nor scrolling when there are too many to show. This will come in future updates. --- src/ChartBar.cpp | 253 ++++++++++++++++++++++++++++++++++++++++++ src/ChartBar.h | 71 ++++++++++++ src/ComparePane.cpp | 1 + src/GcSideBarItem.cpp | 1 + src/GoldenCheetah.cpp | 2 +- src/HomeWindow.cpp | 52 ++++----- src/HomeWindow.h | 4 +- src/src.pro | 2 + 8 files changed, 354 insertions(+), 32 deletions(-) create mode 100644 src/ChartBar.cpp create mode 100644 src/ChartBar.h diff --git a/src/ChartBar.cpp b/src/ChartBar.cpp new file mode 100644 index 000000000..27e398b93 --- /dev/null +++ b/src/ChartBar.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2011 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 "ChartBar.h" +#include "GcScopeBar.h" +#include "DiaryWindow.h" +#include "DiarySidebar.h" +#include "Context.h" +#include "QtMacButton.h" + +ChartBar::ChartBar(Context *context) : QWidget(context->mainWindow), context(context) +{ + + setFixedHeight(23); + setContentsMargins(10,0,10,0); + QHBoxLayout *vlayout = new QHBoxLayout(this); + vlayout->setSpacing(0); + vlayout->setContentsMargins(0,0,0,0); + + layout = new QHBoxLayout; + layout->setSpacing(2); + layout->setContentsMargins(0,0,0,0); + + vlayout->addLayout(layout); + vlayout->addStretch(); + + +#ifdef Q_OS_MAC + buttonFont.setFamily("Lucida Grande"); +#else + buttonFont.setFamily("Helvetica"); +#endif +#ifdef WIN32 + buttonFont.setPointSize(8); +#else + buttonFont.setPointSize(10); +#endif + buttonFont.setWeight(QFont::Black); + + // linear gradients +#ifdef Q_OS_MAC + int shade = 178; + int inshade = 225; +#else + int shade = 200; + int inshade = 250; +#endif + active = QLinearGradient(0, 0, 0, true ? 23 :18); + active.setColorAt(0.0, QColor(shade,shade,shade, 100)); + active.setColorAt(0.5, QColor(shade,shade,shade, 180)); + active.setColorAt(1.0, QColor(shade,shade,shade, 255)); + active.setSpread(QGradient::PadSpread); + inactive = QLinearGradient(0, 0, 0, true ? 23 :18); + inactive.setColorAt(0.0, QColor(inshade,inshade,inshade, 100)); + inactive.setColorAt(0.5, QColor(inshade,inshade,inshade, 180)); + inactive.setColorAt(1.0, QColor(inshade,inshade,inshade, 255)); + inactive.setSpread(QGradient::PadSpread); + + signalMapper = new QSignalMapper(this); // maps each option + connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(clicked(int))); +} + +void +ChartBar::addWidget(QString title) +{ +#ifdef Q_OS_MAC + QtMacButton *newbutton = new QtMacButton(this, QtMacButton::Recessed); +#else + GcScopeButton *newbutton = new GcScopeButton(this); +#endif + newbutton->setText(title); + newbutton->setFont(buttonFont); + + // make the right size + QFontMetrics fontMetric(buttonFont); + int width = fontMetric.width(title); + newbutton->setWidth(width+20); + + // add to layout + layout->addWidget(newbutton); + buttons << newbutton; + + // map signals + connect(newbutton, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); + signalMapper->setMapping(newbutton, buttons.count()-1); +} + +void +ChartBar::clear() +{ + foreach(GcScopeButton *button, buttons) { + layout->removeWidget(button); + delete button; + } + buttons.clear(); +} + +void +ChartBar::removeWidget(int index) +{ + layout->removeWidget(buttons[index]); + delete buttons[index]; + buttons.remove(index); + + // reset mappings + for (int i=0; isetMapping(buttons[i], i); + +} + +void +ChartBar::clicked(int index) +{ + setUpdatesEnabled(false); + // set selected + for(int i=0; isetChecked(i == index); + } + setUpdatesEnabled(true); + emit currentIndexChanged(index); +} + + +#if 0 +ChartBar::setHighlighted() +{ +#ifdef GC_HAVE_LUCENE + if (context->isfiltered) { + searchLabel->setHighlighted(true); + searchLabel->show(); +#ifndef Q_OS_MAC + home->setHighlighted(true); + anal->setHighlighted(true); +#ifdef GC_HAVE_ICAL + diary->setHighlighted(true); +#endif +#endif + } else { + searchLabel->setHighlighted(false); + searchLabel->hide(); +#ifndef Q_OS_MAC + home->setHighlighted(false); + anal->setHighlighted(false); +#ifdef GC_HAVE_ICAL + diary->setHighlighted(false); +#endif +#endif + } +#endif +} +#endif + +ChartBar::~ChartBar() +{ +} + +void +ChartBar::paintEvent (QPaintEvent *event) +{ + // paint the darn thing! + paintBackground(event); + QWidget::paintEvent(event); +} + +// paint is the same as sidebar +void +ChartBar::paintBackground(QPaintEvent *) +{ + // setup a painter and the area to paint + QPainter painter(this); + + painter.save(); + QRect all(0,0,width(),height()); + + // fill with a linear gradient + painter.setPen(Qt::NoPen); + painter.fillRect(all, QColor(Qt::white)); + painter.fillRect(all, isActiveWindow() ? active : inactive); + + QPen black(QColor(100,100,100,200)); + painter.setPen(black); + painter.drawLine(0,height()-1, width()-1, height()-1); + + QPen gray(QColor(230,230,230)); + painter.setPen(gray); + painter.drawLine(0,0, width()-1, 0); + + painter.restore(); +} + +#if 0 +int +ChartBar::selected() +{ + if (home->isChecked()) return 0; +#ifdef GC_HAVE_ICAL + if (diary->isChecked()) return 1; + if (anal->isChecked()) return 2; + if (train->isChecked()) return 3; +#else + if (anal->isChecked()) return 1; + if (train->isChecked()) return 2; +#endif + + // never gets here - shutup compiler + return 0; +} + +void +ChartBar::setSelected(int index) +{ + // we're already there + if (index == selected()) return; + + // mainwindow wants to tell us to switch to a selection + home->setChecked(false); +#ifdef GC_HAVE_ICAL + diary->setChecked(false); +#endif + anal->setChecked(false); + train->setChecked(false); + +#ifdef GC_HAVE_ICAL + switch (index) { + case 0 : home->setChecked(true); break; + case 1 : diary->setChecked(true); break; + case 2 : anal->setChecked(true); break; + case 3 : train->setChecked(true); break; + } +#else + switch (index) { + case 0 : home->setChecked(true); break; + case 1 : anal->setChecked(true); break; + case 2 : train->setChecked(true); break; + } +#endif +} +#endif diff --git a/src/ChartBar.h b/src/ChartBar.h new file mode 100644 index 000000000..41555c980 --- /dev/null +++ b/src/ChartBar.h @@ -0,0 +1,71 @@ +/* + * Copyright 2011 (c) 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_ChartBar_h +#define _GC_ChartBar_h 1 + +#include +#include +#include +#include + +class Context; +#ifdef Q_OS_MAC +class QtMacButton; +#else +class GcScopeButton; +#endif +class GcLabel; + +class ChartBar : public QWidget +{ + Q_OBJECT + +public: + + ChartBar(Context *context); + ~ChartBar(); + +public slots: + + void paintEvent (QPaintEvent *event); + void addWidget(QString); + void clear(); + void clicked(int); + void removeWidget(int); + //void setCurrentIndex(int index); + +signals: + void currentIndexChanged(int); + +private: + void paintBackground(QPaintEvent *); + + Context *context; + QHBoxLayout *layout; + + QFont buttonFont; + QVector buttons; + QSignalMapper *signalMapper; + + QLinearGradient active, inactive; + int currentIndex_; + bool state; +}; + +#endif diff --git a/src/ComparePane.cpp b/src/ComparePane.cpp index cabe5cec7..8708fc192 100644 --- a/src/ComparePane.cpp +++ b/src/ComparePane.cpp @@ -132,6 +132,7 @@ ComparePane::ComparePane(Context *context, QWidget *parent, CompareMode mode) : table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); table->setAcceptDrops(false); + table->setStyleSheet("QTableWidget { border: none; }"); scrollArea->setWidget(table); configChanged(); // set up ready to go... diff --git a/src/GcSideBarItem.cpp b/src/GcSideBarItem.cpp index a0a0d02da..3c664f553 100644 --- a/src/GcSideBarItem.cpp +++ b/src/GcSideBarItem.cpp @@ -379,6 +379,7 @@ GcSplitterHandle::paintBackground(QPaintEvent *) // fill with a linear gradient painter.setPen(Qt::NoPen); + painter.fillRect(all, QColor(Qt::white)); painter.fillRect(all, isActiveWindow() ? active : inactive); QPen black(QColor(100,100,100,200)); diff --git a/src/GoldenCheetah.cpp b/src/GoldenCheetah.cpp index 49bf58f07..d107154e9 100644 --- a/src/GoldenCheetah.cpp +++ b/src/GoldenCheetah.cpp @@ -262,7 +262,7 @@ GcWindow::paintEvent(QPaintEvent * /*event*/) // fill in the title bar QRect bar(0,0,width(),contentsMargins().top()); painter.setPen(Qt::darkGray); - painter.drawRect(QRect(0,0,width()-1,height()-1)); + //painter.drawRect(QRect(0,0,width()-1,height()-1)); //XXX need scopebar as tabbar before we do this //XXX painter.drawLine(0,0,width(),0); diff --git a/src/HomeWindow.cpp b/src/HomeWindow.cpp index b457f0875..82d86d07e 100644 --- a/src/HomeWindow.cpp +++ b/src/HomeWindow.cpp @@ -23,6 +23,7 @@ #include "LTMTool.h" #include "LTMSettings.h" #include "Settings.h" +#include "ChartBar.h" #include @@ -84,31 +85,14 @@ HomeWindow::HomeWindow(Context *context, QString name, QString /* windowtitle */ // each style has its own container widget QWidget *tabArea = new QWidget(this); - //XXX need scopebar as tabbar before we remove spacing - //XXX tabArea->setContentsMargins(0,20,0,0); // no spacing now, used to be 20px - tabArea->setContentsMargins(20,20,20,20); // no spacing now, used to be 20px + tabArea->setContentsMargins(0,0,0,0); // no spacing now, used to be 20px QVBoxLayout *tabLayout = new QVBoxLayout(tabArea); tabLayout->setContentsMargins(0,0,0,0); tabLayout->setSpacing(0); - tabbed = new QTabWidget(this); -#ifdef Q_OS_MAC - tabbed->setAttribute(Qt::WA_MacShowFocusRect, 0); -#endif - tabbed->setContentsMargins(0,0,0,0); - tabbed->setTabsClosable(false); - tabbed->setPalette(palette); - tabbed->setDocumentMode(false); - tabbed->setMovable(true); - tabbed->setElideMode(Qt::ElideNone); - tabbed->setUsesScrollButtons(true); - - QTabBar *tb = tabbed->findChild(QLatin1String("qt_tabwidget_tabbar")); - tb->setShape(QTabBar::RoundedSouth); - tb->setShape(QTabBar::RoundedSouth); - tb->setDrawBase(false); - tabbed->setStyleSheet("QTabWidget::tab-bar { alignment: center; }" - "QTabWidget::pane { top: 20px; }"); + tabbed = new QStackedWidget(this); + chartbar = new ChartBar(context); + tabLayout->addWidget(chartbar); tabLayout->addWidget(tabbed); style->addWidget(tabArea); @@ -161,9 +145,10 @@ HomeWindow::HomeWindow(Context *context, QString name, QString /* windowtitle */ connect(this, SIGNAL(rideItemChanged(RideItem*)), this, SLOT(rideSelected())); connect(this, SIGNAL(dateRangeChanged(DateRange)), this, SLOT(dateRangeChanged(DateRange))); connect(context, SIGNAL(configChanged()), this, SLOT(configChanged())); - connect(tabbed, SIGNAL(currentChanged(int)), this, SLOT(tabSelected(int))); - connect(tabbed, SIGNAL(tabCloseRequested(int)), this, SLOT(removeChart(int))); - connect(tb, SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int))); + //connect(tabbed, SIGNAL(currentChanged(int)), this, SLOT(tabSelected(int))); + //connect(tabbed, SIGNAL(tabCloseRequested(int)), this, SLOT(removeChart(int))); + //connect(tb, SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int))); + connect(chartbar, SIGNAL(currentIndexChanged(int)), this, SLOT(tabSelected(int))); connect(titleEdit, SIGNAL(textChanged(const QString&)), SLOT(titleChanged())); installEventFilter(this); @@ -231,7 +216,7 @@ HomeWindow::titleChanged() // rename the tab if (!currentStyle) { - tabbed->setTabText(controlStack->currentIndex(), titleEdit->text()); + //XXX move to scope bar tabbed->setTabText(controlStack->currentIndex(), titleEdit->text()); } // repaint to reflect @@ -295,6 +280,7 @@ HomeWindow::tabSelected(int index) charts[index]->setProperty("dateRange", property("dateRange")); controlStack->setCurrentIndex(index); titleEdit->setText(charts[index]->property("title").toString()); + tabbed->setCurrentIndex(index); } active = false; @@ -345,6 +331,8 @@ HomeWindow::styleChanged(int id) // block updates as it is butt ugly setUpdatesEnabled(false); tabbed->hide(); //This is a QTabWidget setUpdatesEnabled bug (?) + chartbar->hide(); + chartbar->clear(); // move the windows from there current // position to there new position @@ -354,7 +342,7 @@ HomeWindow::styleChanged(int id) case 0 : // they are tabs in a TabWidget { int tabnum = tabbed->indexOf(charts[i]); - tabbed->removeTab(tabnum); + tabbed->removeWidget(tabbed->widget(tabnum)); } break; case 1 : // they are lists in a GridLayout @@ -373,7 +361,8 @@ HomeWindow::styleChanged(int id) // now put into new style switch (id) { case 0 : // they are tabs in a TabWidget - tabbed->addTab(charts[i], charts[i]->property("title").toString()); + tabbed->addWidget(charts[i]); + chartbar->addWidget(charts[i]->property("title").toString()); charts[i]->setContentsMargins(0,25,0,0); charts[i]->setResizable(false); // we need to show on tab selection! charts[i]->setProperty("dateRange", property("dateRange")); @@ -411,7 +400,7 @@ HomeWindow::styleChanged(int id) // now refresh as we are done setUpdatesEnabled(true); tabbed->show(); // QTabWidget setUpdatesEnabled bug - // and resize artefact too.. tread carefully. + chartbar->show(); // and resize artefact too.. tread carefully. update(); } @@ -522,7 +511,9 @@ HomeWindow::addChart(GcWindow* newone) case 0 : newone->setContentsMargins(0,25,0,0); newone->setResizable(false); // we need to show on tab selection! - tabbed->addTab(newone, newone->property("title").toString()); + //tabbed->addTab(newone, newone->property("title").toString()); + tabbed->addWidget(newone); + chartbar->addWidget(newone->property("title").toString()); break; case 1 : { @@ -621,7 +612,8 @@ HomeWindow::removeChart(int num, bool confirm) switch(currentStyle) { case 0 : // delete tab and widget - tabbed->removeTab(num); + chartbar->removeWidget(num); + tabbed->removeWidget(tabbed->widget(num)); break; case 1 : // scrolled tileGrid->removeWidget(charts[num]); diff --git a/src/HomeWindow.h b/src/HomeWindow.h index 9f1d61019..662a6fa2a 100644 --- a/src/HomeWindow.h +++ b/src/HomeWindow.h @@ -41,6 +41,7 @@ #endif extern QApplication *application; +class ChartBar; class HomeWindow : public GcWindow { @@ -120,7 +121,8 @@ class HomeWindow : public GcWindow QStackedWidget *controlStack; // window controls // each style has its own container widget - QTabWidget *tabbed; + ChartBar *chartbar; + QStackedWidget *tabbed; QScrollArea *tileArea; QWidget *tileWidget; diff --git a/src/src.pro b/src/src.pro index 365ef3977..940bfb099 100644 --- a/src/src.pro +++ b/src/src.pro @@ -274,6 +274,7 @@ HEADERS += \ BingMap.h \ BlankState.h \ CalendarDownload.h \ + ChartBar.h \ ChartSettings.h \ ChooseCyclistDialog.h \ Colors.h \ @@ -465,6 +466,7 @@ SOURCES += \ BingMap.cpp \ BlankState.cpp \ CalendarDownload.cpp \ + ChartBar.cpp \ ChartSettings.cpp \ ChooseCyclistDialog.cpp \ Coggan.cpp \