LTMSidebar::LTMSidebar(MainWindow *parent, const QDir &home) : QWidget(parent), home(home), main(parent), active(false)
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(0,0,0,0);
    mainLayout->setSpacing(0);
    setContentsMargins(0,0,0,0);

    seasonsWidget = new GcSplitterItem(tr("Date Ranges"), iconFromPNG(":images/sidebar/calendar.png"), this);
    QAction *moreSeasonAct = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
    seasonsWidget->addAction(moreSeasonAct);
    connect(moreSeasonAct, SIGNAL(triggered(void)), this, SLOT(dateRangePopup(void)));

    dateRangeTree = new SeasonTreeView;
    //allDateRanges = new QTreeWidgetItem(dateRangeTree, ROOT_TYPE);
    allDateRanges=dateRangeTree->invisibleRootItem();
    // Drop for Seasons
    allDateRanges->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
    allDateRanges->setText(0, tr("Date Ranges"));
    dateRangeTree->setFrameStyle(QFrame::NoFrame);
    dateRangeTree->setColumnCount(1);
    dateRangeTree->setSelectionMode(QAbstractItemView::SingleSelection);
    dateRangeTree->header()->hide();
    dateRangeTree->setIndentation(5);
    dateRangeTree->expandItem(allDateRanges);
    dateRangeTree->setContextMenuPolicy(Qt::CustomContextMenu);
#ifdef Q_OS_MAC
    dateRangeTree->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
    seasonsWidget->addWidget(dateRangeTree);


    eventsWidget = new GcSplitterItem(tr("Events"), iconFromPNG(":images/sidebar/bookmark.png"), this);
    QAction *moreEventAct = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
    eventsWidget->addAction(moreEventAct);
    connect(moreEventAct, SIGNAL(triggered(void)), this, SLOT(eventPopup(void)));


    eventTree = new QTreeWidget;
    eventTree->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    //allEvents = new QTreeWidgetItem(eventTree, ROOT_TYPE);
    allEvents = eventTree->invisibleRootItem();
    allEvents->setText(0, tr("Events"));
    eventTree->setFrameStyle(QFrame::NoFrame);
    eventTree->setColumnCount(2);
    eventTree->setSelectionMode(QAbstractItemView::SingleSelection);
    eventTree->header()->hide();
    eventTree->setIndentation(5);
    eventTree->expandItem(allEvents);
    eventTree->setContextMenuPolicy(Qt::CustomContextMenu);
    eventTree->horizontalScrollBar()->setDisabled(true);
    eventTree->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
#ifdef Q_OS_MAC
    eventTree->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
    eventsWidget->addWidget(eventTree);

    seasons = parent->seasons;
    resetSeasons(); // reset the season list

    configChanged(); // will reset the metric tree

    splitter = new GcSplitter(Qt::Vertical);
    splitter->addWidget(seasonsWidget);
    splitter->addWidget(eventsWidget);

    GcSplitterItem *summaryWidget = new GcSplitterItem(tr("Summary"), iconFromPNG(":images/sidebar/dashboard.png"), this);

    summary = new QWebView(this);
    summary->setContentsMargins(0,0,0,0);
    summary->page()->view()->setContentsMargins(0,0,0,0);
    summary->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
    summary->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    summary->setAcceptDrops(false);

    summaryWidget->addWidget(summary);

    QFont defaultFont; // mainwindow sets up the defaults.. we need to apply
    summary->settings()->setFontSize(QWebSettings::DefaultFontSize, defaultFont.pointSize());
    summary->settings()->setFontFamily(QWebSettings::StandardFont, defaultFont.family());
    splitter->addWidget(summaryWidget);

    mainLayout->addWidget(splitter);

    splitter->prepare(main->cyclist, "LTM");

    // our date ranges
    connect(dateRangeTree,SIGNAL(itemSelectionChanged()), this, SLOT(dateRangeTreeWidgetSelectionChanged()));
    connect(dateRangeTree,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(dateRangePopup(const QPoint &)));
    connect(dateRangeTree,SIGNAL(itemChanged(QTreeWidgetItem *,int)), this, SLOT(dateRangeChanged(QTreeWidgetItem*, int)));
    connect(dateRangeTree,SIGNAL(itemMoved(QTreeWidgetItem *,int, int)), this, SLOT(dateRangeMoved(QTreeWidgetItem*, int, int)));
    connect(eventTree,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(eventPopup(const QPoint &)));
    // GC signal
    connect(main, SIGNAL(configChanged()), this, SLOT(configChanged()));
    connect(seasons, SIGNAL(seasonsChanged()), this, SLOT(resetSeasons()));

    connect(this, SIGNAL(dateRangeChanged(DateRange)), this, SLOT(setSummary(DateRange)));

    // let everyone know what date range we are starting with
    dateRangeTreeWidgetSelectionChanged();

}
IntervalSidebar::IntervalSidebar(Context *context) : QWidget(context->mainWindow), context(context)
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(0,0,0,0);
    mainLayout->setSpacing(0);
    setContentsMargins(0,0,0,0);
    
    splitter = new GcSplitter(Qt::Vertical);
    mainLayout->addWidget(splitter);

    // Route
    routeNavigator = new IntervalNavigator(context, "Route", true);
    routeNavigator->setProperty("nomenu", true);
    groupByMapper = NULL;

    // Bests
    bestNavigator = new IntervalNavigator(context, "Best", true);
    bestNavigator->setProperty("nomenu", true);


    // retrieve settings (properties are saved when we close the window)
    if (appsettings->cvalue(context->athlete->cyclist, GC_ROUTEHEADINGS, "").toString() != "") {
        routeNavigator->setSortByIndex(appsettings->cvalue(context->athlete->cyclist, GC_ROUTESORTBY).toInt());
        routeNavigator->setSortByOrder(appsettings->cvalue(context->athlete->cyclist, GC_ROUTESORTBYORDER).toInt());
        //routeNavigator->setGroupBy(appsettings->cvalue(context->athlete->cyclist, GC_ROUTEGROUPBY).toInt());
        routeNavigator->setColumns(appsettings->cvalue(context->athlete->cyclist, GC_ROUTEHEADINGS).toString());
        routeNavigator->setWidths(appsettings->cvalue(context->athlete->cyclist, GC_ROUTEHEADINGWIDTHS).toString());
    }
    if (appsettings->cvalue(context->athlete->cyclist, GC_BESTHEADINGS, "").toString() != "") {
        bestNavigator->setSortByIndex(appsettings->cvalue(context->athlete->cyclist, GC_BESTSORTBY).toInt());
        bestNavigator->setSortByOrder(appsettings->cvalue(context->athlete->cyclist, GC_BESTSORTBYORDER).toInt());
        bestNavigator->setColumns(appsettings->cvalue(context->athlete->cyclist, GC_BESTHEADINGS).toString());
        bestNavigator->setWidths(appsettings->cvalue(context->athlete->cyclist, GC_BESTHEADINGWIDTHS).toString());
    }

    QWidget *routeWidget = new QWidget(this);
    routeWidget->setContentsMargins(0,0,0,0);
