#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.
*
{
}
+/**
+ * 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();
}
/**
*
* @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);
+ }
}
#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
<string><!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></string>
+</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></string>
</property>
<property name="acceptRichText">
<bool>false</bool>
<x>20</x>
<y>250</y>
<width>381</width>
- <height>29</height>
+ <height>32</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
#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();
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.
*
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(" ")));
+ }
}
+
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
-
-#include "base/rebase.hpp"
-
+#ifndef BACKUPGUI_HPP
+#include "backupgui.hpp"
+#endif
namespace Ui {
class MainWindow;
}
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
<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>
../../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 \
../../gui/ReGuiValidator.hpp \
../../gui/regui.hpp \
aboutdialog.hpp \
- Configuration.hpp \
- backupgui.hpp
+ Configuration.hpp \
+ backupgui.hpp
FORMS += mainwindow.ui \
aboutdialog.ui
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.
*
* 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;
*/
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;
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(
* @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);
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)) {
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,
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);
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;
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.
*
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.
*
*/
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:
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;