]> gitweb.hamatoma.de Git - reqt/commitdiff
rebackgui: configuration works
authorhama <hama@siduction.net>
Sun, 24 Jan 2016 00:56:28 +0000 (01:56 +0100)
committerhama <hama@siduction.net>
Sun, 24 Jan 2016 00:56:28 +0000 (01:56 +0100)
appl/rebackgui/Configuration.cpp
appl/rebackgui/Configuration.hpp
appl/rebackgui/aboutdialog.ui
appl/rebackgui/mainwindow.cpp
appl/rebackgui/mainwindow.hpp
appl/rebackgui/mainwindow.ui
appl/rebackgui/rebackgui.pro
base/ReQStringUtils.cpp
base/ReQStringUtils.hpp
gui/ReGuiApplication.cpp
gui/ReGuiApplication.hpp

index 0c0aec2d681da1da65bcd3fc1912f2809193fb5c..d3db9849fb75d287ee0db0ea6426f7a3864944b9 100644 (file)
@@ -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 <code>no</code>
+ */
+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<int> keys = map.keys();
+                       qSort(keys.begin(), keys.end(), intCompare);
+                       m_items.clear();
+                       QList<int>::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);
+       }
 }
index ed99dc0b7f3da0200ef64690b0a235fde1322777..af9a4a6c7cb218a1f7587d064f084856cf0aac06 100644 (file)
@@ -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<int, BackupItem> BackupItemMap;
+typedef QList<BackupItem> 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<BackupItem> m_items;
+       BackupItemList m_items;
 };
 
 #endif // CONFIGURATION_HPP
index a4e82da3c2fa287789e36faa8a2baf7814ecea9f..5870ff08a9016d1a193c4b2cbd47e19e5b7f12e1 100644 (file)
     <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
 &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
 p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;ReImgConvert&lt;/span&gt; for converting images to smaller dimensions/size.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This is a program of the project&lt;/p&gt;
-&lt;p align=&quot;center&quot; style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Re&lt;/span&gt;al &lt;span style=&quot; font-weight:600;&quot;&gt;Pub&lt;/span&gt;lic &lt;span style=&quot; font-weight:600;&quot;&gt;Lib&lt;/span&gt;rary (RePubLib)&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Sources are public domain and available under&lt;/p&gt;
-&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://github.com/republib&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/republib&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Implemented in QT (C++) 5.x&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Icons: Mark James, &lt;a href=&quot;http://famfamfam.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://famfamfam.com&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Droid Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:600;&quot;&gt;ReBackupGui&lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt; for backup of directories to external media.&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;This is a program of the project&lt;/span&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:600;&quot;&gt;Re&lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;al &lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:600;&quot;&gt;Pub&lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;lic &lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:600;&quot;&gt;Lib&lt;/span&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;rary (RePubLib)&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;Sources are public domain and available under&lt;/span&gt;&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://github.com/republib&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/republib&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt; &lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;Implemented in QT (C++) 5.x&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;Icons: Mark James, &lt;/span&gt;&lt;a href=&quot;http://famfamfam.com&quot;&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt; text-decoration: underline; color:#0000ff;&quot;&gt;http://famfamfam.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Sans Serif'; font-size:9pt;&quot;&gt; &lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
    </property>
    <property name="acceptRichText">
     <bool>false</bool>
@@ -54,7 +54,7 @@ p, li { white-space: pre-wrap; }
      <x>20</x>
      <y>250</y>
      <width>381</width>
-     <height>29</height>
+     <height>32</height>
     </rect>
    </property>
    <layout class="QHBoxLayout" name="horizontalLayout">
index 35c95fd2984e3ddafb109186fb15f4682b2c628c..e171b90d195db7befc802f8ff7df21bf9ec4f7e7 100644 (file)
@@ -8,12 +8,17 @@
 
 #include "backupgui.hpp"
 #include "aboutdialog.hpp"
+#include <QFileDialog>
 
 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                     <code>false</code>
+ */
+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          <code>true</code>
+ */
+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     <code>true</code>: 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<br>
+ *                                     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(" ")));
+       }
 }
 
+
index 3f8409d70e50fc89c4cbe4730d3255cfc553f5e5..78fc42585d2ea2fe1238fbd2ad377d572a6ed8fa 100644 (file)
@@ -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
index 52df1aefdd38fca1b90f245be6751daeb20ce30c..2f101622825d2a295ac0ae7817792a08768e3300 100644 (file)
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
-          <widget class="QWidget" name="">
+          <widget class="QWidget" name="layoutWidget">
            <layout class="QVBoxLayout" name="verticalLayout_2">
             <item>
              <widget class="QTableWidget" name="tableWidget">
