From 7cc0484e5170c1cf6e08e589b2dedd6c8ae887c2 Mon Sep 17 00:00:00 2001 From: hama Date: Wed, 20 Jan 2016 12:32:58 +0100 Subject: [PATCH] reimgconvert: refactoring * guiQueue moved to new class ReGuiApplication * recursive conversion, finding other files works * common home directory .reappl --- appl/reimgconvert/converter.cpp | 89 +++++++++++------- appl/reimgconvert/converter.hpp | 4 +- appl/reimgconvert/mainwindow.cpp | 87 +++--------------- appl/reimgconvert/mainwindow.hpp | 12 +-- appl/reimgconvert/mainwindow.ui | 7 +- appl/reimgconvert/reimgconvert.pro | 6 +- base/ReFileUtils.cpp | 2 +- base/ReQStringUtils.cpp | 1 - base/rebase.hpp | 8 ++ gui/ReGuiApplication.cpp | 143 +++++++++++++++++++++++++++++ gui/ReGuiApplication.hpp | 54 +++++++++++ gui/ReGuiQueue.hpp | 2 +- gui/ReStateStorage.cpp | 61 ------------ gui/ReStateStorage.hpp | 22 ----- gui/regui.hpp | 2 + remodules.hpp | 5 +- 16 files changed, 293 insertions(+), 212 deletions(-) create mode 100644 gui/ReGuiApplication.cpp create mode 100644 gui/ReGuiApplication.hpp diff --git a/appl/reimgconvert/converter.cpp b/appl/reimgconvert/converter.cpp index 26d446e..1a6ce1e 100644 --- a/appl/reimgconvert/converter.cpp +++ b/appl/reimgconvert/converter.cpp @@ -16,6 +16,10 @@ #include #include +enum { + LOC_CONSTRUCTOR_1 = LOC_FIRST_OF(LOC_REIMGCONVERTER_CONVERTER), // 20401 +}; + /** @file * * @section intro_sec Introduction @@ -92,7 +96,7 @@ bool Converter::m_shouldStop = false; QStringList Converter::m_files; -uint64_t Converter::m_totalBytes = 0; +qint64 Converter::m_totalBytes = 0; int Converter::m_totalFiles = 0; bool Converter::m_searchReady = false; QMutex Converter::m_mutex; @@ -211,7 +215,7 @@ void addArg(QStringList& args, const char* prefix, int value){ * @param heightNew the new height of the image * @param quality 0 or quality in % (only for JPEG targets) */ -void TaskConverter::callExternProgram(const QString& source, const QString& target, int width, +void TaskConverter::callExternalProgram(const QString& source, const QString& target, int width, int height, int widthNew, int heightNew, int quality){ QStringList args; // convert -size 100x200 source.png -resize 50x100 target.jpg"; @@ -255,15 +259,16 @@ void TaskConverter::convertOneFile(const QString& source, const QString& target, handleSimple(width, height, widthNew, heightNew); else handleUserDefined(width, height, widthNew, heightNew); - QString node = ReFileUtils::nodeOf(source); + QString relPath = source.mid(m_sourceDir.length()); log( - node + " " + info + " " + ReQStringUtils::readableSize(size) + relPath + " " + ReQStringUtils::readableSize(size) + QString(" -> %1x%2 ").arg(widthNew).arg(heightNew)); - callExternProgram(source, target, width, height, widthNew, heightNew, m_quality); + callExternalProgram(source, target, width, height, widthNew, heightNew, m_quality); struct stat info; if (stat(I18N::s2b(target).constData(), &info) == 0){ sizeTarget = info.st_size; - m_mainWindow->logAppendLast(ReQStringUtils::readableSize(sizeTarget) + m_mainWindow->externalAppend(ReGuiQueueItem::ListAppendToCurrent, + NULL, ReQStringUtils::readableSize(sizeTarget) + " " + ReQStringUtils::readableDuration( clock() - start)); } @@ -413,15 +418,15 @@ bool TaskConverter::readPropertiesByIdentify(const QString& name, int& width, in void TaskConverter::run(){ QString msg; clock_t start = clock(); - uint64_t preSize = 0; - uint64_t postSize = 0; - uint64_t lengthTarget = 0; + qint64 preSize = 0; + qint64 postSize = 0; + qint64 lengthTarget = 0; int no = 0; QString info; QString node; QString targetDir; try{ - while (! m_shouldStop && ! m_searchReady){ + while (! m_shouldStop){ m_mutex.lock(); if (m_files.size() == 0) info.clear(); @@ -431,7 +436,10 @@ void TaskConverter::run(){ } m_mutex.unlock(); if (info.isEmpty()){ - QThread::sleep(50); + if (m_searchReady) + break; + else + QThread::sleep(50); } else { int ix = info.indexOf('\t'); node = info.mid(ix + 1); @@ -455,15 +463,17 @@ void TaskConverter::run(){ preSize += length; postSize += lengthTarget; int percentFiles = int(no * 100 / max(1, m_totalFiles)); - int percentSize = int(preSize * 100 / max(1, m_totalBytes)); - m_mainWindow->setStatusMessage(LOG_INFO, - tr("%1 file(s) of %2 (%3 %), %4 -> %5 (%6 %)") - .arg(no).arg(m_totalFiles) - .arg(percentFiles + percentSize / 2) - .arg(ReQStringUtils::readableSize(preSize)) - .arg(ReQStringUtils::readableSize(postSize)) - .arg(postSize * 100.0 / max(1, preSize), 0, - 'f', 2)); + int percentSize = int(preSize * 100 / max(1, min(preSize, m_totalBytes))); + int percent = preSize > m_totalBytes ? percentFiles + : (2 * percentFiles + percentSize) / 3; + info = tr("%1 file(s) of %2 (%3 %), %4 -> %5 (%6 %)") + .arg(no).arg(m_totalFiles) + .arg(percent) + .arg(ReQStringUtils::readableSize(preSize)) + .arg(ReQStringUtils::readableSize(postSize)) + .arg(postSize * 100.0 / max(1LL, preSize), 0, + 'f', 1); + m_mainWindow->externalStatusMessage(LOG_INFO, info); } } @@ -474,13 +484,14 @@ void TaskConverter::run(){ QObject::tr("Execution stopped because of error(s): ") + exc.message()); } - preSize = max(1, preSize); - msg = QObject::tr("%1 file(s) converted, %2 -> %3 (%4 %), duration: %5").arg(no) + preSize = max(1LL, preSize); + msg = QObject::tr("%1 of %2 file(s) converted, %3 -> %4 (%5 %), duration: %6") + .arg(no).arg(m_totalFiles) .arg(ReQStringUtils::readableSize(preSize)) .arg(ReQStringUtils::readableSize(postSize)) - .arg(postSize * 100.0 / preSize, 0, 'f', 2) + .arg(postSize * 100.0 / preSize, 0, 'f', 1) .arg(ReQStringUtils::readableDuration(clock() - start)); - m_mainWindow->finishTask(msg); + m_mainWindow->externalTaskFinished(msg); } /** @@ -505,13 +516,14 @@ TaskSearch::TaskSearch(const QString& directory, * * @param dir the directory to inspect */ -void TaskSearch::searchOneDirectory(const QString& dir){ +void TaskSearch::processOneDirectory(const QString& dir){ QDirIterator it(dir); QRegExp regExpr(m_sourcePattern, Qt::CaseInsensitive, QRegExp::Wildcard); QString relPath; QString info; - if (dir.length() > m_sourceDir.length()) - relPath = m_sourceDir.mid(m_sourceDir.length()); + if (dir.length() > m_sourceDir.length()){ + relPath = dir.mid(m_sourceDir.length() + 1) + OS_SEPARATOR_STR; + } while (it.hasNext()){ if (m_shouldStop){ break; @@ -521,19 +533,22 @@ void TaskSearch::searchOneDirectory(const QString& dir){ info = relPath + "\t" + it.fileName(); m_mutex.lock(); m_files.append(info); + m_totalFiles++; + m_totalBytes += it.fileInfo().size(); m_mutex.unlock(); } } if (m_recursive && ! m_shouldStop){ QDirIterator it2(dir); + QString node; while (it2.hasNext()){ if (m_shouldStop){ break; } it2.next(); - if (it2.fileInfo().isDir()){ - searchOneDirectory(it2.filePath()); + if (it2.fileInfo().isDir() && (node = it2.fileName()) != "." && node != ".."){ + processOneDirectory(it2.filePath()); } } } @@ -544,7 +559,9 @@ void TaskSearch::searchOneDirectory(const QString& dir){ */ void TaskSearch::run(){ m_searchReady = false; - searchOneDirectory(m_sourceDir); + m_totalBytes = 0; + m_totalFiles = 0; + processOneDirectory(m_sourceDir); m_searchReady = true; } @@ -575,8 +592,9 @@ void TaskShowOther::processOneDirectory(const QString& dir){ QRegExp regExpr(m_sourcePattern, Qt::CaseInsensitive, QRegExp::Wildcard); QString relPath; QString info; - if (dir.length() > m_sourceDir.length()) - relPath = m_sourceDir.mid(m_sourceDir.length()); + if (dir.length() > m_sourceDir.length()){ + relPath = dir.mid(m_sourceDir.length() + 1) + OS_SEPARATOR_STR; + } while (it.hasNext()){ if (m_shouldStop){ break; @@ -585,18 +603,19 @@ void TaskShowOther::processOneDirectory(const QString& dir){ if (! it.fileInfo().isDir() && regExpr.indexIn(it.fileName()) < 0){ info = relPath + it.fileName(); m_totalFiles++; - m_mainWindow->remoteLog(info); + m_mainWindow->externalLog(info); } } if (m_recursive && ! m_shouldStop){ QDirIterator it2(dir); + QString node; while (it2.hasNext()){ if (m_shouldStop){ break; } it2.next(); - if (it2.fileInfo().isDir()){ + if (it2.fileInfo().isDir() && (node = it2.fileName()) != "." && node != ".."){ processOneDirectory(it2.filePath()); } } @@ -611,6 +630,6 @@ void TaskShowOther::run(){ m_totalFiles = 0; processOneDirectory(m_sourceDir); m_searchReady = true; - m_mainWindow->finishTask(tr("Found: %1 file(s)").arg(m_totalFiles)); + m_mainWindow->externalTaskFinished(tr("Found: %1 file(s)").arg(m_totalFiles)); } diff --git a/appl/reimgconvert/converter.hpp b/appl/reimgconvert/converter.hpp index 891374a..a0c4522 100644 --- a/appl/reimgconvert/converter.hpp +++ b/appl/reimgconvert/converter.hpp @@ -74,7 +74,7 @@ protected: virtual void run(); protected: bool buildArgs(); - void callExternProgram(const QString& source, const QString& target, int width, + void callExternalProgram(const QString& source, const QString& target, int width, int height, int widthNew, int heightNew, int quality); void converterTask(); void convertOneFile(const QString& source, const QString& target, @@ -109,7 +109,7 @@ public: protected: virtual void run(); protected: - void searchOneDirectory(const QString& dir); + void processOneDirectory(const QString& dir); private: QString m_sourcePattern; bool m_recursive; diff --git a/appl/reimgconvert/mainwindow.cpp b/appl/reimgconvert/mainwindow.cpp index 5a6fef5..52c5d36 100644 --- a/appl/reimgconvert/mainwindow.cpp +++ b/appl/reimgconvert/mainwindow.cpp @@ -15,7 +15,7 @@ #include "ui_mainwindow.h" #include "aboutdialog.hpp" -const QString VERSION("2016.01.15"); +const QString VERSION("2016.01.20"); /** @class MainWindow mainwindow.hpp "mainwindow.hpp" * @@ -32,17 +32,15 @@ const QString VERSION("2016.01.15"); * @param parent NULL or the parent (who destroys the objects at the end) */ MainWindow::MainWindow(const QString& homeDir, QWidget *parent) : - ReHomeApplication("reimgconvert", homeDir, 2, 100100100, parent), + ReGuiApplication("reimgconvert", homeDir, 2, 100100100, parent), ui(new Ui::MainWindow), m_taskConvert(NULL), m_taskSearch(NULL), - m_taskShowOther(NULL), - m_logger(), - m_guiQueue(), - m_guiTimer(new QTimer(this)){ + m_taskShowOther(NULL) +{ ui->setupUi(this); + initializeGuiElements(); startStop(false); - m_statusMessage = new QLabel(tr("Welcome at reimgconvert")); statusBar()->addWidget(m_statusMessage); connect(ui->actionStart, SIGNAL(triggered()), this, SLOT(onConvert())); @@ -65,10 +63,8 @@ MainWindow::MainWindow(const QString& homeDir, QWidget *parent) : connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about())); connect(ui->comboBoxTemplate, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(onTemplateChangeIndex(const QString&))); - connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(guiTimerUpdate())); connect(ui->pushButtonShowOtherFiles, SIGNAL(clicked()), this, SLOT(onShowOtherFiles())); restoreState(); - m_guiTimer->start(100); } /** @@ -116,27 +112,15 @@ bool MainWindow::error(const QString& message){ } /** - * Finishs a task with sending a ready message. - * - * Note: the method is called from a non-main thread. - * - * @param message the message to show - */ -void MainWindow::finishTask(const QString& message){ - Converter::m_mutex.lock(); - m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::ReadyMessage, NULL, message)); - Converter::m_mutex.unlock(); -} -/** - * Callback method of the GUI timer. + * Reads the m_guiQueue and put the info into the GUI elements. */ void MainWindow::guiTimerUpdate() { int count = m_guiQueue.count(); while(count-- > 0){ - Converter::m_mutex.lock(); + m_mutexGuiQueue.lock(); ReGuiQueueItem item = m_guiQueue.popFront(); - Converter::m_mutex.unlock(); + m_mutexGuiQueue.unlock(); if (item.m_type == ReGuiQueueItem::Undef) break; if (! item.apply()){ @@ -152,12 +136,11 @@ void MainWindow::guiTimerUpdate() say(LOG_INFO, item.m_value); break; case ReGuiQueueItem::StatusLine: - setStatusMessage(false, item.m_value); + externalStatusMessage(false, item.m_value); break; case ReGuiQueueItem::ListAppendToCurrent: { - QListWidgetItem* item2 = reinterpret_cast( - item.m_widget)->currentItem(); + QListWidgetItem* item2 = ui->listWidget->currentItem(); item2->setText(item2->text() + " " + item.m_value); break; } @@ -182,22 +165,6 @@ bool MainWindow::log(const QString& message){ return true; } -/** - * @brief Logs a message - * - * Note: used by non main threads - * - * @param message the message to log - * @return true - */ -bool MainWindow::logAppendLast(const QString& message){ - Converter::m_mutex.lock(); - m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::ListAppendToCurrent, - ui->listWidget, message)); - Converter::m_mutex.unlock(); - return true; -} - /** * @brief Handles the button click on "convert". */ @@ -221,7 +188,7 @@ void MainWindow::onConvert(){ delete m_taskSearch; m_taskSearch = new TaskSearch(ui->comboBoxSourceDir->currentText(), ui->comboBoxSourcePattern->currentText(), - ui->checkBoxCopyOtherFiles->isChecked(), this); + ui->checkBoxRecursive->isChecked(), this); m_taskSearch->start(); delete m_taskConvert; @@ -257,7 +224,7 @@ void MainWindow::onShowOtherFiles(){ delete m_taskShowOther; m_taskShowOther = new TaskShowOther(ui->comboBoxSourceDir->currentText(), ui->comboBoxSourcePattern->currentText(), - ui->checkBoxCopyOtherFiles->isChecked(), this); + ui->checkBoxRecursive->isChecked(), this); m_taskShowOther->start(); } /** @@ -295,20 +262,6 @@ void MainWindow::onTemplateChangeIndex(const QString & text){ int height = match.captured(2).toInt(); setMaxDimensions(width, height); } - -/** - * Writes a text to the log. - * - * Note: this method is called from a non-main thread - * - * @param message the text to set - */ -void MainWindow::remoteLog(const QString& message){ - Converter::m_mutex.lock(); - m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::ListEnd, - ui->listWidget, message)); - Converter::m_mutex.unlock(); -} /** * Reads the history of the widget values and other parameters and set it. */ @@ -406,27 +359,13 @@ void MainWindow::selectTarget(){ ui->comboBoxTargetDir->setCurrentText(dir); } -/** - * Writes a text to the status line. - * - * Note: this method is called from a non-main thread - * - * @param message the text to set - */ -void MainWindow::setRemoteStatus(const QString& message){ - Converter::m_mutex.lock(); - m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::StatusLine, - NULL, message)); - Converter::m_mutex.unlock(); -} - /** * 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){ +void MainWindow::externalStatusMessage(bool error, const QString& message){ RE_UNUSED(error); m_statusMessage->setText(message); } diff --git a/appl/reimgconvert/mainwindow.hpp b/appl/reimgconvert/mainwindow.hpp index 148371a..5ee1406 100644 --- a/appl/reimgconvert/mainwindow.hpp +++ b/appl/reimgconvert/mainwindow.hpp @@ -23,7 +23,7 @@ namespace Ui { class MainWindow; } -class MainWindow: public ReHomeApplication, +class MainWindow: public ReGuiApplication, public ReGuiValidator, public ConvertLogger { Q_OBJECT @@ -35,12 +35,8 @@ public: public: virtual void aboutToQuit(); bool error(const QString& message); - void finishTask(const QString& message); bool log(const QString& message); - bool logAppendLast(const QString& message); - void remoteLog(const QString& message); - void setRemoteStatus(const QString& message); - void setStatusMessage(bool error, const QString& message); + void externalStatusMessage(bool error, const QString& message); public: virtual bool say(ReLoggerLevel level, const QString& message); private: @@ -64,10 +60,6 @@ private: TaskConverter* m_taskConvert; TaskSearch* m_taskSearch; TaskShowOther* m_taskShowOther; - QLabel* m_statusMessage; - ReLogger m_logger; - ReGuiQueue m_guiQueue; - QTimer* m_guiTimer; }; #endif // MAINWINDOW_HPP diff --git a/appl/reimgconvert/mainwindow.ui b/appl/reimgconvert/mainwindow.ui index dcd95ab..403db30 100644 --- a/appl/reimgconvert/mainwindow.ui +++ b/appl/reimgconvert/mainwindow.ui @@ -42,7 +42,7 @@ Dimensions (quick) - + 11 @@ -131,7 +131,7 @@ - + 13 @@ -807,6 +807,9 @@ + + false + 125 diff --git a/appl/reimgconvert/reimgconvert.pro b/appl/reimgconvert/reimgconvert.pro index 4aa94bf..6be8c71 100644 --- a/appl/reimgconvert/reimgconvert.pro +++ b/appl/reimgconvert/reimgconvert.pro @@ -11,7 +11,7 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = reimgconvert TEMPLATE = app -INCLUDEPATH = ../.. /usr/include/c++/4.9 +INCLUDEPATH += ../.. SOURCES += main.cpp\ ../../base/ReException.cpp \ @@ -21,6 +21,7 @@ SOURCES += main.cpp\ ../../gui/ReStateStorage.cpp \ ../../gui/ReGuiValidator.cpp \ ../../gui/ReGuiQueue.cpp \ + ../../gui/ReGuiApplication.cpp \ mainwindow.cpp \ converter.cpp \ aboutdialog.cpp @@ -30,6 +31,7 @@ HEADERS += mainwindow.hpp \ ../../base/ReQStringUtils.hpp \ ../../gui/ReStateStorage.hpp \ ../../gui/ReGuiValidator.hpp \ + ../../gui/ReGuiApplication.hpp \ ../../gui/regui.hpp \ converter.hpp \ aboutdialog.hpp @@ -47,4 +49,4 @@ CODECFORSRC = UTF-8 OTHER_FILES += DISTFILES += \ - ReImgConvert.html + ReImgConvert.html diff --git a/base/ReFileUtils.cpp b/base/ReFileUtils.cpp index 8c3c375..ac2e535 100644 --- a/base/ReFileUtils.cpp +++ b/base/ReFileUtils.cpp @@ -12,7 +12,7 @@ #include "base/rebase.hpp" enum { - LOC_DELETE_TREE_1 = LOC_FIRST_OF(LOC_FILE), // 11801 + LOC_DELETE_TREE_1 = LOC_FIRST_OF(LOC_FILE_UTILS), // 11801 LOC_DELETE_TREE_2, // 11802 LOC_DELETE_TREE_3, // 11803 LOC_SET_TIMES_1, // 11804 diff --git a/base/ReQStringUtils.cpp b/base/ReQStringUtils.cpp index 2458f1f..721479f 100644 --- a/base/ReQStringUtils.cpp +++ b/base/ReQStringUtils.cpp @@ -483,7 +483,6 @@ void ReQStringUtils::skipExpected(const ReString& text, QChar expected, QString ReQStringUtils::readableDuration(clock_t duration){ QString rc; char buffer[128]; - int cl_per_sec = CLOCKS_PER_SEC; double duration2 = (double) duration / CLOCKS_PER_SEC; if (duration2 < 60.0){ rc = QString::number(duration2, 'f', 3) + " sec"; diff --git a/base/rebase.hpp b/base/rebase.hpp index 74f7517..bbdb203 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -126,6 +126,14 @@ inline int min(int a, int b) { return a < b ? a : b; } +inline +int max(qint64 a, qint64 b) { + return a > b ? a : b; +} +inline +int min(qint64 a, qint64 b) { + return a < b ? a : b; +} inline double max(double a, double b) { return a > b ? a : b; } diff --git a/gui/ReGuiApplication.cpp b/gui/ReGuiApplication.cpp new file mode 100644 index 0000000..306758d --- /dev/null +++ b/gui/ReGuiApplication.cpp @@ -0,0 +1,143 @@ +/* + * ReStateStorage.cpp + * + * (Un)License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * More info: http://unlicense.org + * The latest sources: https://github.com/republib + */ +#include "base/rebase.hpp" +#include "gui/regui.hpp" +#include + +enum { + LOC_CONSTRUCTOR_1 = LOC_FIRST_OF(LOC_GUI_APPLICATION), // 12401 + LOC_QUIT_1, // 12402 +}; + +/** + * Constructor. + * + * @param applicationName the name of the application. Defines the node + * of the home directory + * @param homeDirBase "": the user's home directory will be used
+ * otherwise: the home directory will created in this + * directory + * @param maxLogFiles max. count of (rotating) log files + * @param maxLogSize max. size of the (rotating) log files + */ +ReGuiApplication::ReGuiApplication(const char* applicationName, + const QString& homeDirBase, + int maxLogFiles, int maxLogSize, + QWidget *parent = NULL) : + QMainWindow(parent), + m_applicationName(applicationName), + m_homeDir(buildHomeDir(homeDirBase, ".reappl")), + m_logger(), + m_storageFile(), + m_guiQueue(), + m_guiTimer(new QTimer(this)), + m_statusMessage(new QLabel(tr("Welcome!"))), + m_mutexGuiQueue() +{ + m_logger.buildStandardAppender(I18N::s2b(m_homeDir) + applicationName, + maxLogSize, maxLogFiles); + m_storageFile = m_homeDir + applicationName + ".state.conf"; + m_logger.log(LOG_INFO, LOC_CONSTRUCTOR_1, "start"); +} + +/** + * Callback method at the application's end. + */ +void ReGuiApplication::aboutToQuit() +{ + m_logger.log(LOG_INFO, LOC_QUIT_1, "end"); +} + +/** + * Build the home directory path name. + * + * @param homeDirBase "": the user's home directory will be used
+ * otherwise: the home directory will created in this + * directory + * @param node + * @return + */ +QString ReGuiApplication::buildHomeDir(QString homeDirBase, const QString& node){ + QString homeDir; + if (homeDirBase.isEmpty()){ + homeDir = QDir::home().absoluteFilePath(node); + } else if (ReFileUtils::isRootDir(homeDirBase.toLatin1().constData())){ + homeDir = homeDirBase + node; + } + ReQStringUtils::chomp(homeDir, OS_SEPARATOR); + QDir home(homeDir); + if (!home.exists()){ + if (!home.mkpath(homeDir)){ + homeDir = home.tempPath() + node; + home.mkpath(homeDir); + } + } + ReQStringUtils::ensureLastChar(homeDir, OS_SEPARATOR); + return homeDir; +} +/** + * Finishs a task with sending a ready message. + * + * Note: the method is called from a non-main thread. + * + * @param message the message to show + */ +void ReGuiApplication::externalTaskFinished(const QString& message){ + m_mutexGuiQueue.lock(); + m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::ReadyMessage, NULL, message)); + m_mutexGuiQueue.unlock(); +} + +/** + * Initializes the GUI elements of this class. + * + * Should be called after initializing the formular (ui->setupUi()). + */ +void ReGuiApplication::initializeGuiElements(){ + QCoreApplication* app = QCoreApplication::instance(); + QObject::connect(app, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); + connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(guiTimerUpdate())); + m_guiTimer->start(100); +} + +/** + * @brief Logs a message + * + * Note: used by a non main thread. + * + * @param type the type of the queue entry + * @param widget NULL or the target widget + * @param info the info for the target widget + * @return true + */ +bool ReGuiApplication::externalAppend(ReGuiQueueItem::WidgetType type, QWidget* widget, + const QString& info){ + m_mutexGuiQueue.lock(); + m_guiQueue.pushBack(ReGuiQueueItem(type, widget, info)); + m_mutexGuiQueue.unlock(); + return true; +} + + +/** + * Writes a text to the log. + * + * Note: this method is called from a non-main thread + * + * @param message the text to set + */ +void ReGuiApplication::externalLog(const QString& message){ + m_mutexGuiQueue.lock(); + m_guiQueue.pushBack(ReGuiQueueItem(ReGuiQueueItem::LogMessage, NULL, + message)); + m_mutexGuiQueue.unlock(); +} + diff --git a/gui/ReGuiApplication.hpp b/gui/ReGuiApplication.hpp new file mode 100644 index 0000000..97b27a8 --- /dev/null +++ b/gui/ReGuiApplication.hpp @@ -0,0 +1,54 @@ +/* + * ReStateStorage.hpp + * + * (Un)License: Public Domain + * You can use and modify this file without any restriction. + * Do what you want. + * No warranties and disclaimer of any damages. + * More info: http://unlicense.org + * The latest sources: https://github.com/republib + */ + +#ifndef REGUIAPPLICATION_HPP_ +#define REGUIAPPLICATION_HPP_ + +#include + +/** + * An abstract base class for applications which stores their data in a home directory. + */ +class ReGuiApplication : public QMainWindow{ +public: + ReGuiApplication(const char* applicationName, + const QString& homeDir, int maxLogFiles, int maxLogSize, + QWidget *parent); +public slots: + /** + * Callback method called when the application is closed. + */ + void aboutToQuit(); +public: + static QString buildHomeDir(QString homeDirBase, const QString& node); + bool externalAppend(ReGuiQueueItem::WidgetType type, QWidget* widget, const QString& info); + void externalLog(const QString& message); + void externalTaskFinished(const QString& message); +protected: + void initializeGuiElements(); +protected slots: + /** + * Reads the m_guiQueue. + */ + virtual void guiTimerUpdate() = 0; +protected: + QByteArray m_applicationName; + QString m_homeDir; + ReLogger m_logger; + QString m_storageFile; + ReGuiQueue m_guiQueue; + QTimer* m_guiTimer; + QLabel* m_statusMessage; + QMutex m_mutexGuiQueue; + +}; + +#endif /* REGUIAPPLICATION_HPP_ */ diff --git a/gui/ReGuiQueue.hpp b/gui/ReGuiQueue.hpp index 23fa19d..0b5775e 100644 --- a/gui/ReGuiQueue.hpp +++ b/gui/ReGuiQueue.hpp @@ -16,7 +16,7 @@ class ReGuiQueueItem { public: enum WidgetType { Undef, LabelText, NewTableRow, ListEnd, ListAppendToCurrent, - LogMessage, ReadyMessage, StatusLine, + LogMessage, LogError, ReadyMessage, StatusLine, UserDefined1, UserDefined2 }; diff --git a/gui/ReStateStorage.cpp b/gui/ReStateStorage.cpp index e21b7e8..8ea323d 100644 --- a/gui/ReStateStorage.cpp +++ b/gui/ReStateStorage.cpp @@ -355,64 +355,3 @@ void ReStateStorage::store(const QMainWindow* window) { } } -/** - * Constructor. - * - * @param applicationName the name of the application. Defines the node - * of the home directory - * @param homeDirBase "": the user's home directory will be used
- * otherwise: the home directory will created in this - * directory - * @param maxLogFiles max. count of (rotating) log files - * @param maxLogSize max. size of the (rotating) log files - */ -ReHomeApplication::ReHomeApplication(const char* applicationName, - const QString& homeDirBase, - int maxLogFiles, int maxLogSize, - QWidget *parent = NULL) : - QMainWindow(parent), - m_applicationName(applicationName), - m_homeDir(buildHomeDir(homeDirBase, "." + m_applicationName)), - m_logger(), - m_storageFile() -{ - m_logger.buildStandardAppender(I18N::s2b(m_homeDir) + "logger.", - maxLogSize, maxLogFiles); - m_storageFile = m_homeDir + OS_SEPARATOR_STR + "status.conf"; - m_storageFile = m_homeDir + "state.conf"; - QCoreApplication* app = QCoreApplication::instance(); - QObject::connect(app, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); -} - -void ReHomeApplication::aboutToQuit() -{ - m_logger.log(LOG_INFO, 999, "exit"); -} - -/** - * Build the home directory path name. - * - * @param homeDirBase "": the user's home directory will be used
- * otherwise: the home directory will created in this - * directory - * @param node - * @return - */ -QString ReHomeApplication::buildHomeDir(QString homeDirBase, const QString& node){ - QString homeDir; - if (homeDirBase.isEmpty()){ - homeDir = QDir::home().absoluteFilePath(node); - } else if (ReFileUtils::isRootDir(homeDirBase.toLatin1().constData())){ - homeDir = homeDirBase + node; - } - ReQStringUtils::chomp(homeDir, OS_SEPARATOR); - QDir home(homeDir); - if (!home.exists()){ - if (!home.mkpath(homeDir)){ - homeDir = home.tempPath() + node; - home.mkpath(homeDir); - } - } - ReQStringUtils::ensureLastChar(homeDir, OS_SEPARATOR); - return homeDir; -} diff --git a/gui/ReStateStorage.hpp b/gui/ReStateStorage.hpp index 075fec2..b44de8b 100644 --- a/gui/ReStateStorage.hpp +++ b/gui/ReStateStorage.hpp @@ -55,26 +55,4 @@ private: ReLogger* m_logger; }; -/** - * An abstract base class for applications which stores their data in a home directory. - */ -class ReHomeApplication : public QMainWindow{ -public: - ReHomeApplication(const char* applicationName, - const QString& homeDir, int maxLogFiles, int maxLogSize, - QWidget *parent); -public slots: - /** - * Callback method called when the application is closed. - */ - void aboutToQuit(); -public: - static QString buildHomeDir(QString homeDirBase, const QString& node); -protected: - QByteArray m_applicationName; - QString m_homeDir; - ReLogger m_logger; - QString m_storageFile; -}; - #endif /* GUI_RESTATESTORAGE_HPP_ */ diff --git a/gui/regui.hpp b/gui/regui.hpp index ec911b2..e092a32 100644 --- a/gui/regui.hpp +++ b/gui/regui.hpp @@ -17,10 +17,12 @@ #include #include "gui/ReGuiQueue.hpp" #include "gui/ReStateStorage.hpp" +#include "gui/ReGuiApplication.hpp" #include "gui/ReGuiValidator.hpp" #include "gui/ReEdit.hpp" #include "gui/ReSettings.hpp" #include "gui/ReFileTree.hpp" + /** * Tests whether a point is inside the rectangle (including border). * @param rect rectangle to test diff --git a/remodules.hpp b/remodules.hpp index 1633b4b..19e6c2b 100644 --- a/remodules.hpp +++ b/remodules.hpp @@ -29,16 +29,19 @@ enum { LOC_MFPARSER, // 115 LOC_TRAVERSER, LOC_SETTINGS, - LOC_FILE, + LOC_FILE_UTILS, LOC_FILETREE, LOC_STATESTORAGE, // 120 LOC_FILESYSTEM, LOC_RANDOMIZER, LOC_CRYPTFILESYSTEM, + LOC_GUI_APPLICATION, // Applications: LOC_RECFORM_CPPPARSER = 201, LOC_RECFORM_CPPFORMATTER = 202, + LOC_REIMGCONVERTER_ = 203, + LOC_REIMGCONVERTER_CONVERTER = 204, }; #define LOC_FIRST_OF(moduleNo) (moduleNo*100+1) class RplModules { -- 2.39.5