From: hama Date: Wed, 24 Feb 2016 15:31:53 +0000 (+0100) Subject: rebackgui: refactoring, autosave X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=16e3e3fb84604712f449cd9ab66581bccf1d76f7;p=reqt rebackgui: refactoring, autosave * configuration: automatic update and selectable saving * file copy criteria: filetime differs more than 2 sec (older or newer) --- diff --git a/appl/rebackgui/BackupEngine.cpp b/appl/rebackgui/BackupEngine.cpp index a238b86..9e9a138 100644 --- a/appl/rebackgui/BackupEngine.cpp +++ b/appl/rebackgui/BackupEngine.cpp @@ -151,11 +151,11 @@ void BackupTask::copyFile(int index, const QString& relPath, if (! ReFileUtils::isDirectory(targetDir, &isFile)){ if (isFile){ if (_unlink(I18N::s2b(targetDir).constData()) != 0) - error(QObject::tr("cannot remove file (for making a directory (%1): %2") + error(QObject::tr("cannot remove file (for making a directory (%1): %2") .arg(errno).arg(targetDir)); } if (! ReFileUtils::makeDirWithParents(targetDir)) - error(QObject::tr("cannot make directory (%1): %2").arg(errno).arg(targetDir)); + error(QObject::tr("cannot make directory (%1): %2").arg(errno).arg(targetDir)); } QFileInfo info(source); if (m_verboseLevel >= VerboseStandard) @@ -184,8 +184,8 @@ void BackupTask::run() QString relPath, node; QString info; QDateTime start = QDateTime::currentDateTime(); - int hotFiles, processedFiles; - qint64 processedBytes, hotBytes; + int hotFiles, processedFiles; + qint64 processedBytes, hotBytes; while (! m_shouldStop){ m_mutex.lock(); if (m_files.size() == 0) @@ -194,10 +194,10 @@ void BackupTask::run() info = m_files.first(); m_files.removeFirst(); } - hotBytes = m_hotBytes; - processedBytes = m_processedBytes; - hotFiles = m_hotFiles; - processedFiles = m_processedFiles; + hotBytes = m_hotBytes; + processedBytes = m_processedBytes; + hotFiles = m_hotFiles; + processedFiles = m_processedFiles; m_mutex.unlock(); if (info.isEmpty()){ if (m_searchReady) @@ -215,20 +215,20 @@ void BackupTask::run() copyFile(index, relPath, node); if (m_verboseLevel > VerboseQuiet){ qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.toMSecsSinceEpoch(); - double factor = processedBytes / max(1.0, (double) hotBytes); - if (factor > 1.0) - factor = 1; + double factor = processedBytes / max(1.0, (double) hotBytes); + if (factor > 1.0) + factor = 1; m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL, - QObject::tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6") - .arg(processedFiles).arg(hotFiles) - .arg(ReQStringUtils::readableSize(processedBytes)) - .arg(ReQStringUtils::readableSize(hotBytes)) - .arg(processedBytes / 1024.0 / 1024 * 1000 / max(1LL, duration), 0, 'f', 3) + QObject::tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6") + .arg(processedFiles).arg(hotFiles) + .arg(ReQStringUtils::readableSize(processedBytes)) + .arg(ReQStringUtils::readableSize(hotBytes)) + .arg(processedBytes / 1024.0 / 1024 * 1000 / max(1LL, duration), 0, 'f', 3) .arg(ReQStringUtils::runtimeEstimation(start, factor))); } } } - m_mainWindow->externalTaskFinished(QObject::tr("backup complete after %1. Errors: %2") + m_mainWindow->externalTaskFinished(QObject::tr("backup complete after %1. Errors: %2") .arg(ReQStringUtils::readableDuration( QDateTime::currentMSecsSinceEpoch() - start.toMSecsSinceEpoch())) .arg(m_mainWindow->errors())); @@ -344,7 +344,7 @@ void ChecksumOfSourceTask::run() } m_sourceProcessingReady = true; qint64 now = QDateTime::currentMSecsSinceEpoch(); - m_mainWindow->externalTaskFinished(QObject::tr("Building source checksum complete after %1. Processed: %2") + m_mainWindow->externalTaskFinished(QObject::tr("Building source checksum complete after %1. Processed: %2") .arg(ReQStringUtils::readableDuration(now - start)) .arg(count)); } @@ -418,11 +418,11 @@ void ChecksumOfTargetTask::run() m_mutex.unlock(); now = QDateTime::currentMSecsSinceEpoch(); qint64 duration = (now - start.toMSecsSinceEpoch()); - double factor = processedBytes / max(1.0, (double) hotBytes); - if (factor > 1) - factor = 1; + double factor = processedBytes / max(1.0, (double) hotBytes); + if (factor > 1) + factor = 1; m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL, - QObject::tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6") + QObject::tr("%1 of %2 (%3 of %4) %5 MB/sec runtime: %6") .arg(processedFiles).arg(hotFiles * 2) .arg(ReQStringUtils::readableSize(processedBytes)) .arg(ReQStringUtils::readableSize(hotBytes)) @@ -433,7 +433,7 @@ void ChecksumOfTargetTask::run() } } now = QDateTime::currentMSecsSinceEpoch(); - m_mainWindow->externalTaskFinished(QObject::tr("Building target checksums complete after %1. Processed: %2 Errors: %3") + m_mainWindow->externalTaskFinished(QObject::tr("Building target checksums complete after %1. Processed: %2 Errors: %3") .arg(ReQStringUtils::readableDuration(now - start.toMSecsSinceEpoch())) .arg(count) .arg(m_mainWindow->errors())); @@ -495,7 +495,7 @@ void CleanTask::run() node = info.mid(pos + 2); switch(command){ case CmdRemove: - if (_unlink(I18N::s2b(relPath)) != 0){ + if (_unlink(I18N::s2b(relPath)) != 0){ int errNo = errno; if (stat(I18N::s2b(relPath), &info2) == 0) error(QObject::tr("cannot delete (%1): %2").arg(errNo) @@ -526,7 +526,7 @@ void CleanTask::run() QByteArray shadow2 = I18N::s2b(shadow); struct stat info; if (stat(shadow2.constData(), &info) == 0){ - if (_unlink(shadow2.constData()) != 0){ + if (_unlink(shadow2.constData()) != 0){ error(QObject::tr("cannot delete shadow file (%1): %2").arg(errno).arg(shadow)); } } @@ -545,7 +545,7 @@ void CleanTask::run() double factor = double(processedFiles) / max(1, hotFiles); qint64 duration = QDateTime::currentMSecsSinceEpoch() - start.toMSecsSinceEpoch(); m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL, - QObject::tr("%1 of %2 files %3 files/sec runtime: %6") + QObject::tr("%1 of %2 files %3 files/sec runtime: %6") .arg(processedFiles) .arg(hotFiles) .arg(processedFiles * 1000.0 / max(1.0, (double) duration), 0, 'f', 3) @@ -553,7 +553,7 @@ void CleanTask::run() } } } - m_mainWindow->externalTaskFinished(QObject::tr("clean complete after %1. Errors: %2") + m_mainWindow->externalTaskFinished(QObject::tr("clean complete after %1. Errors: %2") .arg(ReQStringUtils::readableDuration( QDateTime::currentMSecsSinceEpoch() - start.toMSecsSinceEpoch())) .arg(m_mainWindow->errors())); @@ -599,7 +599,7 @@ void SearchTask::run() searchOneDirectory(sourceDir, targetDir, ix); } m_searchReady = true; - m_mainWindow->externalLog(QObject::tr( + m_mainWindow->externalLog(QObject::tr( "Search finished: to process: %1 with %2 matching: %3 total: %4 " "subdirs: %5 runtime: %6") .arg(m_hotFiles) @@ -666,15 +666,15 @@ void SearchTask::searchOneDirectory(const QString& source, const QFileInfo src = it.fileInfo(); if (trg.size() != src.size()) doTransfer = true; - else if ((diff = src.lastModified().toMSecsSinceEpoch() - - trg.lastModified().toMSecsSinceEpoch()) > 2000) + else if ((diff = abs(src.lastModified().toMSecsSinceEpoch() + - trg.lastModified().toMSecsSinceEpoch())) >= 2000) doTransfer = true; } } if (doTransfer){ info = prefix + it.fileName(); } - m_mutex.lock(); + m_mutex.lock(); if (doTransfer){ m_files.append(info); m_hotFiles++; @@ -706,7 +706,7 @@ void SearchTask::searchOneDirectory(const QString& source, else subTarget += OS_SEPARATOR_STR; } - searchOneDirectory(ReFileUtils::nativePath(it2.filePath()), subTarget, index); + searchOneDirectory(ReFileUtils::nativePath(it2.filePath()), subTarget, index); } } } @@ -755,15 +755,15 @@ bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& ti node = it.fileName(); if (it.fileInfo().isDir()){ if (node != "." && node != ".."){ - if (! removeOlder(ReFileUtils::nativePath(it.filePath()), time)) + if (! removeOlder(ReFileUtils::nativePath(it.filePath()), time)) isEmpty = false; } } else if (it.fileInfo().lastModified() < time){ if (m_verboseLevel >= VerboseChatty) - m_mainWindow->addToFileList("% " + ReFileUtils::nativePath(it.filePath()) + " " + m_mainWindow->addToFileList("% " + ReFileUtils::nativePath(it.filePath()) + " " + it.fileInfo().lastModified().toString("yyyy.MM.dd/hh:mm:ss")); isEmpty = false; - info = QChar(MAX_INDEX) + ReFileUtils::nativePath(it.filePath()) + m_separatorString + info = QChar(MAX_INDEX) + ReFileUtils::nativePath(it.filePath()) + m_separatorString + QChar(CmdRemove); m_mutex.lock(); m_files.append(info); @@ -771,16 +771,16 @@ bool SearchTargetTask::removeOlder(const QString& directory, const QDateTime& ti m_hotBytes += it.fileInfo().size(); m_totalFiles++; m_mutex.unlock(); - }else { - isEmpty = false; - } - } + }else { + isEmpty = false; + } + } if (isEmpty){ if (m_verboseLevel >= VerboseChatty) m_mainWindow->addToFileList("x " + directory); info = QChar(MAX_INDEX) + directory + m_separatorString + QChar(CmdRemoveDir); - m_mutex.lock(); + m_mutex.lock(); m_files.append(info); m_matchedFiles++; m_hotFiles++; @@ -808,9 +808,9 @@ void SearchTargetTask::searchOneDirectory(const QString& target, m_mutex.lock(); m_totalDirs++; m_mutex.unlock(); - if (target.length() > lengthBase){ - relPath = ReFileUtils::nativePath(target.mid(lengthBase)) + OS_SEPARATOR_STR; - prefix = QChar(1 + index) + relPath + m_separator; + if (target.length() > lengthBase){ + relPath = ReFileUtils::nativePath(target.mid(lengthBase)) + OS_SEPARATOR_STR; + prefix = QChar(1 + index) + relPath + m_separator; } else { prefix = QChar(1 + index) + m_separatorString; } @@ -833,14 +833,14 @@ void SearchTargetTask::searchOneDirectory(const QString& target, QDateTime trgTime = trg.lastModified(); if (trgTime < m_maxAge){ command = CmdRemove; - info = QChar(1 + index) + ReFileUtils::nativePath(it.filePath()) - + "\t" + QChar(command); + info = QChar(1 + index) + ReFileUtils::nativePath(it.filePath()) + + "\t" + QChar(command); } else { command = CmdMove; info = prefix + QChar(command) + it.fileName(); } } - m_mutex.lock(); + m_mutex.lock(); if (command != CmdUndef){ m_files.append(info); m_hotFiles++; @@ -863,10 +863,10 @@ void SearchTargetTask::searchOneDirectory(const QString& target, QString newSource = source + it2.fileName(); QFileInfo src(newSource); if (src.exists() && src.isDir()) - searchOneDirectory(ReFileUtils::nativePath(it2.filePath()), - newSource + OS_SEPARATOR_STR, index); + searchOneDirectory(ReFileUtils::nativePath(it2.filePath()), + newSource + OS_SEPARATOR_STR, index); else{ - moveToShadow(ReFileUtils::nativePath(it2.filePath()), relPath, index); + moveToShadow(ReFileUtils::nativePath(it2.filePath()), relPath, index); } } } @@ -882,12 +882,12 @@ void SearchTargetTask::searchOneDirectory(const QString& target, */ void SearchTargetTask::moveToShadow(const QString& target, const QString& relPath, int index){ QString shadowDir = m_shadowDirs.at(index) + relPath; - ReQStringUtils::chomp(shadowDir, OS_SEPARATOR); - if (! ReFileUtils::makeDirWithParents(shadowDir)){ + ReQStringUtils::chomp(shadowDir, OS_SEPARATOR); + if (! ReFileUtils::makeDirWithParents(shadowDir)){ error(QObject::tr("cannot create shadow directory (%1): %2") .arg(errno).arg(shadowDir)); - } else { + } else { QString shadow = shadowDir + ReFileUtils::nodeOf(target); if (rename(I18N::s2b(target).constData(), I18N::s2b(shadow).constData()) != 0){ error(QObject::tr("cannot move to shadow directory (%1): %2 -> %3") @@ -911,11 +911,11 @@ void SearchTargetTask::run() targetDir = m_targetDirs.at(ix); searchOneDirectory(targetDir, sourceDir, ix); } - if (! m_shouldStop){ + if (! m_shouldStop && ReFileUtils::isDirectory(m_shadowBaseDir)){ removeOlder(m_shadowBaseDir, m_maxAge); } m_searchReady = true; - m_mainWindow->externalLog(QObject::tr( + m_mainWindow->externalLog(QObject::tr( "Search in target finished: to process: %1 with %2 dirs to delete: %3 total: %4 " "subdirs: %5 runtime: %6") .arg(m_hotFiles) diff --git a/appl/rebackgui/Configuration.cpp b/appl/rebackgui/Configuration.cpp index e0f0c4c..d461e49 100644 --- a/appl/rebackgui/Configuration.cpp +++ b/appl/rebackgui/Configuration.cpp @@ -177,7 +177,6 @@ bool Configuration::readBackupDate(BackupItem& item){ bool rc = false; QString target = BackupUtils::findTarget(item, m_mainWindow->logger()); if (! target.isEmpty()){ - item.m_active = true; QString name = BackupUtils::nameOfTargetDescription(target); ReConfig config(I18N::s2b(name).constData()); rc = item.m_active = config.exists(); @@ -228,5 +227,7 @@ void Configuration::save(QString filename) .arg(filename)); } fclose(fp); + m_mainWindow->setStatusMessage(LOG_INFO, QObject::tr("configuration saved: %1") + .arg(filename)); } } diff --git a/appl/rebackgui/mainwindow.cpp b/appl/rebackgui/mainwindow.cpp index e9d32d5..2c4998c 100644 --- a/appl/rebackgui/mainwindow.cpp +++ b/appl/rebackgui/mainwindow.cpp @@ -13,7 +13,7 @@ #include "aboutdialog.hpp" #include -const QString VERSION("2016.02.20"); +const QString VERSION("2016.02.24"); /** * Constructor. @@ -42,63 +42,6 @@ MainWindow::MainWindow(QApplication& application, const QString& homeDir, initializeGui(); } -/** - * Initializes the Graphical User Interface. - */ -void MainWindow::initializeGui(){ - ui->setupUi(this); - initializeGuiElements(); - initializeGuiLanguage(ui->actionEnglish, ui->actionGerman); - startStop(false); - connect(ui->actionStart, SIGNAL(triggered()), this, - SLOT(onStart())); - connect(ui->actionChecksums, SIGNAL(triggered()), this, - SLOT(onChecksums())); - connect(ui->actionClean, SIGNAL(triggered()), this, - SLOT(onClean())); - connect(ui->actionStop, SIGNAL(triggered()), this, - SLOT(onStop())); - connect(ui->pushButtonBackup, SIGNAL(clicked()), this, SLOT(onStart())); - connect(ui->pushButtonChecksum, SIGNAL(clicked()), this, SLOT(onChecksums())); - connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onStop())); - connect(ui->pushButtonAddItem, SIGNAL(clicked()), this, SLOT(onAddItem())); - connect(ui->pushButtonDeleteItem, SIGNAL(clicked()), this, SLOT(onDeleteItem())); - connect(ui->pushButtonAddSource, SIGNAL(clicked()), this, SLOT(onAddSource())); - connect(ui->pushButtonDeleteSource, SIGNAL(clicked()), this, SLOT(onDeleteSource())); - connect(ui->pushButtonSelectTarget, SIGNAL(clicked()), this, SLOT(onSelectTarget())); - connect(ui->pushButtonSaveConfig, SIGNAL(clicked()), this, SLOT(onSaveConfig())); - connect(ui->pushButtonUpdate, SIGNAL(clicked()), this, SLOT(onUpdate())); - connect(ui->actionLoadConfig, SIGNAL(triggered()), this, - SLOT(onLoadConfig())); - connect(ui->actionSaveConfig, SIGNAL(triggered()), this, - SLOT(onSaveConfig())); - connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAbout())); - connect(ui->tableWidgetConfiguration->selectionModel(), - SIGNAL( selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SLOT( onSelectionChanged(const QItemSelection&, const QItemSelection&) )); - connect(ui->tableWidgetConfiguration->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - this, - SLOT(onCurrentChanged(const QModelIndex&, const QModelIndex&))); - connect(ui->pushButtonClearFileList, SIGNAL(clicked()), this, SLOT(onClearFileList())); - connect(ui->pushButtonClearErrorList, SIGNAL(clicked()), this, SLOT(onClearErrorList())); - connect(ui->pushButtonClear, SIGNAL(clicked()), this, SLOT(onClearLog())); - connect(ui->pushButtonClean, SIGNAL(clicked()), this, SLOT(onClean())); - connect(ui->comboBoxVerbose, SIGNAL(currentIndexChanged(int)), this, SLOT(onVerboseIndexChanged(int))); - //connect(m_defaultLanguage, SIGNAL(triggered()), this, - // SLOT(onDefault())); - connect(ui->actionEnglish, SIGNAL(triggered()), this, SLOT(onEnglish())); - connect(ui->actionGerman, SIGNAL(triggered()), this, SLOT(onGerman())); - m_configuration.load(""); - ui->tableWidgetConfiguration->selectRow(0); - updateTable(); - updateItem(0); - if (m_currentTranslator == NULL) - ui->actionEnglish->setChecked(true); - else - ui->actionGerman->setChecked(true); -} - /** * Destructor. */ @@ -167,11 +110,11 @@ void MainWindow::onGuiTimerUpdate() { int count = m_guiQueue.count(); QListWidget* list; - QString statusMessage; - int countStatusMessage = 0; - clock_t start = clock(); - clock_t diff; - while(count-- > 0 || (diff = clock() - start) > CLOCKS_PER_SEC){ + QString statusMessage; + int countStatusMessage = 0; + clock_t start = clock(); + clock_t diff; + while(count-- > 0 || (diff = clock() - start) > CLOCKS_PER_SEC){ m_mutexGuiQueue.lock(); ReGuiQueueItem item = m_guiQueue.popFront(); m_mutexGuiQueue.unlock(); @@ -196,12 +139,12 @@ void MainWindow::onGuiTimerUpdate() say(LOG_ERROR, item.m_value); break; case ReGuiQueueItem::StatusLine: - if (++countStatusMessage % 200 != 0) - statusMessage = item.m_value; - else { - setStatusMessage(LOG_INFO, item.m_value); - statusMessage.clear(); - } + if (++countStatusMessage % 200 != 0) + statusMessage = item.m_value; + else { + setStatusMessage(LOG_INFO, item.m_value); + statusMessage.clear(); + } break; default: say(LOG_ERROR, "unknown item type: " + QString::number(item.m_type) @@ -210,11 +153,87 @@ void MainWindow::onGuiTimerUpdate() } } } - if (!statusMessage.isEmpty()) - setStatusMessage(LOG_INFO, statusMessage); + if (!statusMessage.isEmpty()) + setStatusMessage(LOG_INFO, statusMessage); } +/** + * Initializes the Graphical User Interface. + */ +void MainWindow::initializeGui(){ + ui->setupUi(this); + initializeGuiElements(); + m_guiIsInitialized = false; + initializeGuiLanguage(ui->actionEnglish, ui->actionGerman); + startStop(false); + ui->actionAutosave->setChecked(true); + connect(ui->actionStart, SIGNAL(triggered()), this, + SLOT(onStart())); + connect(ui->actionChecksums, SIGNAL(triggered()), this, + SLOT(onChecksums())); + connect(ui->actionClean, SIGNAL(triggered()), this, + SLOT(onClean())); + connect(ui->actionStop, SIGNAL(triggered()), this, + SLOT(onStop())); + connect(ui->pushButtonBackup, SIGNAL(clicked()), this, SLOT(onStart())); + connect(ui->pushButtonChecksum, SIGNAL(clicked()), this, SLOT(onChecksums())); + connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onStop())); + connect(ui->pushButtonAddItem, SIGNAL(clicked()), this, SLOT(onAddItem())); + connect(ui->pushButtonDeleteItem, SIGNAL(clicked()), this, SLOT(onDeleteItem())); + connect(ui->pushButtonAddSource, SIGNAL(clicked()), this, SLOT(onAddSource())); + connect(ui->pushButtonDeleteSource, SIGNAL(clicked()), this, SLOT(onDeleteSource())); + connect(ui->pushButtonSelectTarget, SIGNAL(clicked()), this, SLOT(onSelectTarget())); + connect(ui->pushButtonSaveConfig, SIGNAL(clicked()), this, SLOT(onSaveConfig())); + connect(ui->actionAutosave, SIGNAL(toggled(bool)), this, SLOT(onAutosaveToggled(bool))); + connect(ui->checkBoxAutoSave, SIGNAL(stateChanged(int)), this, SLOT(onAutosaveChanged(int))); + connect(ui->actionLoadConfig, SIGNAL(triggered()), this, + SLOT(onLoadConfig())); + connect(ui->actionSaveConfig, SIGNAL(triggered()), this, + SLOT(onSaveConfig())); + connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onAbout())); + connect(ui->tableWidgetConfiguration->selectionModel(), + SIGNAL( selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT( onSelectionChanged(const QItemSelection&, const QItemSelection&) )); + connect(ui->tableWidgetConfiguration->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + this, + SLOT(onCurrentChanged(const QModelIndex&, const QModelIndex&))); + connect(ui->pushButtonClearFileList, SIGNAL(clicked()), this, SLOT(onClearFileList())); + connect(ui->pushButtonClearErrorList, SIGNAL(clicked()), this, SLOT(onClearErrorList())); + connect(ui->pushButtonClear, SIGNAL(clicked()), this, SLOT(onClearLog())); + connect(ui->pushButtonClean, SIGNAL(clicked()), this, SLOT(onClean())); + connect(ui->comboBoxVerbose, SIGNAL(currentIndexChanged(int)), this, SLOT(onVerboseIndexChanged(int))); + //connect(m_defaultLanguage, SIGNAL(triggered()), this, + // SLOT(onDefault())); + connect(ui->actionEnglish, SIGNAL(triggered()), this, SLOT(onEnglish())); + connect(ui->actionGerman, SIGNAL(triggered()), this, SLOT(onGerman())); + connect(ui->lineEditName, SIGNAL(editingFinished()), this, SLOT(onUpdateConfig())); + connect(ui->comboBoxDirPatterns, SIGNAL(editTextChanged(const QString&)), this, SLOT(onDirPatternTextChanged(const QString&))); + connect(ui->comboBoxFilePatterns, SIGNAL(editTextChanged(const QString&)), this, SLOT(onFilePatternTextChanged(const QString&))); + connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, + SLOT(onCurrentTabChanged(int))); + m_configuration.load(""); + ui->tableWidgetConfiguration->selectRow(0); + updateTable(); + updateItem(0); + if (m_currentTranslator == NULL) + ui->actionEnglish->setChecked(true); + else + ui->actionGerman->setChecked(true); + m_guiIsInitialized = true; + // Active Name Target Last Sources + ui->tableWidget->setColumnWidth(0, 50); + ui->tableWidget->setColumnWidth(1, 125); + ui->tableWidget->setColumnWidth(2, 175); + ui->tableWidget->setColumnWidth(3, 160); + + ui->tableWidgetConfiguration->setColumnWidth(0, 125); + ui->tableWidgetConfiguration->setColumnWidth(1, 175); + ui->tableWidgetConfiguration->setColumnWidth(2, 160); + ui->tableWidgetConfiguration->selectRow(0); +} + /** * Common initializations for all task starts. * @@ -233,7 +252,7 @@ bool MainWindow::initializeStart(){ BackupEngine::m_totalFiles = 0; BackupEngine::m_processedFiles = 0; BackupEngine::m_processedBytes = 0; - BackupEngine::m_files.clear(); + BackupEngine::m_files.clear(); ChecksumTask::m_sourceProcessingReady = false; if ( (m_maxListSize = comboInt(ui->comboBoxMaxListLength, -999)) == -999){ rc = false; @@ -274,71 +293,65 @@ void MainWindow::onAddItem() { m_configuration.appendNew(); updateTable(); + if (ui->checkBoxAutoSave->isChecked()) + onSaveConfig(); } + /** - * Adds a new backup item. + * Handles the push of the button "select directory". */ -void MainWindow::onDeleteItem() -{ - int row = ui->tableWidgetConfiguration->selectionModel()->currentIndex().row(); - if (row >= 0){ - m_configuration.items().removeAt(row); - for (int ix = row; ix < m_configuration.items().size(); ix++) - m_configuration.items()[ix].m_no = ix; +void MainWindow::onAddSource(){ +QStringList dirs = ReGuiUtils::selectDirectories(tr("Select Source Directory"), + ReFileUtils::parentOf(m_lastSource)); + m_lastSource = ReFileUtils::nativePath(dirs.at(0)); + for (int ix = 0; ix < dirs.size(); ix++){ + QString newEntry = ReFileUtils::nativePath(dirs.at(ix)); + bool found = false; + for (int ix2 = 0; ! found && ix2 < ui->listWidgetSource->count(); ix2++){ + QString oldEntry = ui->listWidgetSource->item(ix2)->text(); + if (oldEntry.isEmpty()){ + ui->listWidgetSource->takeItem(ix2); + ix2--; + } + found = oldEntry == newEntry; + } + if (! found) + ui->listWidgetSource->addItem(newEntry); } - m_configuration.check(); - updateTable(); - updateItem(row); + onUpdateConfig(); } /** - * Delete the selected source directory from the current backup item. + * The state of "Autosave" has been changed. */ -void MainWindow::onDeleteSource() -{ - int row = ui->listWidgetSource->selectionModel()->currentIndex().row(); - if (row >= 0){ - ui->listWidgetSource->takeItem(row); +void MainWindow::onAutosaveChanged(int newState){ + + // Avoid recursion: + if (m_guiIsInitialized){ + m_guiIsInitialized = false; + bool nowChecked = newState == Qt::Checked; + ui->pushButtonSaveConfig->setEnabled(! nowChecked); + ui->actionAutosave->setChecked(nowChecked); + ui->checkBoxAutoSave->setChecked(nowChecked); + m_guiIsInitialized = true; } } -/** - * Action "switch to English". - */ -void MainWindow::onEnglish(){ - ReGuiApplication::onEnglish(); -} -/** - * Action "switch to German". - */ -void MainWindow::onGerman(){ - ReGuiApplication::onGerman(); -} /** - * @brief MainWindow::onSelectionChanged - * @param selected - * @param deselected + * The state of the menu item "Autosave" has been changed. */ -void MainWindow::onSelectionChanged(const QItemSelection& selected, - const QItemSelection& deselected){ - UNUSED_VAR(deselected); - int count = selected.indexes().size(); - if (count > 0){ - int ix = selected.indexes().at(0).row(); - updateItem(ix); +void MainWindow::onAutosaveToggled(bool newState){ + if (m_guiIsInitialized){ + m_guiIsInitialized = false; + ui->pushButtonSaveConfig->setEnabled(! newState); + ui->checkBoxAutoSave->setChecked(newState); + ui->actionAutosave->setChecked(newState); + m_guiIsInitialized = true; } - } -/** - * The language has been changed. - */ -void MainWindow::onLanguageChange() -{ - initializeGui(); -} /** * Starts the backup. */ @@ -372,29 +385,6 @@ void MainWindow::onChecksums(){ } } -/** - * Handles the push of the button "select directory". - */ -void MainWindow::onAddSource(){ -QStringList dirs = ReGuiUtils::selectDirectories(tr("Select Source Directory"), - ReFileUtils::parentOf(m_lastSource)); - m_lastSource = ReFileUtils::nativePath(dirs.at(0)); - for (int ix = 0; ix < dirs.size(); ix++){ - QString newEntry = ReFileUtils::nativePath(dirs.at(ix)); - bool found = false; - for (int ix2 = 0; ! found && ix2 < ui->listWidgetSource->count(); ix2++){ - QString oldEntry = ui->listWidgetSource->item(ix2)->text(); - if (oldEntry.isEmpty()){ - ui->listWidgetSource->takeItem(ix2); - ix2--; - } - found = oldEntry == newEntry; - } - if (! found) - ui->listWidgetSource->addItem(newEntry); - } -} - /** * Remove the lines of the log list. */ @@ -448,29 +438,6 @@ void MainWindow::onClearFileList() ui->listWidgetFile->clear(); } -/** - * Handles the push of the button "select directory". - */ -void MainWindow::onSelectTarget(){ - QString dir = ui->lineEditTarget->text(); - int pos = dir.indexOf(';'); - if (pos < 0){ - dir.clear(); - } else { - dir.remove(0, pos + 1); - if (! ReFileUtils::isAbsolutPath(dir)) - dir.clear(); - } - dir = ReGuiUtils::selectDirectory(tr("Select Target Directory"), dir); - if (!dir.isEmpty()){ - dir = ReFileUtils::nativePath(dir); - extractTarget(dir); - BackupItem& item = m_configuration.items()[m_currentRowConfiguration]; - if (! BackupUtils::prepareTarget(dir, item, &m_logger)) - say(LOG_INFO, tr("target initialized with %1") - .arg(BackupUtils::nameOfTargetDescription(dir))); - } -} /** * The current row has been changed. * @@ -484,6 +451,77 @@ void MainWindow::onCurrentChanged(const QModelIndex & current, updateItem(row); } +/** + * Adds a new backup item. + */ +void MainWindow::onDeleteItem() +{ + int row = ui->tableWidgetConfiguration->selectionModel()->currentIndex().row(); + if (row >= 0){ + m_configuration.items().removeAt(row); + for (int ix = row; ix < m_configuration.items().size(); ix++) + m_configuration.items()[ix].m_no = ix; + } + m_configuration.check(); + updateTable(); + updateItem(row); + if (ui->checkBoxAutoSave->isChecked()) + onSaveConfig(); +} + +/** + * Delete the selected source directory from the current backup item. + */ +void MainWindow::onDeleteSource() +{ + int row = ui->listWidgetSource->selectionModel()->currentIndex().row(); + if (row >= 0){ + ui->listWidgetSource->takeItem(row); + } + onUpdateConfig(); +} + +/** + * The directory patterns has been changed. + * + * @param newText the new text of the dir pattern + */ +void MainWindow::onDirPatternTextChanged(const QString& newText){ + UNUSED_VAR(newText); + onUpdateConfig(); +} + +/** + * Action "switch to English". + */ +void MainWindow::onEnglish(){ + ReGuiApplication::onEnglish(); +} + +/** + * The filename patterns has been changed. + * + * @param newText the new text of the dir pattern + */ +void MainWindow::onFilePatternTextChanged(const QString& newText){ + UNUSED_VAR(newText); + onUpdateConfig(); +} + +/** + * Action "switch to German". + */ +void MainWindow::onGerman(){ + ReGuiApplication::onGerman(); +} +/** + * The language has been changed. + */ +void MainWindow::onLanguageChange() +{ + initializeGui(); +} + /** * Loads the configuration file. */ @@ -498,6 +536,46 @@ void MainWindow::onSaveConfig(){ m_configuration.save(""); } +/** + * @brief MainWindow::onSelectionChanged + * @param selected + * @param deselected + */ +void MainWindow::onSelectionChanged(const QItemSelection& selected, + const QItemSelection& deselected){ + UNUSED_VAR(deselected); + int count = selected.indexes().size(); + if (count > 0){ + int ix = selected.indexes().at(0).row(); + updateItem(ix); + } + onUpdateConfig(); +} + +/** + * Handles the push of the button "select directory". + */ +void MainWindow::onSelectTarget(){ + QString dir = ui->lineEditTarget->text(); + int pos = dir.indexOf(';'); + if (pos < 0){ + dir.clear(); + } else { + dir.remove(0, pos + 1); + if (! ReFileUtils::isAbsolutPath(dir)) + dir.clear(); + } + dir = ReGuiUtils::selectDirectory(tr("Select Target Directory"), dir); + if (!dir.isEmpty()){ + dir = ReFileUtils::nativePath(dir); + extractTarget(dir); + BackupItem& item = m_configuration.items()[m_currentRowConfiguration]; + if (! BackupUtils::prepareTarget(dir, item, &m_logger)) + say(LOG_INFO, tr("target initialized with %1") + .arg(BackupUtils::nameOfTargetDescription(dir))); + } +} + /** * Starts the backup. */ @@ -534,20 +612,17 @@ void MainWindow::onStop(){ } /** - * Stores the GUI elements into the current backup item. + * The tab has been changed. + * @param index */ -void MainWindow::onUpdate(){ - BackupItem& item = m_configuration.items()[m_currentRowConfiguration]; - item.m_name = ui->lineEditName->text(); - item.m_target = ui->lineEditTarget->text(); - item.m_filePatterns = comboText(ui->comboBoxFilePatterns); - item.m_dirPatterns = comboText(ui->comboBoxDirPatterns); - item.m_sources.clear(); - for (int ix = 0; ix < ui->listWidgetSource->count(); ix++){ - item.m_sources.append(ui->listWidgetSource->item(ix)->text()); +void MainWindow::onCurrentTabChanged(int index){ + if (m_guiIsInitialized && index == 0){ + for (int ix = m_configuration.items().count() - 1; ix >= 0; ix--){ + BackupItem& item = m_configuration.items()[ix]; + m_configuration.readBackupDate(item); + } } - updateTable(); - saveState(); + updateTable(ui->tableWidget); } /** @@ -625,6 +700,25 @@ void MainWindow::startStop(bool isStart){ BackupEngine::m_verboseLevel = (ReVerbose_t) ui->comboBoxVerbose->currentIndex(); } +/** + * Stores the GUI elements into the current backup item and save int to the file. + */ +void MainWindow::onUpdateConfig(){ + if (m_guiIsInitialized){ + BackupItem& item = m_configuration.items()[m_currentRowConfiguration]; + item.m_name = ui->lineEditName->text(); + item.m_target = ui->lineEditTarget->text(); + item.m_filePatterns = comboText(ui->comboBoxFilePatterns); + item.m_dirPatterns = comboText(ui->comboBoxDirPatterns); + item.m_sources.clear(); + for (int ix = 0; ix < ui->listWidgetSource->count(); ix++){ + item.m_sources.append(ui->listWidgetSource->item(ix)->text()); + } + updateTable(); + if (ui->checkBoxAutoSave->isChecked()) + onSaveConfig(); + } +} /** * Shows the data of a given backup item in the gui elements. @@ -635,11 +729,15 @@ void MainWindow::updateItem(int index){ m_currentRowConfiguration = index; if (index < m_configuration.items().size()){ BackupItem& item = m_configuration.items()[index]; - ui->lineEditName->setText(item.m_name); ui->lineEditTarget->setText(item.m_target); ui->listWidgetSource->clear(); + // Avoid implicite configuration saving: + bool oldValue = m_guiIsInitialized; + m_guiIsInitialized = false; + ui->lineEditName->setText(item.m_name); ui->comboBoxFilePatterns->setEditText(item.m_filePatterns); ui->comboBoxDirPatterns->setEditText(item.m_dirPatterns); + m_guiIsInitialized = oldValue; for (int ix = 0; ix < item.m_sources.size(); ix++){ ui->listWidgetSource->insertItem(ix, m_lastSource = item.m_sources.at(ix)); } diff --git a/appl/rebackgui/mainwindow.hpp b/appl/rebackgui/mainwindow.hpp index 912e7f7..6883a4b 100644 --- a/appl/rebackgui/mainwindow.hpp +++ b/appl/rebackgui/mainwindow.hpp @@ -35,7 +35,7 @@ public: void startStop(bool isStart); void restoreState(); void saveState(); - +protected slots: private: QString extractTarget(const QString& dir); void initializeGui(); @@ -46,28 +46,34 @@ private slots: virtual void onAboutToQuit(); void onAddItem(); void onAddSource(); + void onAutosaveChanged(int newState); + void onAutosaveToggled(bool newState); void onChecksums(); void onClean(); void onClearFileList(); void onClearErrorList(); void onClearLog(); void onCurrentChanged(const QModelIndex& current, const QModelIndex& previous); + void onCurrentTabChanged(int index); void onDeleteItem(); void onDeleteSource(); + void onDirPatternTextChanged(const QString& newText); void onEnglish(); + void onFilePatternTextChanged(const QString& newText); void onGerman(); virtual void onGuiTimerUpdate(); + virtual void onLanguageChange(); void onSaveConfig(); void onStart(); void onSelectionChanged(const QItemSelection& prior, const QItemSelection& later); void onSelectTarget(); void onStop(); void onLoadConfig(); - void onUpdate(); - void onVerboseIndexChanged(int index); + void onUpdateConfig(); void updateItem(int index); void updateTable(QTableWidget* target = NULL); void updateTableRow(int row, BackupItem& item, QTableWidget* target = NULL); + void onVerboseIndexChanged(int index); private: Ui::MainWindow *ui; Configuration m_configuration; @@ -82,8 +88,6 @@ private: CleanTask* m_cleanTask; int m_errors; int m_maxListSize; -protected slots: - virtual void onLanguageChange(); }; #endif // MAINWINDOW_HPP diff --git a/appl/rebackgui/mainwindow.ui b/appl/rebackgui/mainwindow.ui index 35ce0ee..f556cc3 100644 --- a/appl/rebackgui/mainwindow.ui +++ b/appl/rebackgui/mainwindow.ui @@ -447,8 +447,30 @@ + + + + + 125 + 0 + + + + Configuration will be saved after each change of a property + + + Autosave + + + true + + + + + false + 125 @@ -497,19 +519,6 @@ - - - - - 125 - 0 - - - - Update - - - @@ -786,6 +795,8 @@ + + @@ -799,7 +810,6 @@ - @@ -885,12 +895,12 @@ German - + true - Default + Autosave diff --git a/appl/rebackgui/rebackgui.de.qm b/appl/rebackgui/rebackgui.de.qm deleted file mode 100644 index f0ba012..0000000 Binary files a/appl/rebackgui/rebackgui.de.qm and /dev/null differ diff --git a/appl/rebackgui/rebackgui.de.ts b/appl/rebackgui/rebackgui.de.ts index 58a2970..e1adf8b 100644 --- a/appl/rebackgui/rebackgui.de.ts +++ b/appl/rebackgui/rebackgui.de.ts @@ -106,7 +106,7 @@ p, li { white-space: pre-wrap; } - + Action Aktion @@ -205,19 +205,19 @@ p, li { white-space: pre-wrap; } - + Stop Beenden - + Calculates checksums for source and target files and reports differences Berechnet Prüfsummen für Quell- und Zieldateien und meldet Unterschiede - + Checksums Prüfsummen @@ -228,7 +228,7 @@ p, li { white-space: pre-wrap; } - + Clean Protokoll: Bereinigen @@ -240,8 +240,8 @@ p, li { white-space: pre-wrap; } - - + + Clear Löschen @@ -267,21 +267,31 @@ p, li { white-space: pre-wrap; } + Configuration will be saved after each change of a property + Die Konfiguration wird nach jedem Wechsel einer Eigenschaft gespeichert + + + + + Autosave + Autom. Speichern + + + Save config Konf. speichern - + Name: Name: - Update - Aktualisieren + Aktualisieren - + Target: Ziel: @@ -290,142 +300,137 @@ p, li { white-space: pre-wrap; } Wähle Ziel - + File patterns: Dateimuster: - + <html><head/><body><p>A comma (',') separated list of filename patterns. A prefix of '-' means inversion: if a filename matches it will not be found.</p><p>Example: *.txt,*.odt</p></body></html> <html><head/><body><p>Eine Liste von Dateinamensmustern, getrennt mit Komma (',') . Ein Präfix '-' bedeuted Umkehrung: Wenn ein Dateiname passt, wird er nicht gefunden.</p><p>Beispiel: *.txt,*.odt</p></body></html> - + Dir patterns: Verzeichnismuster: - + <html><head/><body><p>A comma (',') separated list of directory name patterns. A prefix of '-' means inversion: if a directory name matches it will not be found.</p><p>Example: *,-.git,-*cache*</p></body></html> <html><head/><body><p>Eine Liste von Verzeichnisnamensmustern, getrennt mit Komma (',') . Ein Präfix '-' bedeuted Umkehrung: Wenn ein Verzeichnisname passt, wird er nicht gefunden.</p><p>Beispiel: *,-.git,-*cache*</p></body></html> - + Source dirs: Quelldateien: - + Add source Hinzufügen - + Delete source Löschen - + Files Dateien - + File log: Dateiliste: - + Errors Fehler - + Error log: Fehlerprotokoll: - + File Bearbeiten Datei - + Edit Bearbeiten - + Help Hilfe - + Load Config Konfiguration laden - + Save Config Konfiguration sichern - + Exit Beenden - + Start backup Sicherung starten - + About Über - + English - + German - - Default - - - - - - + + + no backup item selected Kein Sicherungselement ausgewählt - - - + + + Target not available Ziel nicht vorhanden - + Select Source Directory Quellverzeichnis auswählen - + Select Target Directory Zielverzeichnis auswählen - + target initialized with %1 Ziel mit %1 vorbelegt @@ -552,17 +557,23 @@ p, li { white-space: pre-wrap; } Kann nicht schreiben (%1): %2 - + + configuration saved: %1 + configuration changed: %1 + Konfiguration gespeichert: %1 + + + Search started... Suche gestartet... - + yes Ja - + no nein diff --git a/appl/refind/refind.de.ts b/appl/refind/refind.de.ts index 25302b1..8b28b7b 100644 --- a/appl/refind/refind.de.ts +++ b/appl/refind/refind.de.ts @@ -1003,6 +1003,9 @@ p, li { white-space: pre-wrap; } ReGuiApplication Welcome! + Alternative: +xxx +yyy Willkommen! diff --git a/appl/reimgconvert/reimgconvert.de.qm b/appl/reimgconvert/reimgconvert.de.qm new file mode 100644 index 0000000..864e62c Binary files /dev/null and b/appl/reimgconvert/reimgconvert.de.qm differ diff --git a/base/ReConfig.cpp b/base/ReConfig.cpp index ca86e2d..b95be38 100644 --- a/base/ReConfig.cpp +++ b/base/ReConfig.cpp @@ -60,7 +60,7 @@ ReConfig::ReConfig(const char* file, bool readOnly, ReLogger* logger) : if (logger == NULL) { initLogger(); } - if (file != NULL) + if (file != NULL && QFileInfo(file).exists()) read(file); } diff --git a/gui/ReGuiApplication.cpp b/gui/ReGuiApplication.cpp index 6b786ac..cea4ab5 100644 --- a/gui/ReGuiApplication.cpp +++ b/gui/ReGuiApplication.cpp @@ -49,7 +49,8 @@ ReGuiApplication::ReGuiApplication(QApplication& application, m_languages(languages), m_installPath(), m_english(NULL), - m_german(NULL) + m_german(NULL), + m_guiIsInitialized(false) { m_installPath = QDir(ReFileUtils::parentOf(m_application.arguments().at(0))) @@ -198,6 +199,7 @@ void ReGuiApplication::initializeGuiElements(){ connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(onGuiTimerUpdate())); m_guiTimer->start(100); statusBar()->addWidget(m_statusMessage); + m_guiIsInitialized = true; } /** diff --git a/gui/ReGuiApplication.hpp b/gui/ReGuiApplication.hpp index a1cd0ae..4edece4 100644 --- a/gui/ReGuiApplication.hpp +++ b/gui/ReGuiApplication.hpp @@ -68,6 +68,7 @@ protected: QString m_installPath; QAction* m_english; QAction* m_german; + bool m_guiIsInitialized; }; #endif /* REGUIAPPLICATION_HPP_ */ diff --git a/gui/ReGuiValidator.cpp b/gui/ReGuiValidator.cpp index 8ea1962..09ab9c8 100644 --- a/gui/ReGuiValidator.cpp +++ b/gui/ReGuiValidator.cpp @@ -147,7 +147,8 @@ void ReGuiValidator::setInHistory(QComboBox* combo, const QString& value) { if (value != combo->itemText(0)) { combo->insertItem(0, value); } - for (int ii = 1; ii < combo->count(); ii++) { + int count = combo->count(); + for (int ii = count - 1; ii > 0; ii--) { if (value == combo->itemText(ii)) { combo->removeItem(ii); }