#ifndef Q_OS_MAC // not on mac thanks
    routeWidget->setStyleSheet("padding: 0px; border: 0px; margin: 0px;");
#endif
    QVBoxLayout *routeLayout = new QVBoxLayout(routeWidget);
    routeLayout->setSpacing(0);
    routeLayout->setContentsMargins(0,0,0,0);
    routeLayout->addWidget(routeNavigator);

    routeItem = new GcSplitterItem(tr("Routes"), iconFromPNG(":images/sidebar/folder.png"), this);
    QAction *routeAction = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
    routeItem->addAction(routeAction);
    connect(routeAction, SIGNAL(triggered(void)), this, SLOT(routePopup()));
    routeItem->addWidget(routeWidget);




    QWidget *bestWidget = new QWidget(this);
    bestWidget->setContentsMargins(0,0,0,0);
#ifndef Q_OS_MAC // not on mac thanks
    bestWidget->setStyleSheet("padding: 0px; border: 0px; margin: 0px;");
#endif
    QVBoxLayout *bestLayout = new QVBoxLayout(bestWidget);
    bestLayout->setSpacing(0);
    bestLayout->setContentsMargins(0,0,0,0);
    bestLayout->addWidget(bestNavigator);

    bestItem = new GcSplitterItem(tr("Bests"), iconFromPNG(":images/sidebar/folder.png"), this);
    QAction *bestAction = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
    bestItem->addAction(bestAction);
    connect(bestAction, SIGNAL(triggered(void)), this, SLOT(bestPopup()));
    bestItem->addWidget(bestWidget);

    splitter->addWidget(routeItem);
    splitter->addWidget(bestItem);

    splitter->prepare(context->athlete->cyclist, "interval");

    // GC signal
    connect(context, SIGNAL(configChanged()), this, SLOT(configChanged()));

    // right click menus...
    connect(routeNavigator,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showRouteMenu(const QPoint &)));
    //connect(context->athlete->intervalWidget,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showIntervalMenu(const QPoint &)));
    connect(bestNavigator,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showBestMenu(const QPoint &)));

    connect (context, SIGNAL(filterChanged()), this, SLOT(filterChanged()));

    configChanged();
}
//********************************************************************************
// CALENDAR SIDEBAR (DiarySidebar)
//********************************************************************************
DiarySidebar::DiarySidebar(Context *context) : context(context)
{
    setContentsMargins(0,0,0,0);
    setAutoFillBackground(true);

    month = year = 0;
    _ride = NULL;

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setContentsMargins(0,0,0,0);
    mainLayout->setSpacing(0);

    // Splitter - cal at top, summary at bottom
    splitter = new GcSplitter(Qt::Vertical);
    mainLayout->addWidget(splitter);

    // calendar
    calendarItem = new GcSplitterItem(tr("Calendar"), iconFromPNG(":images/sidebar/calendar.png"), this);
    summaryItem = new GcSplitterItem(tr("Summary"), iconFromPNG(":images/sidebar/dashboard.png"), this);

    QPalette pal;
    pal.setColor(QPalette::Window, Qt::white);
    setPalette(pal);

    // cal widget
    QWidget *cal = new QWidget(this);
    cal->setPalette(pal);
    cal->setContentsMargins(0,0,0,0);
    cal->setStyleSheet("QLabel { color: gray; }");
    layout = new QVBoxLayout(cal);
    layout->setSpacing(0);
    layout->setContentsMargins(0,0,0,0);
    calendarItem->addWidget(cal);

    // summary widget
    QWidget *sum = new QWidget(this);
    sum->setPalette(pal);
    sum->setContentsMargins(0,0,0,0);
    QVBoxLayout *slayout = new QVBoxLayout(sum);
    slayout->setSpacing(0);
    summaryItem->addWidget(sum);

    splitter->addWidget(calendarItem);
    splitter->addWidget(summaryItem);
    splitter->prepare(context->athlete->cyclist, "diary");

    black.setColor(QPalette::WindowText, Qt::gray);
    white.setColor(QPalette::WindowText, Qt::white);
    grey.setColor(QPalette::WindowText, Qt::gray);

    multiCalendar = new GcMultiCalendar(context);
    layout->addWidget(multiCalendar);

    // Summary level selector
    QHBoxLayout *h = new QHBoxLayout();
    h->setSpacing(5);
    summarySelect = new QComboBox(this);
    summarySelect->setFixedWidth(150); // is it impossible to size constrain qcombos?
    summarySelect->addItem(tr("Day Summary"));
    summarySelect->addItem(tr("Weekly Summary"));
    summarySelect->addItem(tr("Monthly Summary"));
    summarySelect->setCurrentIndex(2); // default to monthly
    h->addStretch();
    h->addWidget(summarySelect, Qt::AlignCenter);
    h->addStretch();
    slayout->addLayout(h);

    summary = new QWebView(this);
    summary->setContentsMargins(0,0,0,0);
    summary->page()->view()->setContentsMargins(0,0,0,0);
    summary->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
    summary->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    summary->setAcceptDrops(false);

    QFont defaultFont; // mainwindow sets up the defaults.. we need to apply
    summary->settings()->setFontSize(QWebSettings::DefaultFontSize, defaultFont.pointSize());
    summary->settings()->setFontFamily(QWebSettings::StandardFont, defaultFont.family());
    slayout->addWidget(summary);
    slayout->addStretch();

    // summary mode changed
    connect(summarySelect, SIGNAL(currentIndexChanged(int)), this, SLOT(refresh()));

    // refresh on these events...
    connect(context, SIGNAL(rideAdded(RideItem*)), this, SLOT(refresh()));
    connect(context, SIGNAL(rideDeleted(RideItem*)), this, SLOT(refresh()));
    connect(context, SIGNAL(configChanged()), this, SLOT(refresh()));

    // set up for current selections
    refresh();
}
void
GcLabel::paintEvent(QPaintEvent *)
{
    static QIcon left = iconFromPNG(":images/mac/left.png");
    static QIcon right = iconFromPNG(":images/mac/right.png");

    QPainter painter(this);
    painter.save();
    painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing, true);

    // grr. some want a rect others want a rectf
    QRectF norm(0,0,width(),height());
    QRect all(0,0,width(),height());

    if (bg) {

        // setup a painter and the area to paint
        if (!underMouse()) painter.fillRect(all, bgColor);
        else {
            if (filtered) painter.fillRect(all, GColor(CCALCURRENT));
            else painter.fillRect(all, Qt::lightGray);
        }

        painter.setPen(Qt::gray);
        painter.drawRect(QRect(0,0,width(),height()));
    }

    if (selected) {
        painter.fillRect(all, GColor(CCALCURRENT));
    }

    if (text() != "<" && text() != ">") {
        painter.setFont(this->font());

        if (xoff || yoff) {

            // draw text in white behind...
            QRectF off(xoff,yoff,width(),height());
            painter.setPen(QColor(255,255,255,200));
            painter.drawText(off, alignment(), text());
        }

        if (filtered && !selected && !underMouse()) painter.setPen(GColor(CCALCURRENT));
        else painter.setPen(QColor(0,0,0,170));

        painter.drawText(norm, alignment(), text());

        if (highlighted) {
            QColor over = GColor(CCALCURRENT);
            over.setAlpha(180);
            painter.setPen(over);

            painter.drawText(norm, alignment(), text());
        }
    } else {

        // use standard icons
        QIcon &icon = text() == "<" ?  left : right;
        Qt::AlignmentFlag alignment = text() == "<" ? Qt::AlignLeft : Qt::AlignRight;

        icon.paint(&painter, all, alignment|Qt::AlignVCenter);
    }

    if (text() != ""  && filtered) {
        QPen pen;
        pen.setColor(GColor(CCALCURRENT));
        pen.setWidth(3);
        painter.setPen(pen);
        painter.drawRect(QRect(0,0,width(),height()));
    }
    painter.restore();
}
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);
    buttonBar->setFixedHeight(fs.height()+7);
