From ccf4081929982c76adbf46dc3a7dd82b98443470 Mon Sep 17 00:00:00 2001 From: hama Date: Sun, 20 Dec 2015 18:42:41 +0100 Subject: [PATCH] Refind: works with separate file finder thread * GUI manipulation only in main thread * layout changed: 4 lines in the header * stop after maximal hits * clear file table + append results to existing results * new layout for export --- appl/refind/dialogfileplaceholder.ui | 6 +- appl/refind/filefinder.cpp | 119 ++--- appl/refind/filefinder.hpp | 8 +- appl/refind/mainwindow.cpp | 84 +++- appl/refind/mainwindow.hpp | 5 +- appl/refind/mainwindow.ui | 669 +++++++++++++-------------- appl/refind/refind.pro | 6 +- appl/refind/utils.cpp | 13 + appl/refind/utils.hpp | 9 +- base/rebase.hpp | 6 +- gui/ReGuiQueue.cpp | 97 ++++ gui/ReGuiQueue.hpp | 82 ++++ gui/regui.hpp | 3 + 13 files changed, 657 insertions(+), 450 deletions(-) create mode 100644 gui/ReGuiQueue.cpp create mode 100644 gui/ReGuiQueue.hpp diff --git a/appl/refind/dialogfileplaceholder.ui b/appl/refind/dialogfileplaceholder.ui index f274a2a..1facfac 100644 --- a/appl/refind/dialogfileplaceholder.ui +++ b/appl/refind/dialogfileplaceholder.ui @@ -7,7 +7,7 @@ 0 0 800 - 429 + 500 @@ -138,12 +138,12 @@ - doc + /home/bob/doc - relative path + path without node diff --git a/appl/refind/filefinder.cpp b/appl/refind/filefinder.cpp index 2869c34..259a2b0 100644 --- a/appl/refind/filefinder.cpp +++ b/appl/refind/filefinder.cpp @@ -21,7 +21,6 @@ * Constructor. */ FileFinder::FileFinder() : - m_lines(0), m_patterns(), m_antiPatterns(), m_minSize(0), @@ -37,15 +36,26 @@ FileFinder::FileFinder() : m_textFinder(NULL), m_table(NULL), m_statistics(), - m_announcer(NULL), - m_observer(NULL){ - m_youngerThan.setMSecsSinceEpoch(0); - m_olderThan.setMSecsSinceEpoch(0); + m_guiQueue(NULL), + m_maxHits(0){ + m_youngerThan.setMSecsSinceEpoch(0); + m_olderThan.setMSecsSinceEpoch(0); } +/** + * Destructor. + */ FileFinder::~FileFinder(){ } +/** + * Resets the instance. + */ +void FileFinder::clear() +{ + m_statistics.clear(); +} + /** * Returns a string representation of the filesize. * @@ -54,7 +64,7 @@ FileFinder::~FileFinder(){ */ QString fileSize(int64_t size){ QString rc; - rc.sprintf("%.6f", (double) size / 1000000.0); + rc.sprintf("%12.6f", (double) size / 1000000.0); return rc; } /** @@ -114,6 +124,7 @@ void FileFinder::fillTable(const QString& path, int depth){ QList::const_iterator it2; QList ::const_iterator it; clock_t nextUpdate = clock() + CLOCKS_PER_SEC; + QString row, size, type, modified; for (it = entries.begin(); it != entries.end(); ++it){ node = it->fileName(); if (node == "." || node == "..") @@ -128,42 +139,42 @@ void FileFinder::fillTable(const QString& path, int depth){ if (ignore) continue; if (depth >= m_minDepth && isValid(*it)){ - if (m_lines >= m_table->rowCount()){ - m_table->setRowCount(m_lines + 500); - } bool isDir = it->isDir(); if (isDir) m_statistics.m_dirs++; else m_statistics.m_files++; - m_table->setItem(m_lines, TC_NODE, new QTableWidgetItem(node)); + row.clear(); + // TC_NODE, TC_EXT, TC_SIZE, TC_MODIFIED, TC_TYPE, TC_PATH int ix = node.lastIndexOf('.'); ext = ix <= 0 ? "" : node.mid(ix + 1).toLower(); - m_table->setItem(m_lines, TC_EXT, new QTableWidgetItem(ext)); - m_table->setItem(m_lines, TC_TYPE, new QTableWidgetItem(typeOf(*it))); - m_table->setItem(m_lines, TC_PATH, new QTableWidgetItem(path)); - QTableWidgetItem* item = new QTableWidgetItem( - isDir ? "" : fileSize(it->size())); + type = typeOf(*it); + if (isDir) + size.clear(); + else + size = fileSize(it->size()); + modified = it->lastModified().toString("yyyy.MM.dd/hh:mm:ss"); + row.reserve(6 + node.length() + ext.length() + size.length() + + modified.length() + type.length() + path.length()); + row.append('\t').append(node).append('\t').append(ext); + row.append('\t').append(size).append('\t').append(modified); + row.append('\t').append(type).append('\t').append(path); if (!isDir) m_statistics.m_bytes += it->size(); - item->setTextAlignment(Qt::AlignRight); - m_table->setItem(m_lines, TC_SIZE, item); - m_table->setItem(m_lines, TC_MODIFIED, - new QTableWidgetItem( - it->lastModified().toString("yyyy.MM.dd/hh:mm:ss"))); - } - clock_t now = clock(); - if (now > nextUpdate){ - m_table->setRowCount(m_lines); - if (m_announcer != NULL) - m_announcer->say(LOG_INFO, path); - nextUpdate = now + CLOCKS_PER_SEC; - } + m_guiQueue->pushBack(ReGuiQueueItem(ReGuiQueueItem::NewTableRow, m_table, row)); + if (m_maxHits-- < 0) + break; + } + clock_t now = clock(); + if (now > nextUpdate){ + m_guiQueue->pushBack(ReGuiQueueItem(ReGuiQueueItem::LogMessage, NULL, path)); + nextUpdate = now + CLOCKS_PER_SEC; + } } for (it2 = antiPatterns.begin(); it2 != antiPatterns.end(); ++it2){ delete *it2; } - if (depth < m_maxDepth || m_maxDepth < 0){ + if (depth < m_maxDepth || m_maxDepth < 0 && m_maxHits > 0){ entries = dir.entryInfoList( QDir::NoSymLinks | QDir::NoDotAndDotDot | QDir::AllDirs, QDir::NoSort); bool filtered = m_excludedDirs.length() > 0; @@ -173,7 +184,6 @@ void FileFinder::fillTable(const QString& path, int depth){ fillTable(path + QDir::separator() + node, depth + 1); } } - m_table->setRowCount(m_lines); } /** * Runs a file search in a second thread. @@ -187,29 +197,20 @@ void FileFinder::run() * Fills the table with the data of the filtered files of a given directory. */ void FileFinder::search(){ - if (! m_append){ - m_statistics.clear(); - m_lines = 0; - } clock_t start = clock(); - m_table->setSortingEnabled(false); - QString path = ReFileUtils::nativePath(m_baseDir); - path = ReQStringUtils::chomp(path, OS_SEPARATOR); - fillTable(path, 0); + m_statistics.clear(); + QString path = ReFileUtils::nativePath(m_baseDir); + path = ReQStringUtils::chomp(path, OS_SEPARATOR); + fillTable(path, 0); m_statistics.m_runtimeSeconds = (double) (clock() - start) / CLOCKS_PER_SEC; - if (m_announcer != NULL){ - QString msg; - msg.sprintf( - I18N::s2b(QObject::tr( - "Found: %d dir(s) and %d file(s) with %.6f MByte. Duration of the search: %.3f sec")), - m_statistics.m_dirs, m_statistics.m_files, - m_statistics.m_bytes / 1000000.0, m_statistics.m_runtimeSeconds); - m_announcer->say(LOG_INFO, msg); - } - m_table->setSortingEnabled(true); - if (m_observer != NULL) - m_observer->notify("ready"); + QString msg; + msg.sprintf( + I18N::s2b(QObject::tr( + "Found: %d dir(s) and %d file(s) with %.6f MByte. Duration of the search: %.3f sec")), + m_statistics.m_dirs, m_statistics.m_files, + m_statistics.m_bytes / 1000000.0, m_statistics.m_runtimeSeconds); + m_guiQueue->pushBack(ReGuiQueueItem(ReGuiQueueItem::ReadyMessage, NULL, msg)); } /** @@ -257,20 +258,26 @@ bool FileFinder::isValid(const QFileInfo& file){ return rc; } -void FileFinder::setAppend(bool append) +/** + * Sets the maximal hit count. + * + * @param maxHits the maximal hit count + */ +void FileFinder::setMaxHits(int maxHits) { - m_append = append; + m_maxHits = maxHits; } /** - * Sets the announcer for the summary message at the end. + * Sets the gui queue for exchanging data to the main tread. * - * @param announcer the announcer + * @param guiQueue the gui queue */ -void FileFinder::setAnnouncer(ReAnnouncer* announcer) +void FileFinder::setGuiQueue(ReGuiQueue* guiQueue) { - m_announcer = announcer; + m_guiQueue = guiQueue; } + /** * Sets the base directory. * diff --git a/appl/refind/filefinder.hpp b/appl/refind/filefinder.hpp index 8292633..0916cfe 100644 --- a/appl/refind/filefinder.hpp +++ b/appl/refind/filefinder.hpp @@ -22,6 +22,7 @@ public: FileFinder(); ~FileFinder(); public: + void clear(); void fillTable(const QString& path, int depth); void run(); void search(); @@ -30,7 +31,9 @@ public: void setBaseDir(const QString& baseDir); void setFiletypes(const QDir::Filters& filetypes); void setExcludedDirs(const QStringList& excludedDirs); + void setGuiQueue(ReGuiQueue* guiQueue); void setMaxDepth(int maxDepth); + void setMaxHits(int maxHits); void setMaxSize(const int64_t& maxSize); void setMinDepth(int minDepth); void setMinSize(const int64_t& minSize); @@ -45,7 +48,6 @@ private: bool isExcludedDir(const QString& node); bool isValid(const QFileInfo& file); private: - int m_lines; QStringList m_patterns; QStringList m_antiPatterns; int64_t m_minSize; @@ -62,9 +64,9 @@ private: TextFinder* m_textFinder; QTableWidget* m_table; Statistics m_statistics; - ReAnnouncer* m_announcer; ReObserver* m_observer; - bool m_append; + ReGuiQueue* m_guiQueue; + int m_maxHits; }; #endif // FILEFINDER_HPP diff --git a/appl/refind/mainwindow.cpp b/appl/refind/mainwindow.cpp index b911aa5..cd47be3 100644 --- a/appl/refind/mainwindow.cpp +++ b/appl/refind/mainwindow.cpp @@ -54,7 +54,9 @@ MainWindow::MainWindow(const QString& startDir, const QString& homeDir, m_storageFile(), m_contextHandlers(), m_logger(new ReMemoryLogger()), - m_finder(NULL){ + m_finder(NULL), + m_guiQueue(), + m_guiTimer(new QTimer(this)){ ui->setupUi(this); initializeHome(); m_statusMessage = new QLabel(tr("Welcome at refind")); @@ -103,12 +105,16 @@ MainWindow::MainWindow(const QString& startDir, const QString& homeDir, m_horizontalHeader = ui->tableWidget->horizontalHeader(); connect(m_horizontalHeader, SIGNAL(sectionClicked ( int ) ), this, SLOT(headerClicked ( int ) )); + connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(guiTimerUpdate())); ui->tableWidget->setColumnWidth(TC_NODE, 200); ui->tableWidget->setColumnWidth(TC_EXT, 40); ui->tableWidget->setColumnWidth(TC_SIZE, 125); ui->tableWidget->setColumnWidth(TC_MODIFIED, 175); ui->tableWidget->setColumnWidth(TC_TYPE, 75); prepareContextMenu(); + m_guiTimer->start(100); + bool active = m_guiTimer->isActive(); + active = ! active; } /** @@ -432,6 +438,37 @@ void MainWindow::fullNameToClipboard(){ } } +/** + * Callback method of the GUI timer. + */ +void MainWindow::guiTimerUpdate() +{ + int count = m_guiQueue.count(); + while(count-- > 0){ + ReGuiQueueItem item = m_guiQueue.popFront(); + if (item.m_type == ReGuiQueueItem::Undef) + break; + if (! item.apply()){ + switch (item.m_type){ + case ReGuiQueueItem::ReadyMessage: + say(LOG_INFO, item.m_value); + m_statistics = m_finder->statistics(); + ui->pushButtonSearch->setEnabled(true); + ui->pushButtonSearch2->setEnabled(true); + break; + case ReGuiQueueItem::LogMessage: + say(LOG_INFO, item.m_value); + break; + default: + say(LOG_ERROR, "unknown item type: " + QString::number(item.m_type) + + " " + item.m_value); + break; + } + + } + } +} + /** * Handle the "copy to clipboard" entry from the context menu. * @@ -636,11 +673,6 @@ void MainWindow::headerPlaceholder(){ */ ReObserver::ReturnCode MainWindow::notify(const char* message) { - if (strcmp(message, "ready") == 0){ - ui->pushButtonSearch->setEnabled(true); - ui->pushButtonSearch2->setEnabled(true); - m_statistics = m_finder->statistics(); - } return ReObserver::SUCCESS; } @@ -684,11 +716,11 @@ msgBox.exec(); } inline QString addEsc(const QString& text){ - QString rc = text; + QString rc = text; #if defined WIN32 - rc.replace("\\", "\\\\"); + rc.replace("\\", "\\\\"); #endif - return rc; + return rc; } /** @@ -698,17 +730,17 @@ inline QString addEsc(const QString& text){ */ void MainWindow::buildGlobalPlaceholders(QMap & hash){ -hash.insert("filepatterns", addEsc(ui->comboBoxFilePatterns->currentText())); -hash.insert("base", m_lastBaseDir.absolutePath()); -hash.insert("textpattern", addEsc(ui->comboBoxTextPattern->currentText())); -hash.insert("dirs", QString::number(m_statistics.m_dirs)); -hash.insert("files", QString::number(m_statistics.m_files)); -hash.insert("runtime", QString::number(m_statistics.m_runtimeSeconds, 'g', 3)); -hash.insert("bytes", QString::number(m_statistics.m_bytes)); -hash.insert("megabytes", - QString::number((double) m_statistics.m_bytes / 1000000)); -hash.insert("datetime", - QDateTime::currentDateTime().toLocalTime().toString("yyyy.MM.dd/hh:mm:ss")); + hash.insert("filepatterns", addEsc(ui->comboBoxFilePatterns->currentText())); + hash.insert("base", m_lastBaseDir.absolutePath()); + hash.insert("textpattern", addEsc(ui->comboBoxTextPattern->currentText())); + hash.insert("dirs", QString::number(m_statistics.m_dirs)); + hash.insert("files", QString::number(m_statistics.m_files)); + hash.insert("runtime", QString::number(m_statistics.m_runtimeSeconds, 'g', 3)); + hash.insert("bytes", QString::number(m_statistics.m_bytes)); + hash.insert("megabytes", + QString::number((double) m_statistics.m_bytes / 1000000)); + hash.insert("datetime", + QDateTime::currentDateTime().toLocalTime().toString("yyyy.MM.dd/hh:mm:ss")); } /** * Replaces the placeholders valid in header and footer. @@ -801,8 +833,12 @@ storage.close(); * @param finder OUT: the finder to populate */ void MainWindow::populateFinder(FileFinder& finder){ + if (! ui->checkBoxAppend->isChecked()){ + ui->tableWidget->setRowCount(0); + m_statistics.clear(); + } finder.setObserver(this); - finder.setAnnouncer(this); + finder.setGuiQueue(&this->m_guiQueue); finder.setBaseDir(comboText(ui->comboBoxDirectory)); finder.setTable(ui->tableWidget); m_lastBaseDir.cd(comboText(ui->comboBoxDirectory)); @@ -812,8 +848,8 @@ void MainWindow::populateFinder(FileFinder& finder){ finder.setYoungerThan(comboDate(ui->comboBoxYounger)); finder.setMinDepth(comboInt(ui->comboBoxMinDepth, 0)); finder.setMaxDepth(comboInt(ui->comboBoxMaxDepth, -1)); + finder.setMaxHits(comboInt(ui->comboBoxMaxHits, 0x7fffffff)); finder.setFiletypes(buildFileTypes()); - finder.setAppend(ui->checkBoxAppend->isChecked()); QStringList patterns; QString value = comboText(ui->comboBoxFilePatterns); if (!value.isEmpty()) @@ -848,6 +884,8 @@ void MainWindow::search(){ guiError(ui->comboBoxDirectory, tr("not a directory: ") + path); else{ QApplication::setOverrideCursor (QCursor(Qt::WaitCursor)); + ui->pushButtonSearch->setEnabled(false); + ui->pushButtonSearch->setEnabled(false); if (m_finder == NULL) m_finder = new FileFinder; populateFinder(*m_finder); @@ -907,7 +945,7 @@ QDir dir(path); if (dir.exists()){ dir.cdUp(); if (dir.exists()){ - path = ReFileUtils::nativePath(dir.absolutePath()); + path = ReFileUtils::nativePath(dir.absolutePath()); ui->comboBoxDirectory->setEditText(path); setInHistory(ui->comboBoxDirectory, path); } diff --git a/appl/refind/mainwindow.hpp b/appl/refind/mainwindow.hpp index d7bb211..db260f7 100644 --- a/appl/refind/mainwindow.hpp +++ b/appl/refind/mainwindow.hpp @@ -36,7 +36,7 @@ enum TableColumns { }; class FileFinder; -class MainWindow: public QMainWindow, public ReGuiValidator, public ReObserver { +class MainWindow: public QMainWindow, public ReGuiValidator, protected ReObserver{ Q_OBJECT @@ -60,6 +60,7 @@ private slots: void filePlaceholder(); void footerPlaceholder(); void fullNameToClipboard(); + void guiTimerUpdate(); void handleTableContextMenu(const QPoint& position); void headerClicked(int col); void headerPlaceholder(); @@ -107,6 +108,8 @@ private: ContextHandlerList m_contextHandlers; ReLogger* m_logger; FileFinder* m_finder; + ReGuiQueue m_guiQueue; + QTimer* m_guiTimer; }; #endif // MAINWINDOW_HPP diff --git a/appl/refind/mainwindow.ui b/appl/refind/mainwindow.ui index e666097..5889024 100644 --- a/appl/refind/mainwindow.ui +++ b/appl/refind/mainwindow.ui @@ -31,7 +31,7 @@ 16777215 - 150 + 175 @@ -44,6 +44,30 @@ + + + + Execute the search + + + &Run search + + + + :/main/icons/action_go.gif + :/main/icons/action_go.png:/main/icons/action_go.gif + + + Ctrl+F + + + true + + + true + + + @@ -57,7 +81,7 @@ - + @@ -116,35 +140,9 @@ - - - - Clears the file table - - - C&lear - - - - - - false - - - - - - - Adds the result of the next search to the table - - - Append - - - - + @@ -157,7 +155,7 @@ - + @@ -170,10 +168,7 @@ - - - - + @@ -186,7 +181,7 @@ - + <html><head/><body><p>A comma (',') separated list of filename patterns. A prefix of '-' means inversion: if a filename matches it will not be found.</p><p>Example: *.txt,*.odt</p></body></html> @@ -196,7 +191,7 @@ - + @@ -251,27 +246,16 @@ - - - - Execute the search + + + + + 125 + 16777215 + - &Run search - - - - :/main/icons/action_go.gif - :/main/icons/action_go.png:/main/icons/action_go.gif - - - Ctrl+F - - - true - - - true + Ignore case @@ -331,6 +315,16 @@ + + + + Files + + + true + + + @@ -341,26 +335,50 @@ + + + + + + Stop after: + + + + + + + true + + + + + + + + - - - - 125 - 16777215 - + + + Adds the result of the next search to the table - ignore case + Append - - + + + + Clears the file table + - Files + C&lear - - true + + + + + false @@ -486,6 +504,19 @@ + + + + + 200 + 16777215 + + + + Younger than: + + + @@ -509,8 +540,8 @@ - - + + 200 @@ -518,11 +549,42 @@ - Younger than: + Older than: + + + + + + + Max. Depth: + + + + + + + <html><head/><body><p>a comma (',') separated list of directory names not entered for the search.</p><p>Example: .git,.cache</p></body></html> + + + true + + + + + + + Min. Depth: - + + + + Excluded Dirs: + + + + &Run search @@ -534,310 +596,219 @@ - - + + + + + + + &Export + + + + + + + + + 300 + 0 + + - 200 + 16777215 + 16777215 + + + + Text at the top of the export file + + + true + + + + + + + Exports file attributes (specified in the template line) of each found files found file in a textfile or clipboard + + + &Export + + + + :/main/icons/database_save.png:/main/icons/database_save.png + + + Alt+E + + + + + + + + 50 16777215 + + Select a placeholder for the footer + - Older than: + ... - - + + - <html><head/><body><p>a comma (',') separated list of directory names not entered for the search.</p><p>Example: .git,.cache</p></body></html> + Text at the end of the export file true + + === found: ${dirs} dir(s) and ${files} file(s) with ${megabytes} MB in ${runtime} sec + - - + + - Min. Depth: + File footer: - - + + + + + 50 + 16777215 + + + + Select a placeholder for the header + - Max. Depth: + ... - + - Excluded Dirs: + File header: + + + + + + + + 50 + 16777215 + + + + Select a placeholder for the template + + + ... + + + + + + + Line template: + + + + + + + Template of a line for each file + + + true + + + ${full};${size};${modified} + + + + &Preview + + + + :/main/icons/eye.png:/main/icons/eye.png + + + + + + + + + Clipboard + + + true + + + + + + + &File: + + + false + + + + + + + Name of the export file + + + true + + + refind.result.txt + + + + + + + + 50 + 16777215 + + + + Select the export file + + + ... + + + + + - - - &Export - - - - - 515 - 106 - 85 - 29 - - - - - - - - - - 10 - 11 - 981 - 116 - - - - - - - Export file: - - - - - - - - - Template of a line for each file - - - true - - - ${full};${size};${modified} - - - - - - - - 50 - 16777215 - - - - Select a placeholder for the template - - - ... - - - - - - - - - - - &File - - - false - - - - - - - Clipboard - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Preview - - - - :/main/icons/eye.png:/main/icons/eye.png - - - - - - - - - - - Name of the export file - - - true - - - refind.result.txt - - - - - - - - 50 - 16777215 - - - - Select the export file - - - ... - - - - - - - - - Exports file attributes (specified in the template line) of each found files found file in a textfile or clipboard - - - &Export - - - - :/main/icons/database_save.png:/main/icons/database_save.png - - - Alt+E - - - - - - - File footer: - - - - - - - Line template: - - - - - - - File header: - - - - - - - - 300 - 0 - - - - - 16777215 - 16777215 - - - - Text at the top of the export file - - - true - - - - - - - Text at the end of the export file - - - true - - - === found: ${dirs} dir(s) and ${files} file(s) with ${megabytes} MB in ${runtime} sec - - - - - - - - 50 - 16777215 - - - - Select a placeholder for the header - - - ... - - - - - - - - 50 - 16777215 - - - - Select a placeholder for the footer - - - ... - - - - - - @@ -1220,7 +1191,6 @@ comboBoxDirectory pushButtonUp pushButtonDirectory - pushButtonSearch comboBoxFilePatterns checkBoxFiles checkBoxDirs @@ -1236,19 +1206,6 @@ comboBoxMinDepth comboBoxMaxDepth comboBoxExcludedDirs - pushButtonSearch2 - comboBoxTemplate - pushButtonFilePlaceholder - comboBoxHeader - pushButtonHeaderPlaceholder - comboBoxExportFile - pushButtonExportFile - comboBoxFooter - pushButtonFooterPlaceholder - radioButtonFile - radioButtonClipboard - pushButtonExport - tabWidget tableWidget diff --git a/appl/refind/refind.pro b/appl/refind/refind.pro index 619646a..16dcfad 100644 --- a/appl/refind/refind.pro +++ b/appl/refind/refind.pro @@ -30,7 +30,8 @@ SOURCES += main.cpp\ dialogfileplaceholder.cpp \ utils.cpp \ dialogoptions.cpp \ - filetablewidget.cpp + filetablewidget.cpp \ + ../../gui/ReGuiQueue.cpp HEADERS += mainwindow.hpp \ @@ -46,7 +47,8 @@ HEADERS += mainwindow.hpp \ dialogfileplaceholder.hpp \ utils.hpp \ dialogoptions.hpp \ - filetablewidget.hpp + filetablewidget.hpp \ + ../../gui/ReGuiQueue.hpp FORMS += mainwindow.ui \ diff --git a/appl/refind/utils.cpp b/appl/refind/utils.cpp index da9e65a..c0c6cb1 100644 --- a/appl/refind/utils.cpp +++ b/appl/refind/utils.cpp @@ -231,3 +231,16 @@ void Statistics::clear(){ m_bytes = 0; m_runtimeSeconds = 0; } + +/** + * Adds the result of another instance to the instance. + * + * @param source instance to add + */ +void Statistics::add(Statistics& source) +{ + m_dirs += source.m_dirs; + m_bytes += source.m_bytes; + m_files += source.m_bytes; + m_runtimeSeconds += source.m_runtimeSeconds; +} diff --git a/appl/refind/utils.hpp b/appl/refind/utils.hpp index 5b16291..d6be1f1 100644 --- a/appl/refind/utils.hpp +++ b/appl/refind/utils.hpp @@ -22,14 +22,14 @@ enum { class ContextHandler { public: enum IntrinsicType { - IT_UNDEF, IT_COPY + IT_UNDEF, IT_COPY }; enum DirMode { - DM_UNDEF, DM_TO_PARENT, DM_TO_FILE + DM_UNDEF, DM_TO_PARENT, DM_TO_FILE }; enum FileType { - FT_UNDEF, FT_FILE, FT_DIR, FT_ALL + FT_UNDEF, FT_FILE, FT_DIR, FT_ALL }; public: ContextHandler(); @@ -56,7 +56,7 @@ public: void clear(); ContextHandlerList©(const ContextHandlerList& source); QList & list(){ - return m_list; + return m_list; } void save(ReStateStorage& storage); void restore(ReStateStorage& storage); @@ -69,6 +69,7 @@ public: Statistics(); public: void clear(); + void add(Statistics& source); public: int m_dirs; int m_files; diff --git a/base/rebase.hpp b/base/rebase.hpp index 18db3d3..8c7577c 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -47,6 +47,7 @@ #include #include #include +#include typedef unsigned char uint8_t; #if !defined __linux__ @@ -65,8 +66,9 @@ typedef QString ReString; #define OS_SEPARATOR_STR "/" #define OS_2nd_SEPARATOR '\\' #define OS_2nd_SEPARATOR_STR "\\" -#define _mkdir(path) mkdir(path, -1) #define _memicmp memicmp +#define _mkdir(path) mkdir(path, -1) +#define _rmdir rmdir #else #define _strcasecmp _stricmp #define OS_SEPARATOR '\\' @@ -147,7 +149,7 @@ inline int hexToInt(char hex, int defaultValue = -1){ * @param value the value to round */ inline int roundInt(double value) { - return (int) value < 0.0 ? ceil(value - 0.5) : floor(value + 0.5); + return (int) value < 0.0 ? ceil(value - 0.5) : floor(value + 0.5); } /** An observer can be informed about state changes. * Pure abstract class. diff --git a/gui/ReGuiQueue.cpp b/gui/ReGuiQueue.cpp new file mode 100644 index 0000000..8c61576 --- /dev/null +++ b/gui/ReGuiQueue.cpp @@ -0,0 +1,97 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + +#include "base/rebase.hpp" +#include "gui/regui.hpp" + +/** + * Constructor. + */ +ReGuiQueue::ReGuiQueue() : + m_locker() +{ +} + +/** + * Adds an entry at the end of the the queue. + * + * This method can be used by all threads. + * + * @param item the item to add + */ +void ReGuiQueue::pushBack(const ReGuiQueueItem& item) +{ + m_locker.lock(); + append(item); + m_locker.unlock(); +} + +/** + * Returns the number of elements. + * + * This method should be called only by the master thread. + * + * @return the number of elements + */ +int ReGuiQueue::count() const +{ + // no locking is necessary: removing is done only by the same thread + return size(); +} + +/** + * Returns the first element and delete it from the queue. + * + * This method should be called only by the master thread. + * + * @return the first elements + */ +ReGuiQueueItem ReGuiQueue::popFront() +{ + m_locker.lock(); + ReGuiQueueItem rc = takeFirst(); + m_locker.unlock(); + return rc; +} + +/** + * Takes the info from the instance and put it into the widget. + * + * This method should only used by the master thread. + * + * @return true: the info could be put into the widget
+ * false: nothing is done + */ +bool ReGuiQueueItem::apply() const +{ + bool rc = m_widget != NULL; + if (rc){ + switch(m_type){ + case LabelText: + reinterpret_cast(m_widget)->setText(m_value); + break; + case NewTableRow: + { + QChar separator = m_value.at(0); + QStringList list = m_value.mid(1).split(separator); + QTableWidget* table = reinterpret_cast(m_widget); + int rowCount = table->rowCount(); + table->setRowCount(rowCount + 1); + int cols = min(list.size(), table->columnCount()); + for (int ix = 0; ix < cols; ix++){ + table->setItem(rowCount, ix, new QTableWidgetItem(list.at(ix))); + } + break; + } + default: + rc = false; + break; + } + } + return rc; +} diff --git a/gui/ReGuiQueue.hpp b/gui/ReGuiQueue.hpp new file mode 100644 index 0000000..4ae6587 --- /dev/null +++ b/gui/ReGuiQueue.hpp @@ -0,0 +1,82 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + +#ifndef REGUIQUEUE_HPP +#define REGUIQUEUE_HPP + +class ReGuiQueueItem { +public: + enum WidgetType { + Undef, LabelText, NewTableRow, LogMessage, ReadyMessage, + UserDefined1, UserDefined2 + }; + +public: + /** Constructor. + */ + ReGuiQueueItem(): + m_type(Undef), + m_widget(NULL), + m_value(){ + } + + /** Constructor. + * @param type widget type + * @param widget NULL or the widget + * @param value the value to set + */ + ReGuiQueueItem(WidgetType type, QWidget* widget, const QString value) : + m_type(type), + m_widget(widget), + m_value(value){ + } + /** Copy constructor. + * @param source the source to copy + */ + ReGuiQueueItem(const ReGuiQueueItem& source) : + m_type(source.m_type), + m_widget(source.m_widget), + m_value(source.m_value){ + } + /** Assign operator. + * @param source the source to copy + * @return the instance + */ + ReGuiQueueItem& operator = (const ReGuiQueueItem& source){ + m_type = source.m_type; + m_widget = source.m_widget; + m_value = source.m_value; + return *this; + } +public: + bool apply() const; +public: + WidgetType m_type; + QWidget* m_widget; + QString m_value; +}; + +/** + * Queue for exchange gui data for the main thread. + * + * Qt allows manipulating GUI elements only in the main thread. + * This queue allows the exchange of information from other threads. + */ +class ReGuiQueue : protected QVector +{ +public: + ReGuiQueue(); +public: + int count() const; + ReGuiQueueItem popFront(); + void pushBack(const ReGuiQueueItem& item); +protected: + QMutex m_locker; +}; + +#endif // REGUIQUEUE_HPP diff --git a/gui/regui.hpp b/gui/regui.hpp index 134bd06..b459c51 100644 --- a/gui/regui.hpp +++ b/gui/regui.hpp @@ -13,6 +13,9 @@ #define REGUI_HPP #include +#include +#include +#include "gui/ReGuiQueue.hpp" #include "gui/ReStateStorage.hpp" #include "gui/ReGuiValidator.hpp" #include "gui/ReEdit.hpp" -- 2.39.5