mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 16:39:57 +00:00
.. doesn't honour font sizes (long story but too complicated to unpick all the fugly code in QtMacButton.mm) .. but at least the chartbar is tall enough for the "standard" size on OS X
479 lines
12 KiB
C++
479 lines
12 KiB
C++
/*
|
|
* 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"
|
|
|
|
#include <QFontMetrics>
|
|
|
|
ChartBar::ChartBar(Context *context) : QWidget(context->mainWindow), context(context)
|
|
{
|
|
// left / right scroller icon
|
|
static QIcon leftIcon = iconFromPNG(":images/mac/left.png");
|
|
static QIcon rightIcon = iconFromPNG(":images/mac/right.png");
|
|
|
|
setContentsMargins(0,0,0,0);
|
|
|
|
// main layout
|
|
QHBoxLayout *mlayout = new QHBoxLayout(this);
|
|
mlayout->setSpacing(0);
|
|
mlayout->setContentsMargins(0,0,0,0);
|
|
|
|
// buttonBar Widget
|
|
buttonBar = new ButtonBar(this);
|
|
buttonBar->setFixedHeight(23);
|
|
buttonBar->setContentsMargins(0,0,0,0);
|
|
|
|
QHBoxLayout *vlayout = new QHBoxLayout(buttonBar);
|
|
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();
|
|
|
|
// scrollarea
|
|
scrollArea = new QScrollArea(this);
|
|
scrollArea->setAutoFillBackground(false);
|
|
scrollArea->setWidgetResizable(true);
|
|
scrollArea->setFrameStyle(QFrame::NoFrame);
|
|
scrollArea->setContentsMargins(0,0,0,0);
|
|
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
scrollArea->setWidget(buttonBar);
|
|
// scroll area turns it on .. we turn it off!
|
|
buttonBar->setAutoFillBackground(false);
|
|
|
|
// scroller buttons
|
|
left = new QToolButton(this);
|
|
left->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
|
left->setAutoFillBackground(false);
|
|
left->setFixedSize(20,20);
|
|
left->setIcon(leftIcon);
|
|
left->setIconSize(QSize(20,20));
|
|
left->setFocusPolicy(Qt::NoFocus);
|
|
mlayout->addWidget(left);
|
|
connect(left, SIGNAL(clicked()), this, SLOT(scrollLeft()));
|
|
|
|
// menu bar in the middle of the buttons
|
|
mlayout->addWidget(scrollArea);
|
|
|
|
right = new QToolButton(this);
|
|
right->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
|
right->setAutoFillBackground(false);
|
|
right->setFixedSize(20,20);
|
|
right->setIcon(rightIcon);
|
|
right->setIconSize(QSize(20,20));
|
|
right->setFocusPolicy(Qt::NoFocus);
|
|
mlayout->addWidget(right);
|
|
connect(right, SIGNAL(clicked()), this, SLOT(scrollRight()));
|
|
|
|
// spacer to make the menuButton on the right
|
|
QLabel *spacer = new QLabel("", this);
|
|
spacer->setAutoFillBackground(false);
|
|
spacer->setFixedHeight(20);
|
|
spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
|
mlayout->addWidget(spacer);
|
|
|
|
menuButton = new QToolButton(this);
|
|
menuButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
|
|
menuButton->setAutoFillBackground(false);
|
|
menuButton->setFixedSize(20,20);
|
|
menuButton->setIcon(iconFromPNG(":images/sidebar/extra.png"));
|
|
menuButton->setIconSize(QSize(10,10));
|
|
menuButton->setFocusPolicy(Qt::NoFocus);
|
|
mlayout->addWidget(menuButton);
|
|
//connect(p, SIGNAL(clicked()), action, SLOT(trigger()));
|
|
|
|
QFontMetrics fs(buttonFont);
|
|
#ifdef Q_OS_MAC
|
|
setFixedHeight(fs.height()+7);
|
|
scrollArea->setFixedHeight(fs.height()+7);
|
|
#else
|
|
setFixedHeight(fs.height()+4);
|
|
scrollArea->setFixedHeight(fs.height()+4);
|
|
#endif
|
|
|
|
signalMapper = new QSignalMapper(this); // maps each option
|
|
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(clicked(int)));
|
|
|
|
barMenu = new QMenu("Add");
|
|
chartMenu = barMenu->addMenu(tr("Add Chart"));
|
|
|
|
// menu
|
|
connect(menuButton, SIGNAL(clicked()), this, SLOT(menuPopup()));
|
|
connect(chartMenu, SIGNAL(aboutToShow()), this, SLOT(setChartMenu()));
|
|
connect(chartMenu, SIGNAL(triggered(QAction*)), context->mainWindow, SLOT(addChart(QAction*)));
|
|
|
|
// trap resize / mouse events
|
|
installEventFilter(this);
|
|
|
|
// appearance update
|
|
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
|
}
|
|
|
|
void
|
|
ChartBar::configChanged(qint32)
|
|
{
|
|
#ifndef Q_OS_MAC
|
|
buttonFont = QFont();
|
|
QFontMetrics fs(buttonFont);
|
|
setFixedHeight(fs.height()+4);
|
|
scrollArea->setFixedHeight(fs.height()+4);
|
|
foreach(GcScopeButton *b, buttons) {
|
|
int width = fs.width(b->text);
|
|
b->setFont(buttonFont);
|
|
b->setFixedWidth(width+20);
|
|
b->setFixedHeight(fs.height()+2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
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->setFixedWidth(width+20);
|
|
newbutton->setFixedHeight(fontMetric.height()+2);
|
|
|
|
// add to layout
|
|
layout->addWidget(newbutton);
|
|
buttons << newbutton;
|
|
|
|
// map signals
|
|
connect(newbutton, SIGNAL(clicked(bool)), signalMapper, SLOT(map()));
|
|
signalMapper->setMapping(newbutton, buttons.count()-1);
|
|
|
|
newbutton->installEventFilter(this);
|
|
|
|
// tidy up scrollers etc
|
|
tidy();
|
|
}
|
|
|
|
void
|
|
ChartBar::setChartMenu()
|
|
{
|
|
context->mainWindow->setChartMenu(chartMenu);
|
|
}
|
|
|
|
void
|
|
ChartBar::menuPopup()
|
|
{
|
|
// set the point for the menu and call below
|
|
barMenu->exec(this->mapToGlobal(QPoint(menuButton->pos().x(), menuButton->pos().y()+20)));
|
|
}
|
|
|
|
void
|
|
ChartBar::setText(int index, QString text)
|
|
{
|
|
buttons[index]->setText(text);
|
|
QFontMetrics fontMetric(buttonFont);
|
|
int width = fontMetric.width(text);
|
|
buttons[index]->setWidth(width+20);
|
|
|
|
tidy(); // still fit ?
|
|
}
|
|
|
|
// tidy up the scrollers on first show...
|
|
void
|
|
ChartBar::tidy()
|
|
{
|
|
// resize to button widths + 2px spacing
|
|
int width = 2;
|
|
#ifdef Q_OS_MAC
|
|
foreach (QtMacButton *button, buttons) {
|
|
#else
|
|
foreach (GcScopeButton *button, buttons) {
|
|
#endif
|
|
width += button->geometry().width() + 2;
|
|
}
|
|
buttonBar->setMinimumWidth(width);
|
|
|
|
if (buttonBar->width() > scrollArea->width()) {
|
|
left->show(); right->show();
|
|
} else {
|
|
left->hide(); right->hide();
|
|
}
|
|
}
|
|
|
|
bool
|
|
ChartBar::eventFilter(QObject *object, QEvent *e)
|
|
{
|
|
// show/hide scrollers on resize event
|
|
if (object == this && e->type() == QEvent::Resize) {
|
|
|
|
// we do NOT move the position, we just show/hide
|
|
// the left and right scrollers
|
|
tidy();
|
|
}
|
|
|
|
// showing us - tidy up
|
|
if (object == this && e->type() == QEvent::Show) {
|
|
tidy();
|
|
}
|
|
|
|
// enter/leave we can track approximate mouse position and decide
|
|
// if we want to 'autoscroll'
|
|
if (e->type() == QEvent::Leave || e->type() == QEvent::Enter) {
|
|
tidy(); // tidy up anyway
|
|
|
|
// XXX for later, perhaps when drag/dropping
|
|
// we should try and be a little more fluid / animate ...
|
|
// which will probably mean using QScrollArea::ScrollContentsBy
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
ChartBar::scrollRight()
|
|
{
|
|
// scroll to the right...
|
|
int w = buttonBar->width();
|
|
scrollArea->ensureVisible(w-10,0,10,10);
|
|
}
|
|
|
|
void
|
|
ChartBar::scrollLeft()
|
|
{
|
|
// scroll to the left
|
|
scrollArea->ensureVisible(0,0,10,10);
|
|
}
|
|
|
|
void
|
|
ChartBar::clear()
|
|
{
|
|
#ifdef Q_OS_MAC
|
|
foreach(QtMacButton *button, buttons) {
|
|
#else
|
|
foreach(GcScopeButton *button, buttons) {
|
|
#endif
|
|
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; i<buttons.count(); i++)
|
|
signalMapper->setMapping(buttons[i], i);
|
|
|
|
}
|
|
|
|
void
|
|
ChartBar::setCurrentIndex(int index)
|
|
{
|
|
clicked(index);
|
|
}
|
|
|
|
void
|
|
ChartBar::clicked(int index)
|
|
{
|
|
setUpdatesEnabled(false);
|
|
// set selected
|
|
for(int i=0; i<buttons.count(); i++) {
|
|
buttons[i]->setChecked(i == index);
|
|
}
|
|
setUpdatesEnabled(true);
|
|
emit currentIndexChanged(index);
|
|
}
|
|
|
|
|
|
#if 0
|
|
ChartBar::setHighlighted()
|
|
{
|
|
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
|
|
|
|
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());
|
|
|
|
// linear gradients
|
|
QLinearGradient active = GCColor::linearGradient(23, true);
|
|
QLinearGradient inactive = GCColor::linearGradient(23, false);
|
|
|
|
// fill with a linear gradient
|
|
painter.setPen(Qt::NoPen);
|
|
painter.fillRect(all, QColor(Qt::white));
|
|
painter.fillRect(all, isActiveWindow() ? active : inactive);
|
|
|
|
if (!GCColor::isFlat()) {
|
|
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();
|
|
}
|
|
|
|
void
|
|
ButtonBar::paintEvent(QPaintEvent *event)
|
|
{
|
|
// paint the darn thing!
|
|
paintBackground(event);
|
|
QWidget::paintEvent(event);
|
|
}
|
|
|
|
// paint is the same as sidebar
|
|
void
|
|
ButtonBar::paintBackground(QPaintEvent *)
|
|
{
|
|
// setup a painter and the area to paint
|
|
QPainter painter(this);
|
|
|
|
painter.save();
|
|
QRect all(0,0,width(),height());
|
|
|
|
// linear gradients
|
|
QLinearGradient active = GCColor::linearGradient(23, true);
|
|
QLinearGradient inactive = GCColor::linearGradient(23, false);
|
|
|
|
// fill with a linear gradient
|
|
painter.setPen(Qt::NoPen);
|
|
painter.fillRect(all, QColor(Qt::white));
|
|
painter.fillRect(all, isActiveWindow() ? active : inactive);
|
|
|
|
if (!GCColor::isFlat()) {
|
|
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
|