+              <property name="editTriggers">
+               <set>QAbstractItemView::NoEditTriggers</set>
+              </property>
+              <property name="selectionMode">
+               <enum>QAbstractItemView::SingleSelection</enum>
+              </property>
+              <property name="selectionBehavior">
+               <enum>QAbstractItemView::SelectRows</enum>
+              </property>
               <attribute name="horizontalHeaderStretchLastSection">
                <bool>true</bool>
               </attribute>
+              <column>
+               <property name="text">
+                <string>Active</string>
+               </property>
+              </column>
               <column>
                <property name="text">
                 <string>Name</string>
             </item>
            </layout>
           </widget>
-          <widget class="QWidget" name="">
+          <widget class="QWidget" name="layoutWidget">
            <layout class="QVBoxLayout" name="verticalLayout_3">
             <item>
              <layout class="QHBoxLayout" name="horizontalLayout_9">
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
-          <widget class="QWidget" name="">
+          <widget class="QWidget" name="layoutWidget">
            <layout class="QVBoxLayout" name="verticalLayout">
             <item>
              <layout class="QHBoxLayout" name="horizontalLayout_7">
              </layout>
             </item>
             <item>
-             <widget class="QTableWidget" name="tableWidget_2">
+             <widget class="QTableWidget" name="tableWidgetConfiguration">
+              <property name="editTriggers">
+               <set>QAbstractItemView::NoEditTriggers</set>
+              </property>
+              <property name="selectionMode">
+               <enum>QAbstractItemView::SingleSelection</enum>
+              </property>
+              <property name="selectionBehavior">
+               <enum>QAbstractItemView::SelectRows</enum>
+              </property>
               <attribute name="horizontalHeaderStretchLastSection">
                <bool>true</bool>
               </attribute>
                 <string>Target</string>
                </property>
               </column>
+              <column>
+               <property name="text">
+                <string>Last backup</string>
+               </property>
+              </column>
               <column>
                <property name="text">
                 <string>Source(s)</string>
             <item>
              <layout class="QHBoxLayout" name="horizontalLayout_6">
               <item>
-               <widget class="QPushButton" name="pushButtonNewEntry">
+               <widget class="QPushButton" name="pushButtonAddItem">
                 <property name="minimumSize">
                  <size>
                   <width>125</width>
                  </size>
                 </property>
                 <property name="text">
-                 <string>New entry</string>
+                 <string>Add item</string>
                 </property>
                </widget>
               </item>
               <item>
-               <widget class="QPushButton" name="pushButtonDeleteEntry">
+               <widget class="QPushButton" name="pushButtonDeleteItem">
                 <property name="minimumSize">
                  <size>
                   <width>125</width>
                  </size>
                 </property>
                 <property name="text">
-                 <string>Delete entry</string>
+                 <string>Delete item</string>
                 </property>
                </widget>
               </item>
             </item>
            </layout>
           </widget>
-          <widget class="QWidget" name="">
+          <widget class="QWidget" name="layoutWidget">
            <layout class="QVBoxLayout" name="verticalLayout_6">
             <item>
              <layout class="QHBoxLayout" name="horizontalLayout_4">
                </widget>
               </item>
               <item>
-               <widget class="QLineEdit" name="lineEdit"/>
+               <widget class="QLineEdit" name="lineEditTarget"/>
               </item>
               <item>
                <widget class="QPushButton" name="pushButtonSelectTarget">
              </layout>
             </item>
             <item>
-             <widget class="QListWidget" name="listWidget_2"/>
+             <widget class="QListWidget" name="listWidgetSource"/>
             </item>
            </layout>
           </widget>
          </layout>
         </item>
         <item>
-         <widget class="QListWidget" name="listWidgetFiles"/>
+         <widget class="QListWidget" name="listWidgetFile"/>
         </item>
        </layout>
       </widget>
          </layout>
         </item>
         <item>
-         <widget class="QListWidget" name="listWidgetErrors"/>
+         <widget class="QListWidget" name="listWidgetError"/>
         </item>
        </layout>
       </widget>
index ee9478d921297e5a4f67aae2d1c88d35a1cf93ab..f8e147bac16687cee9ffab4aa81cff39e75d0be4 100644 (file)
@@ -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
index 3cc636a4238f7d17c693c090820089eee174dfc4..e8ad967cd6547811a262ddd9a228a26720ef54a3 100644 (file)
@@ -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                     <code>true</code>: 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)) {
index bcf2cdfe2bd934debdff7e7afa9111913d66a6e5..22cf850376263291f97787a0406e00792a9b5064 100644 (file)
@@ -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;
index 6c373030361a5b83954a784ac8447cc43152e0ec..efa918a2198bf3e8cae044bf7f3c36908b21af91 100644 (file)
@@ -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.
  *
index 0c30c653a53832ca84d923cadb2cab61e6cd9f91..e99da720c1e64f89c6b29f578865c599946e35e2 100644 (file)
@@ -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;