mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Autoimport Stealth/Background Mode
... new Feature to Autoimport without Dialog (with same timeframe option like the Dialog version)
... in case "Dates/Time" is missing - the Dialog Window appears and waits for input -
if entered and "Save" presses no further input action is required
... malformed activity files are silently ignored
... to avoid inconsistencies closing of the Athlete for which Background Import is running
is blocked until the Import is finalized (Info on import complete is sent to UI)
.. UI is not blocked by Autoimport - but a bit less reactive as long as the import is executed
This commit is contained in:
@@ -121,8 +121,9 @@ Athlete::Athlete(Context *context, const QDir &homeDir)
|
||||
}
|
||||
}
|
||||
|
||||
// read athlete's autoimport configuration
|
||||
// read athlete's autoimport configuration and initialize the autoimport process
|
||||
autoImportConfig = new RideAutoImportConfig(home->config());
|
||||
autoImport = NULL;
|
||||
|
||||
// read athlete's charts.xml and translate etc
|
||||
loadCharts();
|
||||
@@ -230,6 +231,9 @@ Athlete::~Athlete()
|
||||
delete zones_;
|
||||
delete hrzones_;
|
||||
for (int i=0; i<2; i++) delete pacezones_[i];
|
||||
delete autoImportConfig;
|
||||
delete autoImport;
|
||||
|
||||
}
|
||||
|
||||
void Athlete::selectRideFile(QString fileName)
|
||||
@@ -343,16 +347,15 @@ Athlete::configChanged(qint32 state)
|
||||
void
|
||||
Athlete::importFilesWhenOpeningAthlete() {
|
||||
|
||||
autoImport = NULL;
|
||||
// just do it if something is configured
|
||||
if (autoImportConfig->hasRules()) {
|
||||
|
||||
RideImportWizard *import = new RideImportWizard(autoImportConfig, context);
|
||||
autoImport = new RideImportWizard(autoImportConfig, context);
|
||||
|
||||
// only process the popup if we have any files available at all
|
||||
if ( import->getNumberOfFiles() > 0) {
|
||||
import->process();
|
||||
} else {
|
||||
delete import;
|
||||
if ( autoImport->getNumberOfFiles() > 0) {
|
||||
autoImport->process();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ class PMCData;
|
||||
class LTMSettings;
|
||||
class Routes;
|
||||
class AthleteDirectoryStructure;
|
||||
class RideImportWizard;
|
||||
class RideAutoImportConfig;
|
||||
class RideCache;
|
||||
class IntervalCache;
|
||||
@@ -118,7 +119,8 @@ class Athlete : public QObject
|
||||
CalDAV *davCalendar;
|
||||
#endif
|
||||
|
||||
// Athlete's autoimport configuration
|
||||
// Athlete's autoimport handling
|
||||
RideImportWizard *autoImport;
|
||||
RideAutoImportConfig *autoImportConfig;
|
||||
|
||||
// ride metadata definitions
|
||||
|
||||
@@ -1015,20 +1015,32 @@ MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
QList<Tab*> closing = tabList;
|
||||
bool needtosave = false;
|
||||
bool importrunning = false;
|
||||
|
||||
// close all the tabs .. if any refuse we need to ignore
|
||||
// the close event
|
||||
foreach(Tab *tab, closing) {
|
||||
|
||||
// do we need to save?
|
||||
if (tab->context->mainWindow->saveRideExitDialog(tab->context) == true)
|
||||
removeTab(tab);
|
||||
else
|
||||
needtosave = true;
|
||||
// check for if RideImport is is process and let it finalize / or be stopped by the user
|
||||
if (tab->context->athlete->autoImport) {
|
||||
if (tab->context->athlete->autoImport->importInProcess() ) {
|
||||
importrunning = true;
|
||||
QMessageBox::information(this, tr("Activity Import"), tr("Closing of athlete window not possible while background activity import is in progress..."));
|
||||
}
|
||||
}
|
||||
|
||||
// only check for unsaved if autoimport is not running any more
|
||||
if (!importrunning) {
|
||||
// do we need to save?
|
||||
if (tab->context->mainWindow->saveRideExitDialog(tab->context) == true)
|
||||
removeTab(tab);
|
||||
else
|
||||
needtosave = true;
|
||||
}
|
||||
}
|
||||
|
||||
// were any left hanging around?
|
||||
if (needtosave) event->ignore();
|
||||
// were any left hanging around? or autoimport in action on any windows, then don't close any
|
||||
if (needtosave || importrunning) event->ignore();
|
||||
else {
|
||||
|
||||
// finish off the job and leave
|
||||
@@ -1631,7 +1643,17 @@ MainWindow::openTab(QString name)
|
||||
void
|
||||
MainWindow::closeTabClicked(int index)
|
||||
{
|
||||
|
||||
Tab *tab = tabList[index];
|
||||
|
||||
// check for autoimport and let it finalize
|
||||
if (tab->context->athlete->autoImport) {
|
||||
if (tab->context->athlete->autoImport->importInProcess() ) {
|
||||
QMessageBox::information(this, tr("Activity Import"), tr("Closing of athlete window not possible while background activity import is in progress..."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (saveRideExitDialog(tab->context) == false) return;
|
||||
|
||||
// lets wipe it
|
||||
@@ -1641,6 +1663,14 @@ MainWindow::closeTabClicked(int index)
|
||||
bool
|
||||
MainWindow::closeTab()
|
||||
{
|
||||
// check for autoimport and let it finalize
|
||||
if (currentTab->context->athlete->autoImport) {
|
||||
if (currentTab->context->athlete->autoImport->importInProcess() ) {
|
||||
QMessageBox::information(this, tr("Activity Import"), tr("Closing of athlete window not possible while background activity import is in progress..."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// wipe it down ...
|
||||
if (saveRideExitDialog(currentTab->context) == false) return false;
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ RideAutoImportRule::RideAutoImportRule() {
|
||||
_ruleDescriptions.append(tr("Autoimport with dialog - past 90 days"));
|
||||
_ruleDescriptions.append(tr("Autoimport with dialog - past 180 days"));
|
||||
_ruleDescriptions.append(tr("Autoimport with dialog - past 360 days"));
|
||||
_ruleDescriptions.append(tr("Autoimport in background"));
|
||||
_ruleDescriptions.append(tr("Autoimport in background - past 90 days"));
|
||||
_ruleDescriptions.append(tr("Autoimport in background - past 180 days"));
|
||||
_ruleDescriptions.append(tr("Autoimport in background - past 360 days"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ class RideAutoImportRule {
|
||||
|
||||
public:
|
||||
static QList<QString> rules;
|
||||
enum ImportRule { noImport=0, importAll=1, importLast90days=2, importLast180days=3, importLast360days=4 };
|
||||
enum ImportRule { noImport=0, importAll=1, importLast90days=2, importLast180days=3, importLast360days=4,
|
||||
importBackgroundAll=5, importBackground90=6, importBackground180=7, importBackground360=8 };
|
||||
|
||||
RideAutoImportRule();
|
||||
|
||||
|
||||
@@ -41,29 +41,42 @@
|
||||
// drag and drop passes urls ... convert to a list of files and call main constructor
|
||||
RideImportWizard::RideImportWizard(QList<QUrl> *urls, Context *context, QWidget *parent) : QDialog(parent), context(context)
|
||||
{
|
||||
_importInProcess = true;
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
QList<QString> filenames;
|
||||
for (int i=0; i<urls->count(); i++)
|
||||
filenames.append(QFileInfo(urls->value(i).toLocalFile()).absoluteFilePath());
|
||||
autoImportMode = false;
|
||||
autoImportStealth = false;
|
||||
init(filenames, context);
|
||||
filenames.clear();
|
||||
_importInProcess = false;
|
||||
|
||||
}
|
||||
|
||||
RideImportWizard::RideImportWizard(QList<QString> files, Context *context, QWidget *parent) : QDialog(parent), context(context)
|
||||
{
|
||||
_importInProcess = true;
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
autoImportMode = false;
|
||||
autoImportStealth = false;
|
||||
init(files, context);
|
||||
_importInProcess = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
RideImportWizard::RideImportWizard(RideAutoImportConfig *dirs, Context *context, QWidget *parent) : QDialog(parent), context(context), importConfig(dirs)
|
||||
{
|
||||
_importInProcess = true;
|
||||
autoImportMode = true;
|
||||
autoImportStealth = true;
|
||||
|
||||
if (autoImportStealth) hide();
|
||||
QList<QString> files;
|
||||
|
||||
// get the directories
|
||||
// get the directories & rules
|
||||
QList<RideAutoImportRule> rules = importConfig->getConfig();
|
||||
|
||||
// prepare the widget to show the status of the directory
|
||||
@@ -142,16 +155,30 @@ RideImportWizard::RideImportWizard(RideAutoImportConfig *dirs, Context *context,
|
||||
QDate selectAfter = QDate::currentDate();
|
||||
switch(rule.getImportRule()) {
|
||||
case RideAutoImportRule::importLast90days:
|
||||
case RideAutoImportRule::importBackground90:
|
||||
selectAfter = selectAfter.addDays(Q_INT64_C(-90));
|
||||
break;
|
||||
case RideAutoImportRule::importLast180days:
|
||||
case RideAutoImportRule::importBackground180:
|
||||
selectAfter = selectAfter.addDays(Q_INT64_C(-180));
|
||||
break;
|
||||
case RideAutoImportRule::importLast360days:
|
||||
case RideAutoImportRule::importBackground360:
|
||||
selectAfter = selectAfter.addDays(Q_INT64_C(-360));
|
||||
break;
|
||||
}
|
||||
|
||||
// if any of the rules says "with Dialog" then we keep the dialog - if not it's stealth
|
||||
switch (rule.getImportRule()) {
|
||||
|
||||
case RideAutoImportRule::importAll:
|
||||
case RideAutoImportRule::importLast90days:
|
||||
case RideAutoImportRule::importLast180days:
|
||||
case RideAutoImportRule::importLast360days:
|
||||
autoImportStealth = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// now get the files with their full names
|
||||
QFileInfoList fileInfos = importDir->entryInfoList(allFormats, QDir::Files, QDir::NoSort);
|
||||
if (!fileInfos.isEmpty()) {
|
||||
@@ -160,12 +187,16 @@ RideImportWizard::RideImportWizard(RideAutoImportConfig *dirs, Context *context,
|
||||
// append following the import rules
|
||||
switch (rule.getImportRule()) {
|
||||
case RideAutoImportRule::importAll:
|
||||
case RideAutoImportRule::importBackgroundAll:
|
||||
files.append(f.absoluteFilePath());
|
||||
j++;
|
||||
break;
|
||||
case RideAutoImportRule::importLast90days:
|
||||
case RideAutoImportRule::importLast180days:
|
||||
case RideAutoImportRule::importLast360days:
|
||||
case RideAutoImportRule::importBackground90:
|
||||
case RideAutoImportRule::importBackground180:
|
||||
case RideAutoImportRule::importBackground360:
|
||||
if (f.created().date() >= selectAfter || f.lastModified().date() >= selectAfter) {
|
||||
files.append(f.absoluteFilePath());
|
||||
j++;
|
||||
@@ -190,6 +221,9 @@ RideImportWizard::RideImportWizard(RideAutoImportConfig *dirs, Context *context,
|
||||
|
||||
init(files, context);
|
||||
|
||||
_importInProcess = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -379,9 +413,14 @@ int
|
||||
RideImportWizard::process()
|
||||
{
|
||||
|
||||
// import process is starting
|
||||
_importInProcess = true;
|
||||
|
||||
// Make visible and put in front prior to running down the list & processing...
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
this->show();
|
||||
if (!autoImportStealth) {
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
this->show();
|
||||
}
|
||||
|
||||
// set progress bar limits - for each file we
|
||||
// will make 5 passes over the files
|
||||
@@ -427,7 +466,7 @@ RideImportWizard::process()
|
||||
|
||||
}
|
||||
|
||||
if (aborted) { done(0); }
|
||||
if (aborted) { done(0); return 0; }
|
||||
repaint();
|
||||
QApplication::processEvents();
|
||||
|
||||
@@ -447,7 +486,7 @@ RideImportWizard::process()
|
||||
tableWidget->setCurrentCell(i,5);
|
||||
QApplication::processEvents();
|
||||
|
||||
if (aborted) { done(0); }
|
||||
if (aborted) { done(0); return 0; }
|
||||
this->repaint();
|
||||
QApplication::processEvents();
|
||||
|
||||
@@ -611,7 +650,7 @@ RideImportWizard::process()
|
||||
}
|
||||
progressBar->setValue(progressBar->value()+1);
|
||||
QApplication::processEvents();
|
||||
if (aborted) { done(0); }
|
||||
if (aborted) { done(0); return 0; }
|
||||
this->repaint();
|
||||
|
||||
next:;
|
||||
@@ -637,8 +676,13 @@ RideImportWizard::process()
|
||||
progressBar->repaint();
|
||||
}
|
||||
// get it on top to save / correct missing dates
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
|
||||
if (autoImportStealth && needdates > 0) {
|
||||
// leave the stealth mode
|
||||
this->show();
|
||||
activateWindow();
|
||||
} else {
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
}
|
||||
// Wait for user to press save
|
||||
abortButton->setText(tr("Save"));
|
||||
aborted = false;
|
||||
@@ -656,8 +700,8 @@ RideImportWizard::process()
|
||||
// without user intervention
|
||||
|
||||
abortButton->setDisabled(false);
|
||||
if (autoImportStealth) abortClicked(); // simulate "Save" by User
|
||||
|
||||
// abortClicked();
|
||||
} else {
|
||||
|
||||
// de-activate Save button until the dates and times are sorted
|
||||
@@ -856,6 +900,10 @@ RideImportWizard::abortClicked()
|
||||
if (label == tr("Finish")) {
|
||||
// phew. our work is done. -- lets force an update stats...
|
||||
hide();
|
||||
if (autoImportStealth) {
|
||||
// inform the user that the work is done
|
||||
QMessageBox::information(NULL, tr("Auto Import"), tr("Automatic import from defined directories is completed."));
|
||||
}
|
||||
done(0);
|
||||
return;
|
||||
}
|
||||
@@ -914,7 +962,7 @@ RideImportWizard::abortClicked()
|
||||
tableWidget->item(i,5)->setText(tr("Saving..."));
|
||||
tableWidget->setCurrentCell(i,5);
|
||||
QApplication::processEvents();
|
||||
if (aborted) { done(0); }
|
||||
if (aborted) { done(0); return; }
|
||||
this->repaint();
|
||||
|
||||
|
||||
@@ -1021,7 +1069,7 @@ RideImportWizard::abortClicked()
|
||||
delete ride;
|
||||
|
||||
QApplication::processEvents();
|
||||
if (aborted) { done(0); }
|
||||
if (aborted) { done(0); return; }
|
||||
progressBar->setValue(progressBar->value()+1);
|
||||
this->repaint();
|
||||
}
|
||||
@@ -1040,8 +1088,12 @@ RideImportWizard::abortClicked()
|
||||
progressBar->setValue(progressBar->maximum());
|
||||
phaseLabel->setText(donemessage);
|
||||
abortButton->setText(tr("Finish"));
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
aborted = false;
|
||||
if (autoImportStealth) {
|
||||
abortClicked(); // simulate pressing the "Finish" button - even if the window got visible
|
||||
} else {
|
||||
if (!isActiveWindow()) activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1068,6 +1120,23 @@ RideImportWizard::moveFile(const QString &source, const QString &target) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RideImportWizard::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
if (_importInProcess)
|
||||
event->ignore();
|
||||
else
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void
|
||||
RideImportWizard::done(int rc)
|
||||
{
|
||||
_importInProcess = false;
|
||||
QDialog::done(rc);
|
||||
}
|
||||
|
||||
// clean up files
|
||||
RideImportWizard::~RideImportWizard()
|
||||
{
|
||||
|
||||
@@ -48,10 +48,13 @@ public:
|
||||
RideImportWizard(RideAutoImportConfig *dirs, Context *context, QWidget *parent = 0);
|
||||
|
||||
~RideImportWizard();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void done(int);
|
||||
|
||||
int getNumberOfFiles(); // get the number of files selected for processing
|
||||
int process();
|
||||
|
||||
signals:
|
||||
bool importInProcess() { return _importInProcess; }
|
||||
bool isAutoImport() { return autoImportMode;}
|
||||
|
||||
private slots:
|
||||
void abortClicked();
|
||||
@@ -72,6 +75,8 @@ private:
|
||||
QDir tmpActivities; // activitiy .JSON is stored here until rideCache() update was successfull
|
||||
bool aborted;
|
||||
bool autoImportMode;
|
||||
bool autoImportStealth;
|
||||
bool _importInProcess;
|
||||
QLabel *phaseLabel;
|
||||
QTableWidget *tableWidget;
|
||||
QTableWidget *directoryWidget;
|
||||
|
||||
Reference in New Issue
Block a user