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:
Joern
2015-10-25 13:04:19 +01:00
parent e7e6e0bd70
commit a6eabb73d7
7 changed files with 143 additions and 29 deletions

View File

@@ -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();
}
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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"));
}

View File

@@ -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();

View File

@@ -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()
{

View File

@@ -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;