Files
GoldenCheetah/src/TabView.h

306 lines
9.7 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
*/
#ifndef _GC_TabView_h
#define _GC_TabView_h 1
#include <QWidget>
#include <QSplitter>
#include <QFont>
#include <QMetaObject>
#include <QStackedWidget>
#include "HomeWindow.h"
#include "GcSideBarItem.h"
#include "GcWindowRegistry.h"
#ifdef Q_OS_MAC
#include "QtMacButton.h"
#endif
class Tab;
class ViewSplitter;
class Context;
class BlankStatePage;
class TabView : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool sidebar READ sidebarEnabled WRITE setSidebarEnabled USER true)
Q_PROPERTY(bool tiled READ isTiled WRITE setTiled USER true)
Q_PROPERTY(bool selected READ isSelected WRITE setSelected USER true) // make this last always
public:
TabView(Context *context, int type);
virtual ~TabView();
virtual void close() {};
// add the widgets to the view
void setSidebar(QWidget *sidebar);
QWidget *sidebar() { return sidebar_; }
void setPage(HomeWindow *page);
HomeWindow *page() { return page_;}
void setBlank(BlankStatePage *blank);
BlankStatePage *blank() { return blank_; }
void setBottom(QWidget *bottom);
QWidget *bottom() { return bottom_; }
// sidebar
static QString ourStyleSheet();
void setSidebarEnabled(bool x) { _sidebar=x; sidebarChanged(); }
bool sidebarEnabled() const { return _sidebar; }
// tiled
void setTiled(bool x) { _tiled=x; tileModeChanged(); }
bool isTiled() const { return _tiled; }
// bottom
void dragEvent(bool); // showbottom on drag event
void setShowBottom(bool x);
bool isShowBottom() { if (bottom_) return bottom_->isVisible(); return false; }
bool hasBottom() { return (bottom_!=NULL); }
ViewSplitter *bottomSplitter() { return mainSplitter; }
// select / deselect view
void setSelected(bool x) { _selected=x; selectionChanged(); }
bool isSelected() const { return _selected; }
void saveState() { if (page_) page_->saveState(); }
signals:
void sidebarClosed(); // the user dragged the sidebar closed.
void onSelectionChanged();
public slots:
// interface used by the Tab class - must be implemented by a TabView
virtual bool isBlank() = 0;
virtual void setRide(RideItem*);
virtual void checkBlank();
// can be overriden by the derived class but we provide a working version
virtual void sidebarChanged();
virtual void tileModeChanged();
virtual void selectionChanged();
virtual void resetLayout();
virtual void addChart(GcWinID id);
// Let the base class handle the splitter movement and
// hiding the sidebar by dragging it closed.
void splitterMoved(int, int);
//void mediaSelected(QString filename);
//void ergSelected(ErgFile *erg);
//void videosyncSelected(VideosyncFile *videosync);
void configChanged(qint32);
void resizeEvent(QResizeEvent*);
protected:
Context *context;
int type; // used by windowregistry; e.g VIEW_TRAIN VIEW_ANALYSIS VIEW_DIARY VIEW_HOME
// we don't care what values are pass through to the GcWindowRegistry to decide
// what charts are relevant for this view.
// properties
bool _filtered;
QStringList _filter;
bool _sidebar;
bool _tiled;
bool _selected;
int lastHeight; // last height of splitter, default to 100...
int sidewidth; // width of sidebar
bool active;
QStackedWidget *stack;
QSplitter *splitter;
ViewSplitter *mainSplitter;
QPropertyAnimation *anim;
QWidget *sidebar_;
QWidget *bottom_;
HomeWindow *page_;
BlankStatePage *blank_;
};
// we make our own view splitter for the bespoke handle
class ViewSplitter : public QSplitter
{
Q_OBJECT
public:
ViewSplitter(Qt::Orientation orientation, QString name, TabView *parent=0) :
QSplitter(orientation, parent), orientation(orientation), name(name), tabView(parent), showForDrag(false) {
setAcceptDrops(true);
qRegisterMetaType<ViewSplitter*>("hpos");
clearbutton=toggle=NULL;
}
protected:
QSplitterHandle *createHandle() {
return new GcSplitterHandle(name, orientation, NULL, newclear(), newtoggle(), this);
}
int handleWidth() { return 23; };
#ifdef Q_OS_MAC
QtMacButton *newclear() {
if (clearbutton) delete clearbutton; // we only need one!
clearbutton = new QtMacButton(tr("Clear"), this);
// clearbutton->setFixedWidth(60); // no fixed length to allow translation
clearbutton->setFixedHeight(20);
clearbutton->setFocusPolicy(Qt::NoFocus);
connect(clearbutton, SIGNAL(clicked()), this, SLOT(clearClicked()));
return clearbutton;
}
#else
QPushButton *newclear() {
if (clearbutton) delete clearbutton; // we only need one!
clearbutton = new QPushButton(tr("Clear"), this);
// clearbutton->setFixedWidth(60); // no fixed length to allow translation
clearbutton->setFixedHeight(20);
clearbutton->setFocusPolicy(Qt::NoFocus);
connect(clearbutton, SIGNAL(clicked()), this, SLOT(clearClicked()));
return clearbutton;
}
#endif
#ifdef Q_OS_MAC
QtMacButton *newtoggle() {
if (toggle) delete toggle; // we only need one!
toggle = new QtMacButton(tr("OFF"), this);
// toggle->setFixedWidth(40); // no fixed length to allow translation
toggle->setFixedHeight(20);
toggle->setFocusPolicy(Qt::NoFocus);
connect(toggle, SIGNAL(clicked()), this, SLOT(toggled()));
return toggle;
}
#else
QPushButton *newtoggle() {
if (toggle) delete toggle; // we only need one!
toggle = new QPushButton(tr("OFF"), this);
toggle->setCheckable(true);
toggle->setChecked(false);
// toggle->setFixedWidth(40); // no fixed length to allow translation
toggle->setFixedHeight(20);
toggle->setFocusPolicy(Qt::NoFocus);
connect(toggle, SIGNAL(clicked()), this, SLOT(toggled()));
return toggle;
}
#endif
virtual void dragEnterEvent(QDragEnterEvent *event) {
// we handle intervals or seasons
if (event->mimeData()->formats().contains("application/x-gc-intervals") ||
event->mimeData()->formats().contains("application/x-gc-seasons")) {
if (tabView->hasBottom() && tabView->isShowBottom() == false) {
showForDrag = true;
tabView->dragEvent(true);
}
event->acceptProposedAction(); // always accept for this mimeData type
// so we continue to get the leave events we ignore (!)
}
}
virtual void dragLeaveEvent(QDragLeaveEvent *) {
int X = this->mapFromGlobal(QCursor::pos()).x();
int Y = this->mapFromGlobal(QCursor::pos()).y();
// ignore events when the cursor doesn't actually leave the bounds
// of our view -- its just going over multiple widgets
if (X>0 && Y>0 && X <= geometry().width() && Y <= geometry().height()) return;
if (showForDrag == true && !underMouse() && tabView->hasBottom() && tabView->isShowBottom() == true) {
showForDrag = false;
tabView->dragEvent(false);
}
}
public:
Q_PROPERTY(int hpos READ hpos WRITE sethpos USER true)
// handle position
int hpos() const { if (sizes().count() == 2) return sizes()[0]; else return 0; }
void sethpos(int x) {
if (x<0) return; //r requested size too small!
QList<int> csizes = sizes();
if (csizes.count() != 2) return; //don't have two widgets!
int tot = csizes[0] + csizes[1];
if (tot < x) return; // requested size too big!
csizes[0] = x;
csizes[1] = tot-x;
setSizes(csizes);
}
// max hpos
int maxhpos() {
QList<int> csizes = sizes();
if (csizes.count() != 2) return 0; //don't have two widgets!
int tot = csizes[0] + csizes[1];
return tot - 1;
}
signals:
void compareChanged(bool);
void compareClear();
public slots:
void toggled() {
QFont font;
if (toggle->isChecked()) {
font.setWeight(QFont::Bold);
toggle->setFont(font);
toggle->setStyleSheet("color: red");
toggle->setText(tr("ON"));
} else {
font.setWeight(QFont::Normal);
toggle->setFont(font);
toggle->setStyleSheet("");
toggle->setText(tr("OFF"));
}
// we started compare mode
emit compareChanged(toggle->isChecked());
}
void clearClicked() {
emit compareClear();
}
private:
Qt::Orientation orientation;
QString name;
TabView *tabView;
bool showForDrag;
#ifdef Q_OS_MAC
QtMacButton *toggle, *clearbutton;
#else
QPushButton *toggle, *clearbutton;
#endif
};
#endif // _GC_TabView_h