#else
    setFixedHeight(fs.height()+4);
    scrollArea->setFixedHeight(fs.height()+4);
    buttonBar->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)));
}
Exemple #6
0
MainWindow::MainWindow(const QDir &home)
{
    /*----------------------------------------------------------------------
     *  Bootstrap
     *--------------------------------------------------------------------*/
    setAttribute(Qt::WA_DeleteOnClose);
    mainwindows.append(this);  // add us to the list of open windows
    context = new Context(this);
    context->athlete = new Athlete(context, home);

    setInstanceName(context->athlete->cyclist);
    setWindowIcon(QIcon(":images/gc.png"));
    setWindowTitle(context->athlete->home.dirName());
    setContentsMargins(0,0,0,0);
    setAcceptDrops(true);
    GCColor *GCColorSet = new GCColor(context); // get/keep colorset
    GCColorSet->colorSet(); // shut up the compiler

    #ifdef Q_OS_MAC
    // get an autorelease pool setup
    static CocoaInitializer cocoaInitializer;
    #endif
    #ifdef GC_HAVE_WFAPI
    WFApi *w = WFApi::getInstance(); // ensure created on main thread
    w->apiVersion();//shutup compiler
    #endif
    Library::initialise(context->athlete->home);
    QNetworkProxyQuery npq(QUrl("http://www.google.com"));
    QList<QNetworkProxy> listOfProxies = QNetworkProxyFactory::systemProxyForQuery(npq);
    if (listOfProxies.count() > 0) {
        QNetworkProxy::setApplicationProxy(listOfProxies.first());
    }

    if (desktop == NULL) desktop = QApplication::desktop();
    static const QIcon hideIcon(":images/toolbar/main/hideside.png");
    static const QIcon rhideIcon(":images/toolbar/main/hiderside.png");
    static const QIcon showIcon(":images/toolbar/main/showside.png");
    static const QIcon rshowIcon(":images/toolbar/main/showrside.png");
    static const QIcon tabIcon(":images/toolbar/main/tab.png");
    static const QIcon tileIcon(":images/toolbar/main/tile.png");
    static const QIcon fullIcon(":images/toolbar/main/togglefull.png");

#if (defined Q_OS_MAC) && (defined GC_HAVE_LION)
    fullScreen = new LionFullScreen(context);
#endif
#ifndef Q_OS_MAC
    fullScreen = new QTFullScreen(context);
#endif

    // if no workout directory is configured, default to the
    // top level GoldenCheetah directory
    if (appsettings->value(NULL, GC_WORKOUTDIR).toString() == "")
        appsettings->setValue(GC_WORKOUTDIR, QFileInfo(context->athlete->home.absolutePath() + "/../").absolutePath());

    /*----------------------------------------------------------------------
     *  GUI setup
     *--------------------------------------------------------------------*/

    // need to restore geometry before setUnifiedToolBar.. on Mac
    appsettings->setValue(GC_SETTINGS_LAST, context->athlete->home.dirName());
    QVariant geom = appsettings->value(this, GC_SETTINGS_MAIN_GEOM);
    if (geom == QVariant()) {

        // first run -- lets set some sensible defaults...
        // lets put it in the middle of screen 1
        QRect size = desktop->availableGeometry();
        struct SizeSettings app = GCColor::defaultSizes(size.height(), size.width());

        // center on the available screen (minus toolbar/sidebar)
        move((size.width()-size.x())/2 - app.width/2,
             (size.height()-size.y())/2 - app.height/2);

        // set to the right default
        resize(app.width, app.height);

        // set all the default font sizes
        appsettings->setValue(GC_FONT_DEFAULT_SIZE, app.defaultFont);
        appsettings->setValue(GC_FONT_TITLES_SIZE, app.titleFont);
        appsettings->setValue(GC_FONT_CHARTMARKERS_SIZE, app.markerFont);
        appsettings->setValue(GC_FONT_CHARTLABELS_SIZE, app.labelFont);
        appsettings->setValue(GC_FONT_CALENDAR_SIZE, app.calendarFont);
        appsettings->setValue(GC_FONT_POPUP_SIZE, app.popupFont);

        // set the default fontsize
        QFont font;
        font.setPointSize(app.defaultFont);
        QApplication::setFont(font);

    } else {

        QRect size = desktop->availableGeometry();

        // ensure saved geometry isn't greater than current screen size
        if ((geom.toRect().height() >= size.height()) || (geom.toRect().width() >= size.width()))
            setGeometry(size.x()+30,size.y()+30,size.width()-60,size.height()-60);
        else
            setGeometry(geom.toRect());
    }


    /*----------------------------------------------------------------------
     *  Mac Toolbar
     *--------------------------------------------------------------------*/
#ifdef Q_OS_MAC 
    setUnifiedTitleAndToolBarOnMac(true);
    head = addToolBar(context->athlete->cyclist);
    head->setContentsMargins(0,0,0,0);

    // widgets
    QWidget *macAnalButtons = new QWidget(this);
    macAnalButtons->setContentsMargins(0,0,20,0);

    // lhs buttons
    QHBoxLayout *lb = new QHBoxLayout(macAnalButtons);
    lb->setContentsMargins(0,0,0,0);
    lb->setSpacing(0);
    import = new QtMacButton(this, QtMacButton::TexturedRounded);
    QPixmap *importImg = new QPixmap(":images/mac/download.png");
    import->setImage(importImg);
    import->setToolTip("Download");
    lb->addWidget(import);
    lb->addWidget(new Spacer(this));
    compose = new QtMacButton(this, QtMacButton::TexturedRounded);
    QPixmap *composeImg = new QPixmap(":images/mac/compose.png");
    compose->setImage(composeImg);
    compose->setToolTip("Create");
    lb->addWidget(compose);

    // connect to actions
    connect(import, SIGNAL(clicked(bool)), this, SLOT(downloadRide()));
    connect(compose, SIGNAL(clicked(bool)), this, SLOT(manualRide()));

    lb->addWidget(new Spacer(this));

    // activity actions .. peaks, split, delete
    QWidget *acts = new QWidget(this);
    acts->setContentsMargins(0,0,0,0);
    QHBoxLayout *pp = new QHBoxLayout(acts);
    pp->setContentsMargins(0,0,0,0);
    pp->setContentsMargins(0,0,0,0);
    pp->setSpacing(5);
    sidebar = new QtMacButton(this, QtMacButton::TexturedRounded);
    QPixmap *sidebarImg = new QPixmap(":images/mac/sidebar.png");
    sidebar->setImage(sidebarImg);
    sidebar->setMinimumSize(25, 25);
    sidebar->setMaximumSize(25, 25);
    sidebar->setToolTip("Sidebar");
    sidebar->setSelected(true); // assume always start up with sidebar selected

    actbuttons = new QtMacSegmentedButton(3, acts);
    actbuttons->setWidth(115);
    actbuttons->setNoSelect();
    actbuttons->setImage(0, new QPixmap(":images/mac/stop.png"));
    actbuttons->setImage(1, new QPixmap(":images/mac/split.png"));
    actbuttons->setImage(2, new QPixmap(":images/mac/trash.png"));
    pp->addWidget(actbuttons);
    lb->addWidget(acts);
    lb->addStretch();
    connect(actbuttons, SIGNAL(clicked(int,bool)), this, SLOT(actionClicked(int)));

    lb->addWidget(new Spacer(this));

    QWidget *viewsel = new QWidget(this);
    viewsel->setContentsMargins(0,0,0,0);
    QHBoxLayout *pq = new QHBoxLayout(viewsel);
    pq->setContentsMargins(0,0,0,0);
    pq->setSpacing(5);
    pq->addWidget(sidebar);
    styleSelector = new QtMacSegmentedButton(2, viewsel);
    styleSelector->setWidth(80); // actually its 80 but we want a 30px space between is and the searchbox
    styleSelector->setImage(0, new QPixmap(":images/mac/tabbed.png"), 24);
    styleSelector->setImage(1, new QPixmap(":images/mac/tiled.png"), 24);
    pq->addWidget(styleSelector);
    connect(sidebar, SIGNAL(clicked(bool)), this, SLOT(toggleSidebar()));
    connect(styleSelector, SIGNAL(clicked(int,bool)), this, SLOT(toggleStyle()));

    // setup Mac thetoolbar
    head->addWidget(macAnalButtons);
    head->addWidget(new Spacer(this));
    head->addWidget(new Spacer(this));
    head->addWidget(viewsel);

#ifdef GC_HAVE_LUCENE
    SearchFilterBox *searchBox = new SearchFilterBox(this,context,false);
    QCleanlooksStyle *toolStyle = new QCleanlooksStyle();
    searchBox->setStyle(toolStyle);
    searchBox->setFixedWidth(200);
    head->addWidget(searchBox);
    connect(searchBox, SIGNAL(searchResults(QStringList)), this, SLOT(setFilter(QStringList)));
    connect(searchBox, SIGNAL(searchClear()), this, SLOT(clearFilter()));
#endif

#endif 

    /*----------------------------------------------------------------------
     *  Windows and Linux Toolbar
     *--------------------------------------------------------------------*/
#ifndef Q_OS_MAC

    head = new GcToolBar(this);

    QCleanlooksStyle *toolStyle = new QCleanlooksStyle();
    QPalette metal;
    metal.setColor(QPalette::Button, QColor(215,215,215));

    // get those icons
    importIcon = iconFromPNG(":images/mac/download.png");
    composeIcon = iconFromPNG(":images/mac/compose.png");
    intervalIcon = iconFromPNG(":images/mac/stop.png");
    splitIcon = iconFromPNG(":images/mac/split.png");
    deleteIcon = iconFromPNG(":images/mac/trash.png");
    sidebarIcon = iconFromPNG(":images/mac/sidebar.png");
    tabbedIcon = iconFromPNG(":images/mac/tabbed.png");
    tiledIcon = iconFromPNG(":images/mac/tiled.png");
    QSize isize(19,19);

    Spacer *spacerl = new Spacer(this);
    spacerl->setFixedWidth(5);

    import = new QPushButton(this);
    import->setIcon(importIcon);
    import->setIconSize(isize);
    import->setFixedHeight(25);
    import->setStyle(toolStyle);
    import->setToolTip(tr("Download from Device"));
    import->setPalette(metal);
    connect(import, SIGNAL(clicked(bool)), this, SLOT(downloadRide()));

    compose = new QPushButton(this);
    compose->setIcon(composeIcon);
    compose->setIconSize(isize);
    compose->setFixedHeight(25);
    compose->setStyle(toolStyle);
    compose->setToolTip(tr("Create Manual Activity"));
    compose->setPalette(metal);
    connect(compose, SIGNAL(clicked(bool)), this, SLOT(manualRide()));

    sidebar = new QPushButton(this);
    sidebar->setIcon(sidebarIcon);
    sidebar->setIconSize(isize);
    sidebar->setFixedHeight(25);
    sidebar->setStyle(toolStyle);
    sidebar->setToolTip(tr("Toggle Sidebar"));
    sidebar->setPalette(metal);
    connect(sidebar, SIGNAL(clicked(bool)), this, SLOT(toggleSidebar()));

    actbuttons = new QtSegmentControl(this);
    actbuttons->setStyle(toolStyle);
    actbuttons->setIconSize(isize);
    actbuttons->setCount(3);
    actbuttons->setSegmentIcon(0, intervalIcon);
    actbuttons->setSegmentIcon(1, splitIcon);
    actbuttons->setSegmentIcon(2, deleteIcon);
    actbuttons->setSelectionBehavior(QtSegmentControl::SelectNone); //wince. spelling. ugh
    actbuttons->setFixedHeight(25);
    actbuttons->setSegmentToolTip(0, tr("Find Intervals..."));
    actbuttons->setSegmentToolTip(1, tr("Split Activity..."));
    actbuttons->setSegmentToolTip(2, tr("Delete Activity"));
    actbuttons->setPalette(metal);
    connect(actbuttons, SIGNAL(segmentSelected(int)), this, SLOT(actionClicked(int)));

    styleSelector = new QtSegmentControl(this);
    styleSelector->setStyle(toolStyle);
    styleSelector->setIconSize(isize);
    styleSelector->setCount(2);
    styleSelector->setSegmentIcon(0, tabbedIcon);
    styleSelector->setSegmentIcon(1, tiledIcon);
    styleSelector->setSegmentToolTip(0, tr("Tabbed View"));
    styleSelector->setSegmentToolTip(1, tr("Tiled View"));
    styleSelector->setSelectionBehavior(QtSegmentControl::SelectOne); //wince. spelling. ugh
    styleSelector->setFixedHeight(25);
    styleSelector->setPalette(metal);
    connect(styleSelector, SIGNAL(segmentSelected(int)), this, SLOT(setStyleFromSegment(int))); //avoid toggle infinitely

    head->addWidget(spacerl);
    head->addWidget(import);
    head->addWidget(compose);
    head->addWidget(actbuttons);

    head->addStretch();
    head->addWidget(sidebar);
    head->addWidget(styleSelector);

#ifdef GC_HAVE_LUCENE
    // add a search box on far right, but with a little space too
    SearchFilterBox *searchBox = new SearchFilterBox(this,context,false);
    searchBox->setStyle(toolStyle);
    searchBox->setFixedWidth(200);
    head->addWidget(searchBox);
    connect(searchBox, SIGNAL(searchResults(QStringList)), this, SLOT(setFilter(QStringList)));
    connect(searchBox, SIGNAL(searchClear()), this, SLOT(clearFilter()));
#endif
    Spacer *spacer = new Spacer(this);
    spacer->setFixedWidth(5);
    head->addWidget(spacer);
#endif

    /*----------------------------------------------------------------------
     * ScopeBar
     *--------------------------------------------------------------------*/
    scopebar = new GcScopeBar(context);
    connect(scopebar, SIGNAL(selectDiary()), this, SLOT(selectDiary()));
    connect(scopebar, SIGNAL(selectHome()), this, SLOT(selectHome()));
    connect(scopebar, SIGNAL(selectAnal()), this, SLOT(selectAnalysis()));
    connect(scopebar, SIGNAL(selectTrain()), this, SLOT(selectTrain()));

    // Add chart is on the scope bar
    chartMenu = new QMenu(this);
    QCleanlooksStyle *styler = new QCleanlooksStyle();
    QPushButton *newchart = new QPushButton("+", this);
    scopebar->addWidget(newchart);
    newchart->setStyle(styler);
    newchart->setFixedHeight(20);
    newchart->setFixedWidth(24);
    newchart->setFlat(true);
    newchart->setFocusPolicy(Qt::NoFocus);
    newchart->setToolTip(tr("Add Chart"));
    newchart->setAutoFillBackground(false);
    newchart->setAutoDefault(false);
    newchart->setMenu(chartMenu);
    connect(chartMenu, SIGNAL(aboutToShow()), this, SLOT(setChartMenu()));
    connect(chartMenu, SIGNAL(triggered(QAction*)), this, SLOT(addChart(QAction*)));

    /*----------------------------------------------------------------------
     * Central Widget
     *--------------------------------------------------------------------*/

    tab = new Tab(context);

    /*----------------------------------------------------------------------
     * Central Widget
     *--------------------------------------------------------------------*/

    QWidget *central = new QWidget(this);
    setContentsMargins(0,0,0,0);
    central->setContentsMargins(0,0,0,0);
    QVBoxLayout *mainLayout = new QVBoxLayout(central);
    mainLayout->setSpacing(0);
    mainLayout->setContentsMargins(0,0,0,0);
#ifndef Q_OS_MAC // nonmac toolbar on main view -- its not 
                 // unified with the title bar.
    mainLayout->addWidget(head);
#endif
    mainLayout->addWidget(scopebar);
    mainLayout->addWidget(tab);
    setCentralWidget(central);

    /*----------------------------------------------------------------------
     * Application Menus
     *--------------------------------------------------------------------*/
#ifdef WIN32
    menuBar()->setStyleSheet("QMenuBar { background: rgba(225,225,225); }"
		    	     "QMenuBar::item { background: rgba(225,225,225); }");
    menuBar()->setContentsMargins(0,0,0,0);
#endif

    QMenu *fileMenu = menuBar()->addMenu(tr("&Athlete"));
    fileMenu->addAction(tr("&New..."), this, SLOT(newCyclist()), tr("Ctrl+N"));
    fileMenu->addAction(tr("&Open..."), this, SLOT(openCyclist()), tr("Ctrl+O"));
    fileMenu->addAction(tr("&Close Window"), this, SLOT(close()), tr ("Ctrl+W"));
    fileMenu->addAction(tr("&Quit All Windows"), this, SLOT(closeAll()), tr("Ctrl+Q"));

    QMenu *rideMenu = menuBar()->addMenu(tr("A&ctivity"));
    rideMenu->addAction(tr("&Download from device..."), this, SLOT(downloadRide()), tr("Ctrl+D"));
    rideMenu->addAction(tr("&Import from file..."), this, SLOT (importFile()), tr ("Ctrl+I"));
    rideMenu->addAction(tr("&Manual activity entry..."), this, SLOT(manualRide()), tr("Ctrl+M"));
    rideMenu->addSeparator ();
    rideMenu->addAction(tr("&Export..."), this, SLOT(exportRide()), tr("Ctrl+E"));
    rideMenu->addAction(tr("&Batch export..."), this, SLOT(exportBatch()), tr("Ctrl+B"));
    rideMenu->addAction(tr("Export Metrics as CSV..."), this, SLOT(exportMetrics()), tr(""));
#ifdef GC_HAVE_SOAP
    rideMenu->addSeparator ();
    rideMenu->addAction(tr("&Upload to TrainingPeaks"), this, SLOT(uploadTP()), tr("Ctrl+U"));
    rideMenu->addAction(tr("Down&load from TrainingPeaks..."), this, SLOT(downloadTP()), tr("Ctrl+L"));
#endif

#ifdef GC_HAVE_LIBOAUTH
    tweetAction = new QAction(tr("Tweet Activity"), this);
    connect(tweetAction, SIGNAL(triggered(bool)), this, SLOT(tweetRide()));
    rideMenu->addAction(tweetAction);

    shareAction = new QAction(tr("Share (Strava, RideWithGPS, CyclingAnalytics)..."), this);
    connect(shareAction, SIGNAL(triggered(bool)), this, SLOT(share()));
    rideMenu->addAction(shareAction);
#endif

    ttbAction = new QAction(tr("Upload to Trainingstagebuch..."), this);
    connect(ttbAction, SIGNAL(triggered(bool)), this, SLOT(uploadTtb()));
    rideMenu->addAction(ttbAction);

    rideMenu->addSeparator ();
    rideMenu->addAction(tr("&Save activity"), this, SLOT(saveRide()), tr("Ctrl+S"));
    rideMenu->addAction(tr("D&elete activity..."), this, SLOT(deleteRide()));
    rideMenu->addAction(tr("Split &activity..."), this, SLOT(splitRide()));
    rideMenu->addAction(tr("Merge activities..."), this, SLOT(mergeRide()));
    rideMenu->addSeparator ();

    QMenu *optionsMenu = menuBar()->addMenu(tr("&Tools"));
    optionsMenu->addAction(tr("&Options..."), this, SLOT(showOptions()));
    optionsMenu->addAction(tr("Critical Power Estimator..."), this, SLOT(showTools()));
    optionsMenu->addAction(tr("Air Density (Rho) Estimator..."), this, SLOT(showRhoEstimator()));

    optionsMenu->addSeparator();
    optionsMenu->addAction(tr("Get &Withings Data..."), this,
                        SLOT (downloadMeasures()));
    optionsMenu->addAction(tr("Get &Zeo Data..."), this,
                        SLOT (downloadMeasuresFromZeo()));
    optionsMenu->addSeparator();
    optionsMenu->addAction(tr("Create a new workout..."), this, SLOT(showWorkoutWizard()));
    optionsMenu->addAction(tr("Download workouts from ErgDB..."), this, SLOT(downloadErgDB()));
    optionsMenu->addAction(tr("Import workouts or videos..."), this, SLOT(importWorkout()));
    optionsMenu->addAction(tr("Scan disk for videos and workouts..."), this, SLOT(manageLibrary()));

#ifdef GC_HAVE_ICAL
    optionsMenu->addSeparator();
    optionsMenu->addAction(tr("Upload Activity to Calendar"), this, SLOT(uploadCalendar()), tr (""));
    //optionsMenu->addAction(tr("Import Calendar..."), this, SLOT(importCalendar()), tr ("")); // planned for v3.1
    //optionsMenu->addAction(tr("Export Calendar..."), this, SLOT(exportCalendar()), tr ("")); // planned for v3.1
    optionsMenu->addAction(tr("Refresh Calendar"), this, SLOT(refreshCalendar()), tr (""));
#endif
    optionsMenu->addSeparator();
    optionsMenu->addAction(tr("Find intervals..."), this, SLOT(addIntervals()), tr (""));

    // Add all the data processors to the tools menu
    const DataProcessorFactory &factory = DataProcessorFactory::instance();
    QMap<QString, DataProcessor*> processors = factory.getProcessors();

    if (processors.count()) {

        optionsMenu->addSeparator();
        toolMapper = new QSignalMapper(this); // maps each option
        QMapIterator<QString, DataProcessor*> i(processors);
        connect(toolMapper, SIGNAL(mapped(const QString &)), this, SLOT(manualProcess(const QString &)));

        i.toFront();
        while (i.hasNext()) {
            i.next();
            // The localized processor name is shown in menu
            QAction *action = new QAction(QString("%1...").arg(i.value()->name()), this);
            optionsMenu->addAction(action);
            connect(action, SIGNAL(triggered()), toolMapper, SLOT(map()));
            toolMapper->setMapping(action, i.key());
        }
    }
GcOverlayWidget::GcOverlayWidget(Context *context, QWidget *parent) : QWidget(parent), context(context)
{
    // left / right scroller icon
    static QIcon leftIcon = iconFromPNG(":images/mac/left.png");
    static QIcon rightIcon = iconFromPNG(":images/mac/right.png");

    setContentsMargins(4,0,4,4);
    setAutoFillBackground(false);
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);
    setFocusPolicy(Qt::ClickFocus);
    setMinimumSize(250,200);
    setFocus();
    mode = none;
    initial = true;

    // main layout
    QVBoxLayout *mlayout = new QVBoxLayout(this);
    mlayout->setSpacing(0);
    mlayout->setContentsMargins(1,0,1,1);

    QHBoxLayout *titleLayout = new QHBoxLayout;
    titleLayout->setSpacing(0);
    titleLayout->setContentsMargins(0,0,0,0);
    mlayout->addLayout(titleLayout);

    // scroller buttons
    left = new QToolButton(this);
    left->setStyleSheet("QToolButton { border: none; padding: 0px; }");
    left->setAutoFillBackground(false);
    left->setFixedSize(23,23);
    left->setIcon(leftIcon);
    left->setIconSize(QSize(23,23));
    left->setFocusPolicy(Qt::NoFocus);
    left->hide(); // don't show until we have >1 widgets
    titleLayout->addWidget(left);
    connect(left, SIGNAL(clicked()), this, SLOT(scrollLeft()));

    titleLabel = new GcLabel("No Title Set");
    titleLabel->setAutoFillBackground(false);
    titleLabel->setFixedHeight(23);

    // menu bar in the middle of the buttons
    titleLayout->addStretch();
    titleLayout->addWidget(titleLabel);
    titleLayout->addStretch();

    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);
    right->hide();
    titleLayout->addWidget(right);
    connect(right, SIGNAL(clicked()), this, SLOT(scrollRight()));

    stack = new QStackedWidget(this);
    stack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    mlayout->addWidget(stack);

    // trap resize / mouse events
    m_infocus = true;
    m_showMenu = false;
    m_isEditing = true;
    installEventFilter(parent);

    connect(context, SIGNAL(configChanged()), this, SLOT(configChanged()));

    // setup colors
    configChanged();
}