mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Added a graphical splashscreen (#4468)
* Based on QSplashScreen * Shrinking the image for low resolutions (screen width <= 1280, < 1024) * Dynamically adding Golden Cheetahs version and build id * Showing messages related to the current loading state (including the current counter) * Closing the splashscreen as close as possible to showing the MainWindow * The image (splashscreen.svg) was created using Inkscape
This commit is contained in:
committed by
GitHub
parent
d0e536306f
commit
8718974722
@@ -175,7 +175,9 @@ Athlete::Athlete(Context *context, const QDir &homeDir)
|
||||
connect(rideCache, SIGNAL(loadComplete()), this, SLOT(loadComplete()));
|
||||
|
||||
// we need to block on load complete if first (before mainwindow ready)
|
||||
if (context->mainWindow->progress) loop.exec();
|
||||
if (context->mainWindow->isStarting()) {
|
||||
loop.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -137,6 +137,8 @@ Context::Context(MainWindow *mainWindow): mainWindow(mainWindow)
|
||||
isCompareIntervals = isCompareDateRanges = false;
|
||||
isRunning = isPaused = false;
|
||||
|
||||
connect(this, SIGNAL(loadProgress(QString, double)), mainWindow, SLOT(loadProgress(QString, double)));
|
||||
|
||||
#ifdef GC_HAS_CLOUD_DB
|
||||
cdbChartListDialog = NULL;
|
||||
cdbUserMetricListDialog = NULL;
|
||||
|
||||
@@ -82,17 +82,8 @@ ride: '{' rideelement_list '}' {
|
||||
jc->api->writeRideLine(jc->item, jc->request, jc->response);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
double progress= double(jc->loading++) / double(jc->cache->rides().count()) * 100.0f;
|
||||
if (jc->context->mainWindow->progress) {
|
||||
|
||||
// percentage progress
|
||||
QString m = QString("%1%").arg(progress , 0, 'f', 0);
|
||||
jc->context->mainWindow->progress->setText(m);
|
||||
QApplication::processEvents();
|
||||
} else {
|
||||
jc->context->notifyLoadProgress(jc->folder,progress);
|
||||
}
|
||||
jc->context->notifyLoadProgress(jc->folder,progress);
|
||||
|
||||
// find entry and update it
|
||||
int index=jc->cache->find(&jc->item);
|
||||
|
||||
@@ -137,7 +137,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
|
||||
// create a splash to keep user informed on first load
|
||||
// first one in middle of display, not middle of window
|
||||
setSplash(true);
|
||||
setSplash();
|
||||
|
||||
#if defined(_MSC_VER) && defined(_WIN64)
|
||||
// set dbg/stacktrace directory for Windows to the athlete directory
|
||||
@@ -154,9 +154,6 @@ MainWindow::MainWindow(const QDir &home)
|
||||
context->athlete = new Athlete(context, home);
|
||||
currentAthleteTab = new AthleteTab(context);
|
||||
|
||||
// get rid of splash when currentTab is shown
|
||||
clearSplash();
|
||||
|
||||
setWindowIcon(QIcon(":images/gc.png"));
|
||||
setWindowTitle(context->athlete->home->root().dirName());
|
||||
setContentsMargins(0,0,0,0);
|
||||
@@ -182,10 +179,11 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* GUI setup
|
||||
*--------------------------------------------------------------------*/
|
||||
if (appsettings->contains(GC_SETTINGS_MAIN_GEOM)) {
|
||||
splash->showMessage(tr("Setting up GUI..."));
|
||||
if (appsettings->contains(GC_SETTINGS_MAIN_GEOM)) {
|
||||
restoreGeometry(appsettings->value(this, GC_SETTINGS_MAIN_GEOM).toByteArray());
|
||||
restoreState(appsettings->value(this, GC_SETTINGS_MAIN_STATE).toByteArray());
|
||||
} else {
|
||||
} else {
|
||||
|
||||
AppearanceSettings defaults = GSettings::defaultAppearanceSettings();
|
||||
|
||||
@@ -201,6 +199,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* ScopeBar as sidebar from v3.6
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Setting up GUI: Scopebar..."));
|
||||
|
||||
sidebar = new NewSideBar(context, this);
|
||||
HelpWhatsThis *helpNewSideBar = new HelpWhatsThis(sidebar);
|
||||
@@ -238,6 +237,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* What's this Context Help
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Setting up GUI: Context Help..."));
|
||||
|
||||
// Help for the whole window
|
||||
HelpWhatsThis *help = new HelpWhatsThis(this);
|
||||
@@ -250,6 +250,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* Toolbar
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Setting up GUI: Toolbar..."));
|
||||
head = new GcToolBar(this);
|
||||
|
||||
QStyle *toolStyle = QStyleFactory::create("fusion");
|
||||
@@ -394,6 +395,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* Central Widget
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Setting up GUI: Central Widget..."));
|
||||
|
||||
tabbar = new DragBar(this);
|
||||
tabbar->setTabsClosable(false); // use athlete view
|
||||
@@ -461,6 +463,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* Application Menus
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Setting up GUI: Application Menus..."));
|
||||
#ifdef WIN32
|
||||
QString menuColorString = GColor(CTOOLBAR).name();
|
||||
menuBar()->setStyleSheet(QString("QMenuBar { color: black; background: %1; }"
|
||||
@@ -699,6 +702,7 @@ MainWindow::MainWindow(const QDir &home)
|
||||
/*----------------------------------------------------------------------
|
||||
* Lets go, choose latest ride and get GUI up and running
|
||||
*--------------------------------------------------------------------*/
|
||||
splash->showMessage(tr("Selecting ride..."));
|
||||
|
||||
showTabbar(appsettings->value(NULL, GC_TABBAR, "0").toBool());
|
||||
|
||||
@@ -725,12 +729,14 @@ MainWindow::MainWindow(const QDir &home)
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
#if !defined(OPENDATA_DISABLE)
|
||||
splash->showMessage(tr("Checking for udates..."));
|
||||
OpenData::check(currentAthleteTab->context);
|
||||
#else
|
||||
fprintf(stderr, "OpenData disabled, secret not defined.\n"); fflush(stderr);
|
||||
#endif
|
||||
|
||||
#ifdef GC_HAS_CLOUD_DB
|
||||
splash->showMessage(tr("Asking for telemetry..."));
|
||||
telemetryClient = new CloudDBTelemetryClient();
|
||||
if (appsettings->value(NULL, GC_ALLOW_TELEMETRY, "undefined").toString() == "undefined" ) {
|
||||
// ask user if storing is allowed
|
||||
@@ -752,6 +758,8 @@ MainWindow::MainWindow(const QDir &home)
|
||||
|
||||
#endif
|
||||
|
||||
// get rid of splash when currentTab is shown
|
||||
clearSplash();
|
||||
}
|
||||
|
||||
|
||||
@@ -760,47 +768,17 @@ MainWindow::MainWindow(const QDir &home)
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
MainWindow::setSplash(bool first)
|
||||
MainWindow::setSplash()
|
||||
{
|
||||
// new frameless widget
|
||||
splash = new QWidget(NULL);
|
||||
|
||||
// modal dialog with no parent so we set it up as a 'splash'
|
||||
// because QSplashScreen doesn't seem to work (!!)
|
||||
splash->setAttribute(Qt::WA_DeleteOnClose);
|
||||
splash->setWindowFlags(splash->windowFlags() | Qt::FramelessWindowHint);
|
||||
#ifdef Q_OS_LINUX
|
||||
splash->setWindowFlags(splash->windowFlags() | Qt::X11BypassWindowManagerHint);
|
||||
#endif
|
||||
|
||||
// put widgets on it
|
||||
progress = new QLabel(splash);
|
||||
progress->setAlignment(Qt::AlignCenter);
|
||||
QHBoxLayout *l = new QHBoxLayout(splash);
|
||||
l->setSpacing(0);
|
||||
l->addWidget(progress);
|
||||
|
||||
// lets go
|
||||
splash->setFixedSize(100 *dpiXFactor, 80 *dpiYFactor);
|
||||
|
||||
if (first) {
|
||||
// middle of screen
|
||||
splash->move(QGuiApplication::primaryScreen()->availableGeometry().center()-QPoint(50, 25));
|
||||
} else {
|
||||
// middle of mainwindow is appropriate
|
||||
splash->move(geometry().center()-QPoint(50, 25));
|
||||
}
|
||||
splash->show();
|
||||
|
||||
// reset the splash counter
|
||||
loading=1;
|
||||
QString versionText = QString(tr("%1 - build %2")).arg(VERSION_STRING).arg(VERSION_LATEST);
|
||||
splash = new SplashScreen(":images/splashscreen.png", versionText, 533, 100);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::clearSplash()
|
||||
{
|
||||
progress = NULL;
|
||||
splash->close();
|
||||
delete splash;
|
||||
splash = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1390,6 +1368,15 @@ MainWindow::selectTrends()
|
||||
setToolButtons();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MainWindow::isStarting
|
||||
() const
|
||||
{
|
||||
return splash != nullptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::setToolButtons()
|
||||
{
|
||||
@@ -2645,6 +2632,18 @@ MainWindow::actionClicked(int index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::loadProgress
|
||||
(QString folder, double progress)
|
||||
{
|
||||
Q_UNUSED(folder)
|
||||
if (splash) {
|
||||
splash->showMessage(QString(tr("Loading activities: %1\%")).arg(static_cast<int>(progress)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::addIntervals()
|
||||
{
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include "CloudDBTelemetry.h"
|
||||
#endif
|
||||
|
||||
#include "SplashScreen.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// What versions are supported by this SDK?
|
||||
#include <AvailabilityMacros.h>
|
||||
@@ -89,10 +91,6 @@ class MainWindow : public QMainWindow
|
||||
void byebye() { close(); } // go bye bye for a restart
|
||||
bool init; // if constructor has completed set to true
|
||||
|
||||
// when loading athlete
|
||||
QLabel *progress;
|
||||
int loading;
|
||||
|
||||
// currently selected tab
|
||||
AthleteTab *athleteTab() { return currentAthleteTab; }
|
||||
NewSideBar *newSidebar() { return sidebar; }
|
||||
@@ -103,6 +101,8 @@ class MainWindow : public QMainWindow
|
||||
// switch perspective
|
||||
void switchPerspective(int index);
|
||||
|
||||
bool isStarting() const;
|
||||
|
||||
protected:
|
||||
|
||||
// used by ChooseCyclistDialog to see which athletes
|
||||
@@ -121,8 +121,8 @@ class MainWindow : public QMainWindow
|
||||
virtual void dropEvent(QDropEvent *);
|
||||
|
||||
// working with splash screens
|
||||
QWidget *splash;
|
||||
void setSplash(bool first=false);
|
||||
SplashScreen *splash;
|
||||
void setSplash();
|
||||
void clearSplash();
|
||||
|
||||
signals:
|
||||
@@ -133,7 +133,6 @@ class MainWindow : public QMainWindow
|
||||
void deletedAthlete(QString);
|
||||
|
||||
public slots:
|
||||
|
||||
bool eventFilter(QObject*,QEvent*);
|
||||
|
||||
// GUI
|
||||
@@ -145,6 +144,9 @@ class MainWindow : public QMainWindow
|
||||
void support();
|
||||
void actionClicked(int);
|
||||
|
||||
void loadProgress(QString folder, double progress);
|
||||
|
||||
|
||||
// perspective selected
|
||||
void perspectiveSelected(int index);
|
||||
void perspectivesChanged(); // when the list of perspectives is updated in PerspectivesDialog
|
||||
@@ -298,6 +300,7 @@ class MainWindow : public QMainWindow
|
||||
|
||||
private:
|
||||
|
||||
// when loading athlete
|
||||
NewSideBar *sidebar;
|
||||
AthleteView *athleteView;
|
||||
|
||||
|
||||
86
src/Gui/SplashScreen.cpp
Normal file
86
src/Gui/SplashScreen.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Joachim Kohlhammer (joachim.kohlhammer@gmx.de)
|
||||
*
|
||||
* 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 "SplashScreen.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
|
||||
|
||||
SplashScreen::SplashScreen
|
||||
(const QString &pixmapPath, const QString &version, int versionX, int versionY)
|
||||
: QSplashScreen()
|
||||
{
|
||||
QPixmap pixmap(pixmapPath);
|
||||
QScreen *screen = QApplication::primaryScreen();
|
||||
if (screen->geometry().width() <= 1280) {
|
||||
// Scale pixmap for lower screen resolutions
|
||||
int targetPixmapWidth = 420;
|
||||
if (screen->geometry().width() < 1024) {
|
||||
targetPixmapWidth = 320;
|
||||
}
|
||||
int origPixmapWidth = pixmap.rect().width();
|
||||
int origPixmapHeight = pixmap.rect().height();
|
||||
pixmap = pixmap.scaledToWidth(targetPixmapWidth, Qt::SmoothTransformation);
|
||||
int newPixmapWidth = pixmap.rect().width();
|
||||
int newPixmapHeight = pixmap.rect().height();
|
||||
versionX *= newPixmapWidth / static_cast<double>(origPixmapWidth);
|
||||
versionY *= newPixmapHeight / static_cast<double>(origPixmapHeight);
|
||||
}
|
||||
QPainter painter(&pixmap);
|
||||
if (version.size() > 0) {
|
||||
QFont f = font();
|
||||
f.setPointSize(16);
|
||||
painter.setFont(f);
|
||||
QFontMetrics fm(f);
|
||||
QRect versionRect = fm.boundingRect(version);
|
||||
painter.drawText(versionX - versionRect.width(), versionY + versionRect.height(), version);
|
||||
}
|
||||
setPixmap(pixmap);
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
SplashScreen::~SplashScreen
|
||||
()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplashScreen::showMessage
|
||||
(const QString &msg)
|
||||
{
|
||||
QSplashScreen::showMessage(msg);
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SplashScreen::clearMessage
|
||||
()
|
||||
{
|
||||
QSplashScreen::clearMessage();
|
||||
QApplication::processEvents();
|
||||
}
|
||||
38
src/Gui/SplashScreen.h
Normal file
38
src/Gui/SplashScreen.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Joachim Kohlhammer (joachim.kohlhammer@gmx.de)
|
||||
*
|
||||
* 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 SPLASHSCREEN_H
|
||||
#define SPLASHSCREEN_H
|
||||
|
||||
#include <QSplashScreen>
|
||||
|
||||
|
||||
class SplashScreen : public QSplashScreen
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SplashScreen(const QString &pixmapPath, const QString &version, int versionX, int versionY);
|
||||
virtual ~SplashScreen();
|
||||
|
||||
public slots:
|
||||
void showMessage(const QString &msg);
|
||||
void clearMessage();
|
||||
};
|
||||
|
||||
#endif
|
||||
150
src/Resources/images-src/splashscreen.svg
Normal file
150
src/Resources/images-src/splashscreen.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 261 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 81 KiB |
@@ -665,7 +665,7 @@ HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/C
|
||||
Gui/Views.h Gui/BatchProcessingDialog.h Gui/DownloadRideDialog.h Gui/ManualRideDialog.h Gui/NewSideBar.h \
|
||||
Gui/MergeActivityWizard.h Gui/RideImportWizard.h Gui/SplitActivityWizard.h Gui/SolverDisplay.h Gui/MetricSelect.h \
|
||||
Gui/AddTileWizard.h Gui/NavigationModel.h Gui/AthleteView.h Gui/AthleteConfigDialog.h Gui/AthletePages.h Gui/Perspective.h \
|
||||
Gui/PerspectiveDialog.h
|
||||
Gui/PerspectiveDialog.h Gui/SplashScreen.h
|
||||
|
||||
# metrics and models
|
||||
HEADERS += Metrics/Banister.h Metrics/CPSolver.h Metrics/Estimator.h Metrics/ExtendedCriticalPower.h Metrics/HrZones.h Metrics/PaceZones.h \
|
||||
@@ -766,7 +766,7 @@ SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.cpp
|
||||
Gui/BatchProcessingDialog.cpp Gui/DownloadRideDialog.cpp Gui/ManualRideDialog.cpp Gui/EditUserMetricDialog.cpp Gui/NewSideBar.cpp \
|
||||
Gui/MergeActivityWizard.cpp Gui/RideImportWizard.cpp Gui/SplitActivityWizard.cpp Gui/SolverDisplay.cpp Gui/MetricSelect.cpp \
|
||||
Gui/AddTileWizard.cpp Gui/NavigationModel.cpp Gui/AthleteView.cpp Gui/AthleteConfigDialog.cpp Gui/AthletePages.cpp Gui/Perspective.cpp \
|
||||
Gui/PerspectiveDialog.cpp
|
||||
Gui/PerspectiveDialog.cpp Gui/SplashScreen.cpp
|
||||
|
||||
## Models and Metrics
|
||||
SOURCES += Metrics/aBikeScore.cpp Metrics/aCoggan.cpp Metrics/AerobicDecoupling.cpp Metrics/Banister.cpp Metrics/BasicRideMetrics.cpp \
|
||||
|
||||
Reference in New Issue
Block a user