From: hama Date: Sun, 24 Jan 2016 00:56:28 +0000 (+0100) Subject: rebackgui: configuration works X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=94822fb3ff2653a2945333fbc48b748ccdc26cf5;p=reqt rebackgui: configuration works --- diff --git a/appl/rebackgui/Configuration.cpp b/appl/rebackgui/Configuration.cpp index 0c0aec2..d3db984 100644 --- a/appl/rebackgui/Configuration.cpp +++ b/appl/rebackgui/Configuration.cpp @@ -8,6 +8,39 @@ #include "backupgui.hpp" +/** + * Constructor. + */ +BackupItem::BackupItem() : + m_no(0), + m_name(), + m_sources(), + m_target(), + m_lastBackup(){ +} + +/** + * Constructor. + * + * @param no number of the item, 1..N + */ +BackupItem::BackupItem(int no) : + m_no(no), + m_name(), + m_sources(), + m_target(), + m_lastBackup(){ +} + +/** + * Returns the list of backup items + * @return the list of backup items + */ +BackupItemList& Configuration::items() +{ + return m_items; +} + /** * Constructor. * @@ -19,14 +52,96 @@ Configuration::Configuration(MainWindow* mainWindow) : { } +/** + * Appends a new item to the list. + */ +void Configuration::appendNew() +{ + BackupItem item(m_items.size()); + item.m_name = QObject::tr("item") + QString::number(item.m_no + 1); + m_items.append(item); +} + +/** + * Checks the configuration. + */ +void Configuration::check() +{ + if (m_items.size() == 0){ + appendNew(); + } +} + +/** + * Returns the item with the given number. + * + * If it not exists it will be created. + * + * @param no the number of the item + * @param map a map containing all items + * @return the item with the number no + */ +BackupItem& Configuration::getItem(int no, BackupItemMap& map){ + if (! map.contains(no)) + map.insert(no, BackupItem(no)); + return map[no]; +} + +static bool intCompare(int a, int b){ + return a < b; +} + /** * Loads the configuration file. * * @param filename the file to load. If "": take the default filename */ -void Configuration::load(const QString& filename) +void Configuration::load(QString filename) { - + if (filename.isEmpty()) + filename = m_mainWindow->fileOfHome(m_mainWindow->applicationName() + ".conf"); + FILE* fp = fopen(I18N::s2b(filename).constData(), "r"); + m_items.clear(); + if (fp == NULL){ + m_mainWindow->error(QObject::tr("cannot open (%1): %2").arg(errno) + .arg(filename)); + } else { + char line[64000]; + QString line2, value; + BackupItemMap map; + int no; + int lineNo = 0; + while(fgets(line, sizeof line, fp) != NULL){ + lineNo++; + // ignore comments and empty lines: + if (line[0] == '#' || line[strspn(line, " \t\r\n")] == '\0') + continue; + line2.fromUtf8(line); + ReQStringUtils::chomp(line2); + if (ReQStringUtils::hasPrefixAndNumber("name", line2, no, value)){ + getItem(no, map).m_name = value; + } else if (ReQStringUtils::hasPrefixAndNumber("sources", line2, no, value)){ + getItem(no, map).m_sources = value.split(';'); + } else if (ReQStringUtils::hasPrefixAndNumber("target", line2, no, value)){ + getItem(no, map).m_name = value; + } else if (ReQStringUtils::hasPrefixAndNumber("lastbackup", line2, no, value)){ + getItem(no, map).m_lastBackup.setMSecsSinceEpoch(value.toLongLong()); + } else { + m_mainWindow->error(QObject::tr("unknown format in %1-%2: %3") + .arg(filename).arg(lineNo) + .arg(line2)); + } + QList keys = map.keys(); + qSort(keys.begin(), keys.end(), intCompare); + m_items.clear(); + QList::iterator it; + for (it = keys.begin(); it != keys.end(); ++it){ + m_items.append(map[*it]); + } + } + fclose(fp); + } + check(); } /** @@ -34,7 +149,30 @@ void Configuration::load(const QString& filename) * * @param filename the file to save. If "": take the default filename */ -void Configuration::save(const QString& filename) +void Configuration::save(QString filename) { - + if (filename.isEmpty()) + filename = m_mainWindow->fileOfHome(m_mainWindow->applicationName() + ".conf"); + FILE* fp = fopen(I18N::s2b(filename).constData(), "w"); + if (fp == NULL){ + m_mainWindow->error(QObject::tr("cannot open (%1): %2").arg(errno) + .arg(filename)); + } else { + QByteArray buffer; + for (int ix = 0; ix < m_items.size(); ix++){ + BackupItem& item = m_items[ix]; + buffer = "name." + QByteArray::number(ix + 1) + "=" + + item.m_name.toUtf8() + "\n"; + buffer += "sources." + QByteArray::number(ix + 1) + "=" + + item.m_sources.join(';').toUtf8() + "\n"; + buffer += "target." + QByteArray::number(ix + 1) + "=" + + item.m_target.toUtf8() + "\n"; + buffer += "lastbackup." + QByteArray::number(ix + 1) + "=" + + item.m_lastBackup.toString("yyyy.MM.dd/hh:mm") + "\n"; + if (fputs(buffer.constData(), fp) != buffer.length()) + m_mainWindow->error(QObject::tr("cannot write (%1): %2").arg(errno) + .arg(filename)); + } + fclose(fp); + } } diff --git a/appl/rebackgui/Configuration.hpp b/appl/rebackgui/Configuration.hpp index ed99dc0..af9a4a6 100644 --- a/appl/rebackgui/Configuration.hpp +++ b/appl/rebackgui/Configuration.hpp @@ -9,26 +9,40 @@ #ifndef CONFIGURATION_HPP #define CONFIGURATION_HPP +class MainWindow; + class BackupItem{ public: + BackupItem(); + BackupItem(int no); +public: + int m_no; QString m_name; QStringList m_sources; QString m_target; QDateTime m_lastBackup; }; +typedef QMap BackupItemMap; +typedef QList BackupItemList; class Configuration { public: Configuration(MainWindow* mainWindow); public: - void load(const QString& filename); - void save(const QString& filename); + void appendNew(); + void check(); + BackupItemList& items(); + void load(QString filename); + void save(QString filename); +private: + BackupItem& getItem(int no, BackupItemMap& map); + BackupItem& splitLine(QString& line, QString& value); private: QString m_filename; MainWindow* m_mainWindow; - QList m_items; + BackupItemList m_items; }; #endif // CONFIGURATION_HPP diff --git a/appl/rebackgui/aboutdialog.ui b/appl/rebackgui/aboutdialog.ui index a4e82da..5870ff0 100644 --- a/appl/rebackgui/aboutdialog.ui +++ b/appl/rebackgui/aboutdialog.ui @@ -32,14 +32,14 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">ReImgConvert</span> for converting images to smaller dimensions/size.</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is a program of the project</p> -<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Re</span>al <span style=" font-weight:600;">Pub</span>lic <span style=" font-weight:600;">Lib</span>rary (RePubLib)</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sources are public domain and available under</p> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="https://github.com/republib"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/republib</span></a> </p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Implemented in QT (C++) 5.x</p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Icons: Mark James, <a href="http://famfamfam.com"><span style=" text-decoration: underline; color:#0000ff;">http://famfamfam.com</span></a> </p></body></html> +</style></head><body style=" font-family:'Droid Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">ReBackupGui</span><span style=" font-family:'Sans Serif'; font-size:9pt;"> for backup of directories to external media.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">This is a program of the project</span></p> +<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Re</span><span style=" font-family:'Sans Serif'; font-size:9pt;">al </span><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Pub</span><span style=" font-family:'Sans Serif'; font-size:9pt;">lic </span><span style=" font-family:'Sans Serif'; font-size:9pt; font-weight:600;">Lib</span><span style=" font-family:'Sans Serif'; font-size:9pt;">rary (RePubLib)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Sources are public domain and available under</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="https://github.com/republib"><span style=" font-family:'Sans Serif'; font-size:9pt; text-decoration: underline; color:#0000ff;">https://github.com/republib</span></a><span style=" font-family:'Sans Serif'; font-size:9pt;"> </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Implemented in QT (C++) 5.x</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Icons: Mark James, </span><a href="http://famfamfam.com"><span style=" font-family:'Sans Serif'; font-size:9pt; text-decoration: underline; color:#0000ff;">http://famfamfam.com</span></a><span style=" font-family:'Sans Serif'; font-size:9pt;"> </span></p></body></html> false @@ -54,7 +54,7 @@ p, li { white-space: pre-wrap; } 20 250 381 - 29 + 32 diff --git a/appl/rebackgui/mainwindow.cpp b/appl/rebackgui/mainwindow.cpp index 35c95fd..e171b90 100644 --- a/appl/rebackgui/mainwindow.cpp +++ b/appl/rebackgui/mainwindow.cpp @@ -8,12 +8,17 @@ #include "backupgui.hpp" #include "aboutdialog.hpp" +#include const QString VERSION("2016.01.20"); MainWindow::MainWindow(const QString& homeDir, QWidget *parent) : - ReGuiApplication("reimgconvert", homeDir, 2, 100100100, parent), - ui(new Ui::MainWindow) + ReGuiApplication("rebackupgui", homeDir, 2, 100100100, parent), + ui(new Ui::MainWindow), + m_configuration(this), + m_currentRowConfiguration(0), + m_currentRowBackup(0), + m_lastSource() { ui->setupUi(this); initializeGuiElements(); @@ -22,20 +27,264 @@ MainWindow::MainWindow(const QString& homeDir, QWidget *parent) : SLOT(onStart())); connect(ui->actionStop, SIGNAL(triggered()), this, SLOT(onStop())); - connect(ui->actionSelectTarget, SIGNAL(triggered()), this, - SLOT(selectTarget())); - connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(clear())); - connect(ui->pushButtonStart, SIGNAL(clicked()), this, SLOT(onStart())); + connect(ui->pushButtonBackup, SIGNAL(clicked()), this, SLOT(onStart())); connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onStop())); - connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); - loadConfig(); + 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->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->pushButtonDeleteItem, SIGNAL(clicked()), this, SLOT(onNewDeleteItem())); + 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&))); + m_configuration.load(""); + updateTable(); + updateItem(0); } +/** + * Destructor. + */ MainWindow::~MainWindow() { delete ui; } +/** + * Calles at the program's end. + */ +void MainWindow::aboutToQuit() +{ + +} + +/** + * Issues an error message. + * + * @param message the message to issue + * @return false + */ +bool MainWindow::error(const QString& message){ + ui->listWidgetError->addItem(message); + ui->listWidgetError->setCurrentRow(ui->listWidgetError->count() - 1); + return false; +} + + +/** + * Set GUI elements from the queue when the GUI timer is triggered. + */ +void MainWindow::guiTimerUpdate() +{ + int count = m_guiQueue.count(); + while(count-- > 0){ + m_mutexGuiQueue.lock(); + ReGuiQueueItem item = m_guiQueue.popFront(); + m_mutexGuiQueue.unlock(); + if (item.m_type == ReGuiQueueItem::Undef) + break; + if (! item.apply()){ + switch (item.m_type){ + case ReGuiQueueItem::ListEnd: + ui->listWidgetLog->addItem(item.m_value); + break; + case ReGuiQueueItem::ReadyMessage: + log(item.m_value); + startStop(false); + break; + case ReGuiQueueItem::LogMessage: + log(item.m_value); + break; + case ReGuiQueueItem::LogError: + error(item.m_value); + break; + case ReGuiQueueItem::StatusLine: + setStatusMessage(false, item.m_value); + break; + default: + error("unknown item type: " + QString::number(item.m_type) + + " " + item.m_value); + break; + } + } + } +} + +/** + * @brief Logs a message + * + * @param message the message to log + * @return true + */ +bool MainWindow::log(const QString& message){ + ui->listWidgetLog->addItem(message); + ui->listWidgetLog->setCurrentRow(ui->listWidgetLog->count() - 1); + return true; +} + +/** + * Shows the "about" window. + */ +void MainWindow::onAbout() +{ + AboutDialog dialog(VERSION); + dialog.exec(); +} + +/** + * Adds a new backup item. + */ +void MainWindow::onAddItem() +{ + m_configuration.appendNew(); + updateTable(); +} + +/** + * 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); +} + +/** + * Delete the selected source directory from the current backup item. + */ +void MainWindow::onDeleteSource() +{ + +} + +void MainWindow::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected){ + int count = selected.indexes().size(); + if (count > 0){ + int ix = selected.indexes().at(0).row(); + updateItem(ix); + } + +} +/** + * Handles the push of the button "select directory". + */ +void MainWindow::onAddSource(){ + QString dir = QFileDialog::getExistingDirectory(this, + tr("Select Source Directory"), m_lastSource, + QFileDialog::ShowDirsOnly); + if (!dir.isEmpty()){ + m_lastSource = ReFileUtils::nativePath(dir); + ui->listWidgetSource->addItem(m_lastSource); + } +} + +/** + * Handles the push of the button "select directory". + */ +void MainWindow::onSelectTarget(){ + QString dir = QFileDialog::getExistingDirectory(this, + tr("Select Target Directory"), m_lastSource, + QFileDialog::ShowDirsOnly); + if (!dir.isEmpty()){ + dir = ReFileUtils::nativePath(dir); + findTarget(dir); + } +} + +/** + * Find the target identification. + * + * @param dir the directory on the external medium (already mounted) + */ +void MainWindow::findTarget(const QString& dir){ +#if defined __linux__ + +#else +#endif +} + +/** + * The current row has been changed. + * + * @param current the current model index + * @param previous the previous model index + */ +void MainWindow::onCurrentChanged(const QModelIndex & current, + const QModelIndex & previous){ + int row = current.row(); + updateItem(row); +} + +/** + * Loads the configuration file. + */ +void MainWindow::onLoadConfig(){ + m_configuration.load(""); + updateTable(); +} +/** + * Loads the configuration file. + */ +void MainWindow::onSaveConfig(){ + m_configuration.save(""); +} + +/** + * Starts the backup. + */ +void MainWindow::onStart(){ + startStop(true); +} +/** + * Stops the backup. + */ +void MainWindow::onStop(){ + startStop(false); +} + +/** + * Stores the GUI elements into the current backup item. + */ +void MainWindow::onUpdate(){ + BackupItem& item = m_configuration.items()[m_currentRowConfiguration]; + item.m_name = ui->lineEditName->text(); + item.m_target = ui->lineEditTarget->text(); + item.m_sources.clear(); + for (int ix = 0; ix < ui->listWidgetSource->count(); ix++){ + item.m_sources.append(ui->listWidgetSource->item(ix)->text()); + } + updateTable(); +} + +/** +* Writes a text to the status line. +* +* @param error true: the message is an error message +* @param message the text to set +*/ +void MainWindow::setStatusMessage(bool error, const QString& message){ + RE_UNUSED(error); + m_statusMessage->setText(message); +} + /** * Starts or stops the backup. * @@ -49,21 +298,61 @@ void MainWindow::startStop(bool isStart){ ui->pushButtonStop->setEnabled(isStart); } + /** - * Loads the configuration file. + * Shows the data of a given backup item in the gui elements. + * + * @param index the index in the list */ -void MainWindow::loadConfig(){ - +void MainWindow::updateItem(int index){ + m_currentRowConfiguration = index; + BackupItem& item = m_configuration.items()[index]; + ui->lineEditName->setText(item.m_name); + ui->lineEditTarget->setText(item.m_target); + ui->listWidgetSource->clear(); + for (int ix = 0; ix < item.m_sources.size(); ix++){ + ui->listWidgetSource->insertItem(ix, m_lastSource = item.m_sources.at(ix)); + } } /** - * @brief Handles the button click on "convert". + * Writes the backup item list into the two tables */ -void MainWindow::onStart(){ +void MainWindow::updateTable(QTableWidget* target) +{ + if (target == NULL){ + updateTable(ui->tableWidget); + updateTable(ui->tableWidgetConfiguration); + } else { + int size = m_configuration.items().size(); + if (target->rowCount() != size) + target->setRowCount(size); + for (int ix = 0; ix < size; ix++){ + updateTableRow(ix, m_configuration.items()[ix], target); + } + } } + /** - * @brief Handles the button click on "convert". + * Sets a row of the item table with the values from the given item. + * + * @param row this row will be updated + * @param item the data source of the row + * @param target NULL: fill both tables
+ * otherwise: the table to process */ -void MainWindow::onStop(){ +void MainWindow::updateTableRow(int row, BackupItem& item, QTableWidget* target){ + if (target == NULL){ + updateTableRow(row, item, ui->tableWidget); + updateTableRow(row, item, ui->tableWidgetConfiguration); + } else { + int base = target == ui->tableWidget ? 1 : 0; + target->setItem(row, base + 0, new QTableWidgetItem(item.m_name)); + target->setItem(row, base + 1, new QTableWidgetItem(item.m_target)); + target->setItem(row, base + 2, new QTableWidgetItem(! item.m_lastBackup.isValid() ? "" : + item.m_lastBackup.toString("yyyy.MM.dd hh:mm"))); + target->setItem(row, base + 3, new QTableWidgetItem(item.m_sources.join(" "))); + } } + diff --git a/appl/rebackgui/mainwindow.hpp b/appl/rebackgui/mainwindow.hpp index 3f8409d..78fc425 100644 --- a/appl/rebackgui/mainwindow.hpp +++ b/appl/rebackgui/mainwindow.hpp @@ -8,9 +8,9 @@ #ifndef MAINWINDOW_HPP #define MAINWINDOW_HPP - -#include "base/rebase.hpp" - +#ifndef BACKUPGUI_HPP +#include "backupgui.hpp" +#endif namespace Ui { class MainWindow; } @@ -26,14 +26,33 @@ public: bool error(const QString& message); bool log(const QString& message); void setStatusMessage(bool error, const QString& message); -private: - virtual void aboutToQuit(); - void loadConfig(); + void startStop(bool isStart); private slots: - void about(); - + virtual void aboutToQuit(); + void findTarget(const QString& dir); + virtual void guiTimerUpdate(); + void onAbout(); + void onAddItem(); + void onAddSource(); + void onCurrentChanged(const QModelIndex& current, const QModelIndex& previous); + void onDeleteItem(); + void onDeleteSource(); + void onSaveConfig(); + void onStart(); + void onSelectionChanged(const QItemSelection& prior, const QItemSelection& later); + void onSelectTarget(); + void onStop(); + void onLoadConfig(); + void onUpdate(); + void updateItem(int index); + void updateTable(QTableWidget* target = NULL); + void updateTableRow(int row, BackupItem& item, QTableWidget* target = NULL); private: Ui::MainWindow *ui; + Configuration m_configuration; + int m_currentRowConfiguration; + int m_currentRowBackup; + QString m_lastSource; }; #endif // MAINWINDOW_HPP diff --git a/appl/rebackgui/mainwindow.ui b/appl/rebackgui/mainwindow.ui index 52df1ae..2f10162 100644 --- a/appl/rebackgui/mainwindow.ui +++ b/appl/rebackgui/mainwindow.ui @@ -30,13 +30,27 @@ Qt::Vertical - + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + true + + + Active + + Name @@ -107,7 +121,7 @@ - + @@ -175,7 +189,7 @@ Qt::Vertical - + @@ -202,7 +216,16 @@ - + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + true @@ -216,6 +239,11 @@ Target + + + Last backup + + Source(s) @@ -226,7 +254,7 @@ - + 125 @@ -234,12 +262,12 @@ - New entry + Add item - + 125 @@ -247,7 +275,7 @@ - Delete entry + Delete item @@ -281,7 +309,7 @@ - + @@ -345,7 +373,7 @@ - + @@ -413,7 +441,7 @@ - +
@@ -470,7 +498,7 @@ - + @@ -523,7 +551,7 @@ - + diff --git a/appl/rebackgui/rebackgui.pro b/appl/rebackgui/rebackgui.pro index ee9478d..f8e147b 100644 --- a/appl/rebackgui/rebackgui.pro +++ b/appl/rebackgui/rebackgui.pro @@ -18,11 +18,11 @@ SOURCES += main.cpp\ ../../base/ReFileUtils.cpp \ ../../base/ReLogger.cpp \ ../../gui/ReStateStorage.cpp \ - ../../gui/ReGuiValidator.cpp \ + ../../gui/ReGuiApplication.cpp \ ../../gui/ReGuiQueue.cpp \ mainwindow.cpp \ aboutdialog.cpp \ - Configuration.cpp + Configuration.cpp HEADERS += mainwindow.hpp \ ../../base/rebase.hpp \ @@ -31,8 +31,8 @@ HEADERS += mainwindow.hpp \ ../../gui/ReGuiValidator.hpp \ ../../gui/regui.hpp \ aboutdialog.hpp \ - Configuration.hpp \ - backupgui.hpp + Configuration.hpp \ + backupgui.hpp FORMS += mainwindow.ui \ aboutdialog.ui diff --git a/base/ReQStringUtils.cpp b/base/ReQStringUtils.cpp index 3cc636a..e8ad967 100644 --- a/base/ReQStringUtils.cpp +++ b/base/ReQStringUtils.cpp @@ -79,6 +79,34 @@ QString& ReQStringUtils::ensureLastChar(QString& value, QChar lastChar) { return value; } +/** + * Checks whether a line has the format "prefix.number=value", e.g. "name.5=joe" + * + * @param prefix prefix of the line, which is search + * @param line the line where the prefix is searched + * @param no OUT: the number found after the prefix + * @param value the string behind the '=' + * @return true: the line has the needed format and prefix + */ +bool ReQStringUtils::hasPrefixAndNumber(const QString prefix, const QString& line, + int& no, QString& value) +{ + bool rc = false; + int lengthPrefix = prefix.length(); + if (line.startsWith(prefix) && line.at(lengthPrefix) == '.'){ + int lengthNumber = 0; + uint number; + if ( (lengthNumber = lengthOfUInt(line, lengthPrefix + 1, 10, &number)) > 0){ + if (line.at(lengthPrefix + 1 + lengthNumber) == '='){ + no = number; + rc = true; + value = line.mid(lengthPrefix + 1 + lengthNumber); + } + } + } + return rc; +} + /** * @brief Determines the length and value of an integer. * @@ -91,7 +119,7 @@ QString& ReQStringUtils::ensureLastChar(QString& value, QChar lastChar) { * otherwise: the length of the integer */ int ReQStringUtils::lengthOfUInt64(const ReString& text, int start, int radix, - uint64_t* pValue) { + quint64* pValue) { int inputLength = text.size(); int64_t value = 0; int ix = start; @@ -145,7 +173,7 @@ int ReQStringUtils::lengthOfUInt64(const ReString& text, int start, int radix, */ int ReQStringUtils::lengthOfUInt(const ReString& text, int start, int radix, uint* pValue) { - uint64_t value; + quint64 value; int rc = lengthOfUInt64(text, start, radix, &value); if (pValue != NULL) *pValue = (uint) value; @@ -671,10 +699,10 @@ void ReUnitParser::parse() { bool isNeg = op.startsWith("-"); if (isNeg) op = op.mid(1); - uint64_t value = valueOf(op); + quint64 value = valueOf(op); if (powerOperands.count() > 1) { - uint64_t fac = value; - uint64_t exponent = valueOf(*++it3); + quint64 fac = value; + quint64 exponent = valueOf(*++it3); if (qLn(value) * qLn(exponent) >= qLn(qPow(2.0, 64))) throw ReParserException( QObject::tr( @@ -703,8 +731,8 @@ void ReUnitParser::parse() { * @return the value of the number multiplied by the factor given by the unit * @throws ReParserException */ -uint64_t ReUnitParser::valueOf(const QString& value) const { - uint64_t rc = 0; +quint64 ReUnitParser::valueOf(const QString& value) const { + quint64 rc = 0; int ix = ReQStringUtils::lengthOfUInt64(value, 0, 10, &rc); if (ix == 0) throw ReParserException(QObject::tr("number expected: ") + value); @@ -726,7 +754,7 @@ uint64_t ReUnitParser::valueOf(const QString& value) const { bool ok = false; QString unit2 = *pair.begin(); QString factor = *++pair.begin(); - uint64_t nFactor = factor.toLongLong(&ok); + quint64 nFactor = factor.toLongLong(&ok); if (!ok) throw ReParserException(QObject::tr("not a number: ") + factor); if (unit2.startsWith(unit, Qt::CaseInsensitive)) { diff --git a/base/ReQStringUtils.hpp b/base/ReQStringUtils.hpp index bcf2cdf..22cf850 100644 --- a/base/ReQStringUtils.hpp +++ b/base/ReQStringUtils.hpp @@ -43,6 +43,8 @@ public: static ReString& chomp(ReString& text, char cc = '\n'); static int countOf(const QString& value, QChar toFind, int start = 0); static QString& ensureLastChar(QString& value, QChar lastChar); + static bool hasPrefixAndNumber(const QString prefix, const QString& line, + int& no, QString& value); static int lengthOfDate(const ReString& text, int start = 0, QDate* value = NULL); static int lengthOfDateTime(const ReString& text, int start = 0, @@ -53,7 +55,7 @@ public: static int lengthOfTime(const ReString& text, int start = 0, QTime* value = NULL); static int lengthOfUInt64(const ReString& text, int start = 0, int radix = - 10, uint64_t* value = NULL); + 10, quint64* value = NULL); static int lengthOfUInt(const ReString& text, int start, int radix, uint* pValue); static QString longestPrefix(const QStringList& list); @@ -116,7 +118,7 @@ public: protected: void parse(); void normalize(); - uint64_t valueOf(const QString& value) const; + quint64 valueOf(const QString& value) const; protected: int64_t m_result; QString m_expr; diff --git a/gui/ReGuiApplication.cpp b/gui/ReGuiApplication.cpp index 6c37303..efa918a 100644 --- a/gui/ReGuiApplication.cpp +++ b/gui/ReGuiApplication.cpp @@ -56,6 +56,17 @@ void ReGuiApplication::aboutToQuit() m_logger.log(LOG_INFO, LOC_QUIT_1, "end"); } +/** + * Returns the full name of a file in the home directory. + * + * @param node the filename without path + * @return the filename with path + */ +QString ReGuiApplication::fileOfHome(const QString& node) +{ + return m_homeDir + node; +} + /** * Build the home directory path name. * @@ -109,6 +120,16 @@ void ReGuiApplication::initializeGuiElements(){ statusBar()->addWidget(m_statusMessage); } +/** + * Returns the application's name. + * + * @return the name of the application + */ +const QByteArray& ReGuiApplication::applicationName() const +{ + return m_applicationName; +} + /** * Returns the logger. * diff --git a/gui/ReGuiApplication.hpp b/gui/ReGuiApplication.hpp index 0c30c65..e99da72 100644 --- a/gui/ReGuiApplication.hpp +++ b/gui/ReGuiApplication.hpp @@ -28,13 +28,15 @@ public slots: */ void aboutToQuit(); public: - static QString buildHomeDir(QString homeDirBase, const QString& node); + const QByteArray& applicationName() const; + QString fileOfHome(const QString& node); bool externalAppend(ReGuiQueueItem::WidgetType type, QWidget* widget, const QString& info); void externalError(const QString& message); void externalLog(const QString& message); void externalTaskFinished(const QString& message); ReLogger* logger(); - +public: + static QString buildHomeDir(QString homeDirBase, const QString& node); protected: void initializeGuiElements(); protected slots: @@ -44,6 +46,8 @@ protected slots: virtual void guiTimerUpdate() = 0; protected: QByteArray m_applicationName; + /// the base directory for resources of the program like configuration file. + /// With trailing slash QString m_homeDir; ReLogger m_logger; QString m_storageFile;