390 changes: 390 additions & 0 deletions src/Gui/PerspectiveDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,390 @@
/*
* Copyright (c) 2021 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 "PerspectiveDialog.h"
#include "TabView.h"
#include "Perspective.h"

#include <QFormLayout>
#include <QLabel>
#include <QMessageBox>

///
/// PerspectiveDialog
///
PerspectiveDialog::PerspectiveDialog(QWidget *parent, TabView *tabView) : QDialog(parent), tabView(tabView), active(false)
{

setWindowTitle("Manage Perspectives");
setMinimumWidth(400*dpiXFactor);
setMinimumHeight(450*dpiXFactor);

//setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::Tool);
QVBoxLayout *mainLayout = new QVBoxLayout(this);

// create all the widgets
QLabel *xlabel = new QLabel(tr("Perspectives"));
perspectiveTable = new PerspectiveTableWidget(this);
#ifdef Q_OS_MAX
xdataTable->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
perspectiveTable->setColumnCount(1);
perspectiveTable->horizontalHeader()->setStretchLastSection(true);
perspectiveTable->horizontalHeader()->hide();
perspectiveTable->setSortingEnabled(false);
perspectiveTable->verticalHeader()->hide();
perspectiveTable->setShowGrid(false);
perspectiveTable->setSelectionMode(QAbstractItemView::SingleSelection);
perspectiveTable->setSelectionBehavior(QAbstractItemView::SelectRows);
perspectiveTable->setAcceptDrops(true);
//perspectiveTable->setDropIndicatorShown(true);

QLabel *xslabel = new QLabel(tr("Charts"));
chartTable = new ChartTableWidget(this);
#ifdef Q_OS_MAX
xdataSeriesTable->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
chartTable->setColumnCount(1);
chartTable->horizontalHeader()->setStretchLastSection(true);
chartTable->horizontalHeader()->hide();
chartTable->setSortingEnabled(false);
chartTable->verticalHeader()->hide();
chartTable->setShowGrid(false);
chartTable->setSelectionMode(QAbstractItemView::SingleSelection);
chartTable->setSelectionBehavior(QAbstractItemView::SelectRows);
chartTable->setDragEnabled(true);

upPerspective = new QToolButton(this);
upPerspective->setArrowType(Qt::UpArrow);
downPerspective = new QToolButton(this);
downPerspective->setArrowType(Qt::DownArrow);
upPerspective->setFixedSize(20*dpiXFactor,20*dpiYFactor);
downPerspective->setFixedSize(20*dpiXFactor,20*dpiYFactor);

addPerspective = new QPushButton("+", this);
removePerspective = new QPushButton("-", this);

#ifdef Q_OS_MAC
addPerspective->setText(tr("Add"));
removePerspective->setText(tr("Delete"));
#else
addPerspective->setFixedSize(20*dpiXFactor,20*dpiYFactor);
removePerspective->setFixedSize(20*dpiXFactor,20*dpiYFactor);
#endif

// not so obvious perhaps
instructions = new QLabel(tr("Drag charts to move to a perspective"));

// lay it out
mainLayout->addWidget(xlabel);
mainLayout->addWidget(perspectiveTable);
QHBoxLayout *xb = new QHBoxLayout();
xb->addWidget(upPerspective);
xb->addWidget(downPerspective);
xb->addStretch();
xb->addWidget(addPerspective);
xb->addWidget(removePerspective);
mainLayout->addLayout(xb);

mainLayout->addWidget(xslabel);
mainLayout->addWidget(chartTable);
QHBoxLayout *xs = new QHBoxLayout();
xs->addWidget(instructions);
mainLayout->addLayout(xs);

connect(perspectiveTable, SIGNAL(currentItemChanged(QTableWidgetItem*,QTableWidgetItem*)), this, SLOT(perspectiveSelected()));
connect(perspectiveTable, SIGNAL(chartMoved(GcChartWindow*)), this, SLOT(perspectiveSelected())); // just reset the chart list
connect(perspectiveTable, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(perspectiveNameChanged(QTableWidgetItem*))); // user edit

connect(removePerspective, SIGNAL(clicked(bool)), this, SLOT(removePerspectiveClicked()));
connect(addPerspective, SIGNAL(clicked(bool)), this, SLOT(addPerspectiveClicked()));
connect(upPerspective, SIGNAL(clicked(bool)), this, SLOT(upPerspectiveClicked()));
connect(downPerspective, SIGNAL(clicked(bool)), this, SLOT(downPerspectiveClicked()));

// set table
setTables();
}

void PerspectiveDialog::close()
{
}

// set the perspective part of the dialog, the chart list
// is set when a perspective is selected
void PerspectiveDialog::setTables()
{
active = true;

perspectiveTable->clear();
perspectiveTable->setRowCount(tabView->perspectives_.count());

// add a row for each perspective
int perspectiverow=0;
foreach(Perspective *perspective, tabView->perspectives_) {

// add a row to the perspective table - editable by default
QTableWidgetItem *add = new QTableWidgetItem(perspective->title_, 0);
add->setFlags(add->flags() | Qt::ItemIsDropEnabled);

// and the perspective we represent, so we can avoid dropping on ourselves
add->setData(Qt::UserRole, QVariant::fromValue(static_cast<void*>(perspective)));

perspectiveTable->setItem(perspectiverow++, 0, add);

}

// enable/disable remove button if we have > 1 perspectives
// it must not be possible to remove the last perspective
removePerspective->setEnabled(perspectiverow > 1);
active = false;

// set to first row
if (perspectiveTable->currentRow()==0) perspectiveSelected();
else perspectiveTable->selectRow(0);

}

void PerspectiveDialog::perspectiveSelected()
{
if (active) return; // ignore when programmatically maintaining views

// charts listed are for the perspective currently selected
chartTable->clear();

// lets find the one we have selected...
int perspectiverow =perspectiveTable->currentIndex().row();

// check that we're in bounds
if (perspectiverow < 0 || perspectiverow >= tabView->perspectives_.count()) return;

// how many charts...
chartTable->setRowCount(tabView->perspectives_[perspectiverow]->charts.count());

// lets populate
int chartrow=0;
foreach(GcChartWindow *chart, tabView->perspectives_[perspectiverow]->charts) {

// add a row for each name
QTableWidgetItem *add = new QTableWidgetItem();
add->setFlags((add->flags() | Qt::ItemIsDragEnabled) & (~Qt::ItemIsEditable));
add->setText(chart->title());

// add perspective and chart pointers so we can encode when dragging (for dropping)
add->setData(Qt::UserRole, QVariant::fromValue(static_cast<void*>(tabView->perspectives_[perspectiverow])));
add->setData(Qt::UserRole+1, QVariant::fromValue(static_cast<void*>(chart)));

chartTable->setItem(chartrow++, 0, add);
}

if (chartrow) chartTable->selectRow(0);
}

void
PerspectiveDialog::removePerspectiveClicked()
{
// just do diag first.. lets not be too hasty !!!
int index = perspectiveTable->selectedItems()[0]->row();

// wipe it - tabView will worry about bounds and switching if we delete the currently selected one
tabView->removePerspective(tabView->perspectives_[index]);

// set tables
setTables();

emit perspectivesChanged();
}

void
PerspectiveDialog::addPerspectiveClicked()
{
QString name;
AddPerspectiveDialog *dialog= new AddPerspectiveDialog(tabView->context, name);
int ret= dialog->exec();
delete dialog;
if (ret == QDialog::Accepted && name != "") {

// add...
tabView->addPerspective(name);
emit perspectivesChanged();

setTables();
}
}

void
PerspectiveDialog::upPerspectiveClicked()
{
int index = perspectiveTable->selectedItems()[0]->row();
if (index == 0) return; // already at beginning

// move it
tabView->swapPerspective(index, index-1);

// set tables
setTables();

// select it again
perspectiveTable->selectRow(index-1);

emit perspectivesChanged();
}

void
PerspectiveDialog::downPerspectiveClicked()
{
int index = perspectiveTable->selectedItems()[0]->row();
if (index == (tabView->perspectives_.count()-1)) return; // already at end

// move it
tabView->swapPerspective(index, index+1);

// set tables
setTables();

// select it again
perspectiveTable->selectRow(index+1);

emit perspectivesChanged();
}

void
PerspectiveDialog::perspectiveNameChanged(QTableWidgetItem *item)
{
if (active) return;

// if the name changed we need to update
if (item->text() != tabView->perspectives_[item->row()]->title()) {

// update the title
tabView->perspectives_[item->row()]->title_ = item->text();

// tell the world
emit perspectivesChanged();
}
}

// drag and drop processing
void
PerspectiveTableWidget::dragEnterEvent(QDragEnterEvent *event)
{
bool accept = true;

// must be a chartref (from dragging charts below) anything else we ignore
// just in case someone tries to drag a file etc
foreach (QString format, event->mimeData()->formats()) {
if (format != "application/x-gc-chartref") accept = false;
}

if (accept) {
event->acceptProposedAction(); // whatever you wanna drop we will try and process!
return;
}

QTableWidget::dragEnterEvent(event);
}

void
PerspectiveTableWidget::dragMoveEvent(QDragMoveEvent *event)
{
QPoint pos = mapFromGlobal(QCursor::pos());

QTableWidgetItem *hover = itemAt(pos);
if (hover) {
QTableWidget::dragMoveEvent(event);
event->acceptProposedAction(); // not fussy yet
return;
}

QTableWidget::dragMoveEvent(event);
}

void
PerspectiveTableWidget::dropEvent(QDropEvent *event)
{
// dropping a chart onto a perspective
QByteArray rawData = event->mimeData()->data("application/x-gc-chartref");
QDataStream stream(&rawData, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_4_6);

// pack data
quint64 p,c;
stream >> p;
stream >> c;

// lets look at the context..
Perspective *perspective = (Perspective*)(p);
GcChartWindow *chart = (GcChartWindow*)(c);

// to where?
QPoint pos = mapFromGlobal(QCursor::pos());

QTableWidgetItem *hover = itemAt(pos);
if (hover) {
QVariant v = hover->data(Qt::UserRole);
Perspective *hoverp = static_cast<Perspective*>(v.value<void*>());
event->accept();

// move, but only if source and dest are not the same
if (perspective != hoverp) {
chart = perspective->takeChart(chart);
if (chart) hoverp->addChart(chart);
emit chartMoved(chart);
}
}
}

QStringList
ChartTableWidget::mimeTypes() const
{
QStringList returning;
returning << "application/x-gc-chartref";

return returning;
}

QMimeData *
ChartTableWidget::mimeData (const QList<QTableWidgetItem *> items) const
{
QMimeData *returning = new QMimeData;

// we need to pack into a byte array
QByteArray rawData;
QDataStream stream(&rawData, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_6);

// pack data
foreach (QTableWidgetItem *p, items) {

// convert to one of ours
QVariant v = p->data(Qt::UserRole);
Perspective *perspective = static_cast<Perspective*>(v.value<void*>());

v = p->data(Qt::UserRole + 1);
GcChartWindow *chart = static_cast<GcChartWindow*>(v.value<void*>());

// serialize
stream << (quint64)(perspective);
stream << (quint64)(chart);

}

// and return as mime data
returning->setData("application/x-gc-chartref", rawData);
return returning;
}
103 changes: 103 additions & 0 deletions src/Gui/PerspectiveDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2021 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_PerspectiveDialog_h
#define _GC_PerspectiveDialog_h 1
#include "GoldenCheetah.h"
#include "TabView.h"
#include "Perspective.h"

#include <QtGui>
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QTableWidget>
#include <QHeaderView>

class Context;

// reimplement QTableWidget to accept and process drop events
class PerspectiveTableWidget : public QTableWidget
{
Q_OBJECT

public:
PerspectiveTableWidget(QWidget *parent) : QTableWidget(parent) { setMouseTracking(true); }

// process drag and drop
virtual void dragEnterEvent(QDragEnterEvent *);
virtual void dragMoveEvent(QDragMoveEvent *);
virtual void dropEvent(QDropEvent *);

signals:
void chartMoved(GcChartWindow*);

};

class ChartTableWidget : public QTableWidget
{
Q_OBJECT

public:
ChartTableWidget(QWidget *parent) : QTableWidget(parent) {}

virtual QStringList mimeTypes() const;
virtual QMimeData *mimeData (const QList<QTableWidgetItem *> items) const;
};

class PerspectiveDialog : public QDialog
{
Q_OBJECT
G_OBJECT

public:
PerspectiveDialog(QWidget *parent, TabView *tabView);

private slots:

void perspectiveSelected();
void setTables();
void close();

void removePerspectiveClicked();
void addPerspectiveClicked();

void upPerspectiveClicked();
void downPerspectiveClicked();

void perspectiveNameChanged(QTableWidgetItem *);

signals:
void perspectivesChanged();

private:
TabView *tabView;

PerspectiveTableWidget *perspectiveTable;
ChartTableWidget *chartTable;

QPushButton *addPerspective, *removePerspective;
QToolButton *upPerspective, *downPerspective;
QLabel *instructions;

QPushButton *closeButton;

bool active;
};

#endif // _GC_PerspectiveDialog_h
132 changes: 99 additions & 33 deletions src/Gui/TabView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ TabView::TabView(Context *context, int type) :
_sidebar(true), _tiled(false), _selected(false), lastHeight(130*dpiYFactor), sidewidth(0),
active(false), bottomRequested(false), bottomHideOnIdle(false), perspectiveactive(false),
stack(NULL), splitter(NULL), mainSplitter(NULL),
sidebar_(NULL), bottom_(NULL), page_(NULL), blank_(NULL),
sidebar_(NULL), bottom_(NULL), perspective_(NULL), blank_(NULL),
loaded(false)
{
// setup the basic widget
Expand Down Expand Up @@ -87,8 +87,8 @@ TabView::~TabView()
{
saveState(); // writes xxx-perspectives.xml

foreach(Perspective *p, pages_) delete p;
pages_.clear();
foreach(Perspective *p, perspectives_) delete p;
perspectives_.clear();
}

void
Expand Down Expand Up @@ -292,9 +292,9 @@ TabView::saveState()
out<<"<layouts>\n";

// so lets run through the perspectives
foreach(Perspective *page, pages_) {
foreach(Perspective *page, perspectives_) {

out<<"<layout name=\""<< page->title <<"\" style=\"" << page->currentStyle <<"\">\n";
out<<"<layout name=\""<< page->title_ <<"\" style=\"" << page->currentStyle <<"\">\n";

// iterate over charts
foreach (GcChartWindow *chart, page->charts) {
Expand Down Expand Up @@ -428,31 +428,31 @@ TabView::restoreState(bool useDefault)
QXmlInputSource source;
source.setData(content);
QXmlSimpleReader xmlReader;
ViewParser handler(context);
ViewParser handler(context, type, useDefault);
xmlReader.setContentHandler(&handler);
xmlReader.setErrorHandler(&handler);

// parse and instantiate the charts
xmlReader.parse(source);
pages_ = handler.perspectives;
perspectives_ = handler.perspectives;

}
if (legacy && pages_.count() == 1) pages_[0]->title = "General";
if (legacy && perspectives_.count() == 1) perspectives_[0]->title_ = "General";

if (pages_.count() == 0) {
page_ = new Perspective(context, "empty", type);
pages_ << page_;
if (perspectives_.count() == 0) {
perspective_ = new Perspective(context, "empty", type);
perspectives_ << perspective_;
}

// add to stack
foreach(Perspective *page, pages_) {
foreach(Perspective *page, perspectives_) {
pstack->addWidget(page);
cstack->addWidget(page->controls());
page->configChanged(0); // set colors correctly- will have missed from startup
}

// default to first one
page_ = pages_[0];
perspective_ = perspectives_[0];

// if this is analysis view then lets select the first ride now
if (type == VIEW_ANALYSIS) {
Expand Down Expand Up @@ -483,12 +483,78 @@ TabView::addPerspective(QString name)
if (type == VIEW_TRAIN) page->styleChanged(2);
else page->styleChanged(0);

pages_ << page;
perspectives_ << page;
pstack->addWidget(page);
cstack->addWidget(page->controls());
page->configChanged(0); // set colors correctly- will be empty...
}

void
TabView::removePerspective(Perspective *p)
{
if (perspectives_.count() == 1) return; // not allowed to have zero perspectives mate

int index = perspectives_.indexOf(p);

if (index < 0) return; // doesn't even exist

if (p == perspective_) { // need to switch before we zap it!
Perspective *original = perspective_;

// switch one after this one (if it exists)
if (index < (perspectives_.count()-1)) perspective_ = perspectives_[index + 1];
else if (index > 0) perspective_ = perspectives_[index -1];
else return; // no no no ???

// switch to another
if (original != perspective_) perspectiveSelected(perspectives_.indexOf(perspective_));

}

// we can now remove from view
pstack->removeWidget(p);
cstack->removeWidget(p->controls());

// and model
perspectives_.removeAt(index);
delete p;
}

void
TabView::swapPerspective(int from, int to) // is actually swapping as only move 1 position at a time
{
if (from == to) return; // nowt to do in this case.

// make from always < to
if (from > to) {
int hold=from;
from = to;
to = hold;
}

// is from selected?
if (perspectives_[from] == perspective_) {
// remove and re-add to
QWidget *w = cstack->widget(to);
cstack->removeWidget(w);
cstack->insertWidget(from, w);
w = pstack->widget(to);
pstack->removeWidget(w);
pstack->insertWidget(from, w);
} else {
// remove and re-add from
QWidget *w = cstack->widget(from);
cstack->removeWidget(w);
cstack->insertWidget(to, w);
w = pstack->widget(from);
pstack->removeWidget(w);
pstack->insertWidget(to, w);
}
Perspective *hold = perspectives_[from];
perspectives_[from] = perspectives_[to];
perspectives_[to] = hold;
}

void
TabView::setPages(QStackedWidget *pages)
{
Expand Down Expand Up @@ -660,12 +726,12 @@ TabView::setPerspectives(QComboBox *perspectiveSelector)
if (!loaded) restoreState(false);

perspectiveSelector->clear();
foreach(Perspective *page, pages_) {
perspectiveSelector->addItem(page->title);
foreach(Perspective *page, perspectives_) {
perspectiveSelector->addItem(page->title_);
}
perspectiveSelector->addItem("Add New Perspective...");
perspectiveSelector->addItem("Manage Perspectives...");
perspectiveSelector->insertSeparator(pages_.count());
perspectiveSelector->insertSeparator(perspectives_.count());
perspectiveactive=false;

// if we only just loaded the charts and views, we need to select
Expand All @@ -675,7 +741,7 @@ TabView::setPerspectives(QComboBox *perspectiveSelector)
perspectiveSelected(0);

// due to visibility optimisation we need to force the first tab to be selected in tab mode
if (page_->currentStyle == 0 && page_->charts.count()) page_->tabSelected(0);
if (perspective_->currentStyle == 0 && perspective_->charts.count()) perspective_->tabSelected(0);
}
}

Expand All @@ -689,11 +755,11 @@ TabView::perspectiveSelected(int index)
// and set the date / ride property to help
// it catch up with what it missed whilst we
// were looking at another perspective
if (index < pages_.count()) {
if (index < perspectives_.count()) {

setUpdatesEnabled(false);

page_ = pages_[index];
perspective_ = perspectives_[index];

// switch to this perspective's charts and controls
pstack->setCurrentIndex(index);
Expand All @@ -703,8 +769,8 @@ TabView::perspectiveSelected(int index)

// set properties on the perspective as they propagate to charts
RideItem *notconst = (RideItem*)context->currentRideItem();
page_->setProperty("ride", QVariant::fromValue<RideItem*>(notconst));
page_->setProperty("dateRange", QVariant::fromValue<DateRange>(context->currentDateRange()));
perspective_->setProperty("ride", QVariant::fromValue<RideItem*>(notconst));
perspective_->setProperty("dateRange", QVariant::fromValue<DateRange>(context->currentDateRange()));

setUpdatesEnabled(true);
}
Expand All @@ -714,7 +780,7 @@ TabView::perspectiveSelected(int index)
void
TabView::tileModeChanged()
{
if (page_) page_->setStyle(isTiled() ? 2 : 0);
if (perspective_) perspective_->setStyle(isTiled() ? 2 : 0);
}

void
Expand All @@ -727,14 +793,14 @@ TabView::selectionChanged()
context->mainWindow->showhideSidebar->setChecked(_sidebar);

// or do we need to show blankness?
if (isBlank() && blank_ && page_ && blank_->canShow()) {
if (isBlank() && blank_ && perspective_ && blank_->canShow()) {

splitter->hide();
blank()->show();

stack->setCurrentIndex(1);

} else if (blank_ && page_) {
} else if (blank_ && perspective_) {

blank()->hide();
splitter->show();
Expand Down Expand Up @@ -764,7 +830,7 @@ TabView::resetLayout()
void
TabView::addChart(GcWinID id)
{
if (page_) page_->appendChart(id);
if (perspective_) perspective_->appendChart(id);
}

void
Expand Down Expand Up @@ -830,16 +896,16 @@ bool ViewParser::endElement( const QString&, const QString&, const QString &qNam

// translate the metrics, but only if the built-in "default.XML"s are read (and only for LTM charts)
// and only if the language is not English (i.e. translation is required).
#if 0 // XXX fixme

if (useDefault && !english) {

// translate the titles
Perspective::translateChartTitles(charts);
Perspective::translateChartTitles(page->charts);

// translate the LTM settings
for (int i=0; i<charts.count(); i++) {
for (int i=0; i<page->charts.count(); i++) {
// find out if it's an LTMWindow via dynamic_cast
LTMWindow* ltmW = dynamic_cast<LTMWindow*> (charts[i]);
LTMWindow* ltmW = dynamic_cast<LTMWindow*> (page->charts[i]);
if (ltmW) {
// the current chart is an LTMWindow, let's translate

Expand All @@ -851,7 +917,7 @@ bool ViewParser::endElement( const QString&, const QString&, const QString &qNam
}
}
}
#endif

page->styleChanged(style);
}
return true;
Expand All @@ -871,8 +937,8 @@ bool ViewParser::startElement( const QString&, const QString&, const QString &na
}
}

// we need a new perspective
page = new Perspective(context, name, VIEW_HOME); //XXX fixme VIEW_HOME!!! XXX
// we need a new perspective for this view type
page = new Perspective(context, name, type);
perspectives.append(page);
}
else if (name == "chart") {
Expand Down
16 changes: 11 additions & 5 deletions src/Gui/TabView.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Tab;
class ViewSplitter;
class Context;
class BlankStatePage;
class PerspectiveDialog;

class TabView : public QWidget
{
Expand All @@ -45,6 +46,7 @@ class TabView : public QWidget
Q_PROPERTY(bool selected READ isSelected WRITE setSelected USER true) // make this last always

friend class ::MainWindow;
friend class ::PerspectiveDialog;

public:

Expand All @@ -56,7 +58,7 @@ class TabView : public QWidget
void setSidebar(QWidget *sidebar);
QWidget *sidebar() { return sidebar_; }
void setPages(QStackedWidget *pages);
Perspective *page() { return page_;}
Perspective *page() { return perspective_;}
void setBlank(BlankStatePage *blank);
BlankStatePage *blank() { return blank_; }
void setBottom(QWidget *bottom);
Expand All @@ -80,6 +82,8 @@ class TabView : public QWidget

// add a new perspective
void addPerspective(QString);
void removePerspective(Perspective *);
void swapPerspective(int from, int to); // reorder by moving 1 pos at a time

// bottom
void dragEvent(bool); // showbottom on drag event
Expand All @@ -98,7 +102,7 @@ class TabView : public QWidget

int viewType() { return type; }

void importChart(QMap<QString,QString>properties, bool select) { page_->importChart(properties, select); }
void importChart(QMap<QString,QString>properties, bool select) { perspective_->importChart(properties, select); }

signals:

Expand Down Expand Up @@ -158,8 +162,8 @@ class TabView : public QWidget
QWidget *sidebar_;
QWidget *bottom_;

Perspective *page_; // currently selected page
QList<Perspective *> pages_;
Perspective *perspective_; // currently selected page
QList<Perspective *> perspectives_;

// the perspectives are stacked- charts and their associatated controls
QStackedWidget *pstack, *cstack;
Expand All @@ -177,7 +181,7 @@ class ViewParser : public QXmlDefaultHandler
{

public:
ViewParser(Context *context) : style(2), context(context) {}
ViewParser(Context *context, int type, bool useDefault) : style(2), context(context), type(type), useDefault(useDefault) {}

// the results!
QList<Perspective*> perspectives;
Expand All @@ -194,6 +198,8 @@ class ViewParser : public QXmlDefaultHandler
Context *context;
GcChartWindow *chart;
Perspective *page; // current
int type; // what type of view is this VIEW_{HOME,ANALYSIS,DIARY,TRAIN}
bool useDefault; // force a reset by using the default layouts

};
// we make our own view splitter for the bespoke handle
Expand Down
6 changes: 4 additions & 2 deletions src/src.pro
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,8 @@ HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/C
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/NewSideBar.h \
Gui/MergeActivityWizard.h Gui/RideImportWizard.h Gui/SplitActivityWizard.h Gui/SolverDisplay.h Gui/MetricSelect.h \
Gui/AddChartWizard.h Gui/NavigationModel.h Gui/AthleteView.h Gui/AthleteConfigDialog.h Gui/AthletePages.h Gui/Perspective.h
Gui/AddChartWizard.h Gui/NavigationModel.h Gui/AthleteView.h Gui/AthleteConfigDialog.h Gui/AthletePages.h Gui/Perspective.h \
Gui/PerspectiveDialog.h

# metrics and models
HEADERS += Metrics/Banister.h Metrics/CPSolver.h Metrics/Estimator.h Metrics/ExtendedCriticalPower.h Metrics/HrZones.h Metrics/PaceZones.h \
Expand Down Expand Up @@ -835,7 +836,8 @@ SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.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/NewSideBar.cpp \
Gui/MergeActivityWizard.cpp Gui/RideImportWizard.cpp Gui/SplitActivityWizard.cpp Gui/SolverDisplay.cpp Gui/MetricSelect.cpp \
Gui/AddChartWizard.cpp Gui/NavigationModel.cpp Gui/AthleteView.cpp Gui/AthleteConfigDialog.cpp Gui/AthletePages.cpp Gui/Perspective.cpp
Gui/AddChartWizard.cpp Gui/NavigationModel.cpp Gui/AthleteView.cpp Gui/AthleteConfigDialog.cpp Gui/AthletePages.cpp Gui/Perspective.cpp \
Gui/PerspectiveDialog.cpp

## Models and Metrics
SOURCES += Metrics/aBikeScore.cpp Metrics/aCoggan.cpp Metrics/AerobicDecoupling.cpp Metrics/Banister.cpp Metrics/BasicRideMetrics.cpp \
Expand Down