Files
GoldenCheetah/src/TabView.cpp
Mark Liversedge c59ab396be Toolbar/Menu update when Compare Pane Show/Hide
.. if the compare pane is automatically shown or hidden
   due to the user dragging and dropping the menu and toolbar
   got out of sync with the status of the widget.
2013-12-02 17:48:48 +01:00

282 lines
8.0 KiB
C++

/*
* Copyright (c) 2013 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 "TabView.h"
#include "Tab.h"
#include "Context.h"
#include "Athlete.h"
#include "RideItem.h"
#include "BlankState.h"
#include "HomeWindow.h"
#include "GcWindowRegistry.h"
#include "TrainDB.h"
#include "MetricAggregator.h"
#include "MainWindow.h"
#include "Settings.h"
TabView::TabView(Context *context, int type) :
QWidget(context->tab), context(context), type(type),
_sidebar(true), _tiled(false), _selected(false), lastHeight(130),
stack(NULL), splitter(NULL), mainSplitter(NULL),
sidebar_(NULL), bottom_(NULL), page_(NULL), blank_(NULL)
{
// setup the basic widget
QVBoxLayout *layout = new QVBoxLayout(this);
setContentsMargins(0,0,0,0);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
stack = new QStackedWidget(this);
stack->setContentsMargins(0,0,0,0);
stack->setFrameStyle(QFrame::Plain | QFrame::NoFrame);
stack->setMinimumWidth(500);
stack->setMinimumHeight(500);
layout->addWidget(stack);
// the splitter
splitter = new QSplitter(this);
splitter->setHandleWidth(1);
splitter->setStyleSheet(" QSplitter::handle { background-color: rgb(120,120,120); color: darkGray; }");
splitter->setFrameStyle(QFrame::NoFrame);
splitter->setContentsMargins(0, 0, 0, 0); // attempting to follow some UI guides
splitter->setOpaqueResize(true); // redraw when released, snappier UI
stack->insertWidget(0, splitter); // splitter always at index 0
QString heading = "Compare Intervals";
if (type == VIEW_HOME) heading = "Compare Date Ranges";
mainSplitter = new ViewSplitter(Qt::Vertical, heading, this);
mainSplitter->setHandleWidth(23);
mainSplitter->setFrameStyle(QFrame::NoFrame);
mainSplitter->setContentsMargins(0, 0, 0, 0); // attempting to follow some UI guides
mainSplitter->setOpaqueResize(true); // redraw when released, snappier UI
// the animator
anim = new QPropertyAnimation(mainSplitter, "hpos");
connect(splitter,SIGNAL(splitterMoved(int,int)), this, SLOT(splitterMoved(int,int)));
}
TabView::~TabView()
{
if (page_) page_->saveState();
}
void
TabView::setRide(RideItem*ride)
{
page()->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
}
void
TabView::splitterMoved(int pos,int)
{
// show / hide sidebar as dragged..
if ((pos == 0 && sidebarEnabled())) setSidebarEnabled(false);
//XXX ? analysisSidebar should handle resizeEvents better, we shouldn't have
// to babysit it when the sidebar sizes change
//analysisSidebar->setWidth(pos);
// we now have splitter settings for each view
QString setting = QString("%1/%2").arg(GC_SETTINGS_SPLITTER_SIZES).arg(type);
appsettings->setCValue(context->athlete->cyclist, setting, splitter->saveState());
}
void
TabView::setSidebar(QWidget *sidebar)
{
sidebar_ = sidebar;
splitter->insertWidget(0, sidebar);
}
void
TabView::setPage(HomeWindow *page)
{
page_ = page;
// add to mainSplitter
// now reset the splitter
mainSplitter->insertWidget(-1, page);
mainSplitter->setStretchFactor(0,0);
mainSplitter->setCollapsible(0, false);
splitter->insertWidget(-1, mainSplitter);
QString setting = QString("%1/%2").arg(GC_SETTINGS_SPLITTER_SIZES).arg(type);
QVariant splitterSizes = appsettings->cvalue(context->athlete->cyclist, setting);
if (splitterSizes.toByteArray().size() > 1 ) {
splitter->restoreState(splitterSizes.toByteArray());
}
}
void
TabView::setBottom(QWidget *widget)
{
bottom_ = widget;
bottom_->hide();
mainSplitter->insertWidget(-1, bottom_);
mainSplitter->setCollapsible(1, true); // XXX we need a ComparePane widget ...
mainSplitter->setStretchFactor(1,1);
}
void
TabView::dragEvent(bool x)
{
setShowBottom(x);
context->mainWindow->setToolButtons(); // toolbuttons reflect show/hide status
}
// hide and show bottom - but with a little animation ...
void
TabView::setShowBottom(bool x)
{
// remember last height used when hidind
if (!x && bottom_) lastHeight = bottom_->height();
// basic version for now .. remembers and sets horizontal position precisely
// adding animation should be easy from here
if (bottom_) {
if (x) {
// set to the last value....
bottom_->show();
anim->setDuration(lastHeight * 3);
anim->setEasingCurve(QEasingCurve(QEasingCurve::Linear));
anim->setKeyValueAt(0,mainSplitter->maxhpos()-22);
anim->setKeyValueAt(1,mainSplitter->maxhpos()-(lastHeight+22));
anim->start();
} else {
// need a hide animator to hide on timeout
//anim->setDuration(200);
//anim->setEasingCurve(QEasingCurve(QEasingCurve::Linear));
//anim->setKeyValueAt(0,mainSplitter->maxhpos()-(lastHeight+22));
//anim->setKeyValueAt(1,mainSplitter->maxhpos()-22);
//anim->start();
bottom_->hide();
}
}
}
void
TabView::setBlank(BlankStatePage *blank)
{
blank_ = blank;
blank->hide();
stack->insertWidget(1, blank); // blank state always at index 1
// and when stuff happens lets check
connect(blank, SIGNAL(closeClicked()), this, SLOT(checkBlank()));
connect(context->athlete->metricDB, SIGNAL(dataChanged()), this, SLOT(checkBlank()));
connect(context, SIGNAL(configChanged()), this, SLOT(checkBlank()));
connect(trainDB, SIGNAL(dataChanged()), this, SLOT(checkBlank()));
}
void
TabView::sidebarChanged()
{
if (sidebarEnabled()) {
sidebar_->show();
// Restore sizes
QString setting = QString("%1/%2").arg(GC_SETTINGS_SPLITTER_SIZES).arg(type);
QVariant splitterSizes = appsettings->cvalue(context->athlete->cyclist, setting);
if (splitterSizes.toByteArray().size() > 1 ) {
splitter->restoreState(splitterSizes.toByteArray());
splitter->setOpaqueResize(true); // redraw when released, snappier UI
}
// if it was collapsed we need set to at least 200
// unless the mainwindow isn't big enough
if (sidebar_->width()<10) {
int size = width() - 200;
if (size>200) size = 200;
QList<int> sizes;
sizes.append(size);
sizes.append(width()-size);
splitter->setSizes(sizes);
}
} else sidebar_->hide();
}
void
TabView::tileModeChanged()
{
if (page_) page_->setStyle(isTiled() ? 2 : 0);
}
void
TabView::selectionChanged()
{
// we got selected..
if (isSelected()) {
// or do we need to show blankness?
if (isBlank() && blank_ && page_ && blank_->canShow()) {
splitter->hide();
blank()->show();
stack->setCurrentIndex(1);
} else if (blank_ && page_) {
blank()->hide();
splitter->show();
emit onSelectionChanged(); // give view a change to prepare
page()->selected(); // select the view
stack->setCurrentIndex(0);
}
} else {
emit onSelectionChanged(); // give view a change to clear
}
}
void
TabView::resetLayout()
{
if (page_) page_->resetLayout();
}
void
TabView::addChart(GcWinID id)
{
if (page_) page_->appendChart(id);
}
void
TabView::checkBlank()
{
selectionChanged(); // run through the code again
}