mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-15 00:49:55 +00:00
.. 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.
282 lines
8.0 KiB
C++
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
|
|
}
|