QMutex BackupEngine::m_mutex;
QChar BackupEngine::m_separator = '\t';
QString BackupEngine::m_separatorString = "\t";
+QStringList ChecksumTask::m_checksumInfo;
+bool ChecksumTask::m_sourceProcessingReady = false;
/**
* Constructor.
/**
* Constructor.
*
+ * @param compareWithTarget <code>false</code>: all files will be found<br>
+ * otherwise: only not existing or newer files will
+ * be found
* @param name name of the task
* @param filePatterns only files which match the patterns will be found
* @param dirPatterns only subdirectories which matches the patterns will be entered
* @param targetDir the base target directory
* @param mainWindow the GUI module, the parent
*/
-SearchTask::SearchTask(const QString& name,
+SearchTask::SearchTask(bool compareWithTarget, const QString& name,
const QString& filePatterns, const QString& dirPatterns,
const QStringList& sourceDirs, const QString& targetDir,
MainWindow* mainWindow) :
BackupEngine(name, sourceDirs, targetDir, mainWindow),
m_fileMatcher(filePatterns),
- m_dirMatcher(dirPatterns)
+ m_dirMatcher(dirPatterns),
+ m_compareWithTarget(compareWithTarget)
{
-
}
/**
QString targetDir, sourceDir;
for (int ix = 0; ix < m_sourceDirs.size(); ix++){
sourceDir = m_sourceDirs.at(ix);
- targetDir = m_targetDirs.at(ix) + ReFileUtils::nodeOf(sourceDir);
- processOneDirectory(sourceDir, targetDir, ix);
+ if (m_compareWithTarget)
+ targetDir = m_targetDirs.at(ix) + ReFileUtils::nodeOf(sourceDir);
+ searchOneDirectory(sourceDir, targetDir, ix);
}
m_searchReady = true;
m_mainWindow->externalLog(tr(
- "Search finished: to copy: %1 with %2 matching: %3 total: %4 "
+ "Search finished: to process: %1 with %2 matching: %3 total: %4 "
"subdirs: %5 runtime: %6")
.arg(m_hotFiles)
.arg(ReQStringUtils::readableSize(m_hotBytes))
* it is newer or has another size
* @param index the index of the base directory in m_sourceDirs
*/
-void SearchTask::processOneDirectory(const QString& source,
+void SearchTask::searchOneDirectory(const QString& source,
const QString& target, int index){
QDirIterator it(source);
- QString prefix;
QString info, node;
int lengthBase = m_sourceDirs.at(index).length();
+ assert(index < 0x7fff);
+ QString prefix;
+ m_mutex.lock();
+ m_totalDirs++;
+ m_mutex.unlock();
if (source.length() > lengthBase){
prefix = QChar(1 + index) + source.mid(lengthBase) + OS_SEPARATOR_STR
+ m_separator;
} else {
qint64 diff = 0;
bool doCopy = false;
- if (target.isEmpty())
+ if (! m_compareWithTarget)
+ doCopy = true;
+ else if (target.isEmpty())
doCopy = true;
else {
QFileInfo trg(target + it.fileName());
}
}
if (doCopy){
- assert(index < 0x7fff);
info = prefix + it.fileName();
}
m_mutex.lock();
subTarget.clear();
else
subTarget += OS_SEPARATOR_STR;
- processOneDirectory(it2.filePath(), subTarget, index);
- m_mutex.lock();
- m_totalDirs++;
- m_mutex.unlock();
}
+ searchOneDirectory(it2.filePath(), subTarget, index);
}
}
}
const QStringList& sourceDirs, const QString& targetDir,
MainWindow* mainWindow) :
BackupEngine(name, sourceDirs, targetDir, mainWindow),
- m_lastRelPath()
+ m_lastRelPath(),
+ m_buffer()
{
}
bool isFile;
if (! ReFileUtils::isDirectory(targetDir, &isFile)){
if (isFile){
- if (_unlink(I18N::s2b(targetDir).constData()) != 0)
+ if (_unlink(I18N::s2b(targetDir).constData()) != 0)
error(tr("cannot remove file (for making a directory (%1): %2")
.arg(errno).arg(targetDir));
}
.arg(ReQStringUtils::readableDuration(estimated)));
}
}
- m_mainWindow->externalTaskFinished(tr("backup complete after %1. Errors: %2")
- .arg(ReQStringUtils::readableDuration(
- QDateTime::currentMSecsSinceEpoch() - start))
- .arg(m_mainWindow->errors()));
+ m_mainWindow->externalTaskFinished(tr("backup complete after %1. Errors: %2")
+ .arg(ReQStringUtils::readableDuration(
+ QDateTime::currentMSecsSinceEpoch() - start))
+ .arg(m_mainWindow->errors()));
+}
+
+/**
+ * Constructor.
+ *
+ * @param name name of the task
+ * @param sourceDirs the list of source directories to inspect
+ * @param targetDir the base of the target directories
+ * @param mainWindow the GUI module
+ */
+ChecksumTask::ChecksumTask(const QString& name,
+ const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow) :
+ BackupEngine(name, sourceDirs, targetDir, mainWindow),
+ m_lastRelPath(),
+ m_buffer()
+{
+ m_buffer.resize(1024*1024);
+}
+
+/**
+ * Calculates the checksum of a given file.
+ *
+ * @param isSource <code>true</code>: the file is taken from the source<br>
+ * <code>true</code>: the file is taken from the target
+ * @param index index in source/target dirs (dependin on <code>isSource</code>)
+ * @param relpath the relative path from the base (source or target)
+ * @param node the node of the file (without path)
+ * @return "": checksum could not be calculated<br>
+ * otherwise: the checksum of the file
+ */
+QByteArray ChecksumTask::buildChecksum(bool isSource, int index,
+ const QString& relpath, const QString& node)
+{
+ QString filename;
+ if (isSource)
+ filename = m_sourceDirs.at(index) + relpath + node;
+ else
+ filename = m_targetDirs.at(index) + relpath + node;
+ qint64 size = 0;
+ QByteArray rc = ReFileUtils::buildChecksum(filename, m_buffer, &size).toHex();
+ m_mutex.lock();
+ m_processedFiles++;
+ m_processedBytes += size;
+ m_mutex.unlock();
+ if (rc.isEmpty()){
+ error(QObject::tr("cannot build checksum: %1").arg(filename) );
+ } else {
+ m_mainWindow->addToFileList(QString(rc) + " " + filename);
+ }
+ return rc;
}
+
+/**
+ * Constructor.
+ *
+ * @param name name of the task
+ * @param sourceDirs the list of source directories to inspect
+ * @param targetDir the base of the target directories
+ * @param mainWindow the GUI module
+ */
+ChecksumOfSourceTask::ChecksumOfSourceTask(const QString& name,
+ const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow) :
+ ChecksumTask(name, sourceDirs, targetDir, mainWindow)
+{
+}
+
+/**
+ * Calculats the checksum of source files.
+ */
+void ChecksumOfSourceTask::run()
+{
+ qint64 start = QDateTime::currentMSecsSinceEpoch();
+ QString relPath, node;
+ QString info;
+ int count = 0;
+ while (true){
+ m_mutex.lock();
+ if (m_files.size() == 0)
+ info.clear();
+ else{
+ info = m_files.first();
+ m_files.removeFirst();
+ }
+ m_mutex.unlock();
+ if (info.isEmpty()){
+ if (m_searchReady)
+ break;
+ else
+ QThread::msleep(50);
+ } else {
+ int index = int(info.at(0).unicode()) - 1;
+ int pos = info.indexOf(m_separator, 1);
+ if (pos == 1)
+ relPath.clear();
+ else
+ relPath = info.mid(1, pos - 1);
+ node = info.mid(pos + 1);
+ QByteArray checksum = buildChecksum(true, index, relPath, node);
+ count++;
+ if (! checksum.isEmpty()){
+ QString info = QChar(1 + index) + relPath + m_separator
+ + node + m_separatorString + checksum;
+ m_mutex.lock();
+ m_checksumInfo.append(info);
+ m_mutex.unlock();
+ }
+ }
+ }
+ m_sourceProcessingReady = true;
+ qint64 now = QDateTime::currentMSecsSinceEpoch();
+ m_mainWindow->externalTaskFinished(tr("Building source checksum complete after %1. Processed: %2")
+ .arg(ReQStringUtils::readableDuration(now - start))
+ .arg(count));
+}
+
+/**
+ * Constructor.
+ *
+ * @param name name of the task
+ * @param sourceDirs the list of source directories to inspect
+ * @param targetDir the base of the target directories
+ * @param mainWindow the GUI module
+ */
+ChecksumOfTargetTask::ChecksumOfTargetTask(const QString& name,
+ const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow) :
+ ChecksumTask(name, sourceDirs, targetDir, mainWindow)
+{
+
+}
+
+/**
+ * Calculats the checksum of target files.
+ */
+void ChecksumOfTargetTask::run()
+{
+ qint64 start = QDateTime::currentMSecsSinceEpoch();
+ QString relPath, node;
+ qint64 now = 0;
+ QString info;
+ int count = 0;
+ while (true){
+ m_mutex.lock();
+ if (m_checksumInfo.size() == 0)
+ info.clear();
+ else{
+ info = m_checksumInfo.first();
+ m_checksumInfo.removeFirst();
+ }
+ m_mutex.unlock();
+ if (info.isEmpty()){
+ if (m_sourceProcessingReady)
+ break;
+ else
+ QThread::msleep(50);
+ } else {
+ int index = int(info.at(0).unicode()) - 1;
+ int pos = info.indexOf(m_separator, 1);
+ if (pos == 1)
+ relPath.clear();
+ else
+ relPath = info.mid(1, pos - 1);
+ int pos2 = info.indexOf(m_separator, pos + 1);
+ node = info.mid(pos + 1, pos2 - pos - 1);
+ QString sourceChecksum = info.mid(pos2 + 1);
+
+ QByteArray checksum = buildChecksum(false, index, relPath, node);
+ count++;
+ if (! checksum.isEmpty()){
+ if (checksum != sourceChecksum)
+ error(QObject::tr("checksum differs: ") + relPath + node
+ + " [" + sourceChecksum + "/" + checksum + "]");
+ }
+ now = QDateTime::currentMSecsSinceEpoch();
+ qint64 estimated = (now - start) * m_hotBytes * 2 / max(1LL, m_processedBytes);
+ m_mainWindow->externalAppend(ReGuiQueueItem::StatusLine, NULL,
+ tr("%1 of %2 (%3 of %4) %5 MB/sec Remaining: %6 of %7")
+ .arg(m_processedFiles).arg(m_hotFiles * 2)
+ .arg(ReQStringUtils::readableSize(m_processedBytes))
+ .arg(ReQStringUtils::readableSize(m_hotBytes * 2))
+ .arg(m_processedBytes / 1024.0 / 1024 / (now - start) * 1000, 0, 'f', 3)
+ .arg(ReQStringUtils::readableDuration(estimated - (now - start)))
+ .arg(ReQStringUtils::readableDuration(estimated)));
+
+ }
+ }
+ now = QDateTime::currentMSecsSinceEpoch();
+ m_mainWindow->externalTaskFinished(tr("Building target checksums complete after %1. Processed: %2 Errors: %3")
+ .arg(ReQStringUtils::readableDuration(now - start))
+ .arg(count)
+ .arg(m_mainWindow->errors()));
+}
+
+
#define BACKUPPROCESSOR_HPP
+/**
+ * Abstract base class of executing backup and related tasks.
+ */
class BackupEngine : public QThread
{
public:
QString m_name;
public:
static bool m_shouldStop;
+ /// Entry: <index_of_source_dir><relative_path>TAB<node>
static QStringList m_files;
static qint64 m_hotBytes;
static int m_processedFiles;
static QString m_separatorString;
};
-class SearchTask : public BackupEngine
+/**
+ * Reads filenames from the file list and copies the files from source to target.
+ */
+class BackupTask : public BackupEngine
{
public:
- SearchTask(const QString& name,
- const QString& filePatterns, const QString& dirPatterns,
- const QStringList& sourceDirs, const QString& targetDir,
+ BackupTask(const QString& name, const QStringList& sourceDirs, const QString& targetDir,
MainWindow* mainWindow);
public:
virtual void run();
+protected:
+ void copyFile(int index, const QString& relpath,
+ const QString& node);
private:
- QString m_filePatterns;
- QString m_dirPatterns;
- ReIncludeExcludeMatcher m_fileMatcher;
- ReIncludeExcludeMatcher m_dirMatcher;
- void processOneDirectory(const QString& source, const QString& target,
- int index);
+ QString m_lastRelPath;
+ QByteArray m_buffer;
};
-class BackupTask : public BackupEngine
+/**
+ * Abstract base class of the checksum test classes.
+ */
+class ChecksumTask : public BackupEngine
{
public:
- BackupTask(const QString& name, const QStringList& sourceDirs, const QString& targetDir,
+ ChecksumTask(const QString& name, const QStringList& sourceDirs, const QString& targetDir,
MainWindow* mainWindow);
public:
- virtual void run();
+ virtual void run() = 0;
protected:
- void copyFile(int index, const QString& relpath,
+ QByteArray buildChecksum( bool isSource, int index, const QString& relpath,
const QString& node);
-private:
+protected:
QString m_lastRelPath;
QByteArray m_buffer;
+protected:
+ /// Entry: <index_of_target_dir><relative_path>TAB<node>TAB<checksum>
+ static QStringList m_checksumInfo;
+public:
+ static bool m_sourceProcessingReady;
+};
+
+/**
+ Handles the checksum activities for the source files.
+
+ * Reads from the file list, calculates the checksum of the source file and
+ * writes an entry into the checksum file list
+ */
+class ChecksumOfSourceTask : public ChecksumTask
+{
+public:
+ ChecksumOfSourceTask(const QString& name, const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow);
+public:
+ virtual void run();
};
+/**
+ Handles the checksum activities for the target files.
+
+ * Reads from the checksum file list, calculates the checksum of the target file
+ * and compares it with the checksum of the source file.
+ */
+class ChecksumOfTargetTask : public ChecksumTask
+{
+public:
+ ChecksumOfTargetTask(const QString& name, const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow);
+public:
+ virtual void run();
+};
+
+/**
+ * Searches the files matching the file patterns and writes them into the file list.
+ */
+class SearchTask : public BackupEngine
+{
+public:
+ SearchTask(bool compareWithTarget, const QString& name,
+ const QString& filePatterns, const QString& dirPatterns,
+ const QStringList& sourceDirs, const QString& targetDir,
+ MainWindow* mainWindow);
+public:
+ virtual void run();
+private:
+ QString m_filePatterns;
+ QString m_dirPatterns;
+ ReIncludeExcludeMatcher m_fileMatcher;
+ ReIncludeExcludeMatcher m_dirMatcher;
+ void searchOneDirectory(const QString& source, const QString& target,
+ int index);
+private:
+ bool m_compareWithTarget;
+};
+
+
#endif // BACKUPPROCESSOR_HPP
#include "aboutdialog.hpp"
#include <QFileDialog>
-const QString VERSION("2016.01.30");
+const QString VERSION("2016.01.31");
/**
* Constructor.
m_lastSource(),
m_searchTask(NULL),
m_backupTask(NULL),
+ m_checksumOfSourceTask(NULL),
+ m_checksumOfTargetTask(NULL),
m_errors(0)
{
ui->setupUi(this);
startStop(false);
connect(ui->actionStart, SIGNAL(triggered()), this,
SLOT(onStart()));
+ connect(ui->actionChecksums, SIGNAL(triggered()), this,
+ SLOT(onChecksums()));
connect(ui->actionStop, SIGNAL(triggered()), this,
SLOT(onStop()));
connect(ui->pushButtonBackup, SIGNAL(clicked()), this, SLOT(onStart()));
+ connect(ui->pushButtonChecksum, SIGNAL(clicked()), this, SLOT(onChecksums()));
connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(onStop()));
connect(ui->pushButtonAddItem, SIGNAL(clicked()), this, SLOT(onAddItem()));
connect(ui->pushButtonDeleteItem, SIGNAL(clicked()), this, SLOT(onDeleteItem()));
/**
* Calles at the program's end.
*/
-void MainWindow::aboutToQuit()
+void MainWindow::onAboutToQuit()
{
}
/**
* Set GUI elements from the queue when the GUI timer is triggered.
*/
-void MainWindow::guiTimerUpdate()
+void MainWindow::onGuiTimerUpdate()
{
int count = m_guiQueue.count();
while(count-- > 0){
}
}
+/**
+ * Common initializations for all task starts.
+ */
+void MainWindow::initializeStart(){
+ BackupEngine::m_searchReady = false;
+ BackupEngine::m_hotBytes = 0;
+ BackupEngine::m_hotFiles = 0;
+ BackupEngine::m_matchedFiles = 0;
+ BackupEngine::m_totalDirs = 0;
+ BackupEngine::m_totalFiles = 0;
+ BackupEngine::m_processedFiles = 0;
+ BackupEngine::m_processedBytes = 0;
+ ChecksumTask::m_sourceProcessingReady = false;
+ m_errors = 0;
+ startStop(true);
+}
+
/**
* @brief Logs a message
*
}
}
+
+/**
+ * Starts the backup.
+ */
+void MainWindow::onChecksums(){
+ int row = ui->tableWidget->currentRow();
+ if (row < 0){
+ say(LOG_ERROR, tr("no backup item selected"));
+ } else {
+ BackupItem& item = m_configuration.items()[row];
+ QString target = BackupUtils::findTarget(item, &m_logger);
+ if (target.isEmpty()){
+ say(LOG_ERROR, tr("Target not available"));
+ } else {
+ ReQStringUtils::ensureLastChar(target, OS_SEPARATOR);
+ initializeStart();
+ writeTargetConfiguration(item, target);
+ delete m_searchTask;
+ m_searchTask = new SearchTask(false, item.m_name,
+ item.m_filePatterns, item.m_dirPatterns,
+ item.m_sources, target, this);
+ m_searchTask->start();
+ delete m_checksumOfSourceTask;
+ m_checksumOfSourceTask = new ChecksumOfSourceTask(item.m_name,
+ item.m_sources, target, this);
+ m_checksumOfSourceTask->start();
+ delete m_checksumOfTargetTask;
+ m_checksumOfTargetTask = new ChecksumOfTargetTask(item.m_name,
+ item.m_sources, target, this);
+ m_checksumOfTargetTask->start();
+ }
+ }
+}
+
/**
* Handles the push of the button "select directory".
*/
say(LOG_ERROR, tr("no backup item selected"));
} else {
BackupItem& item = m_configuration.items()[row];
- BackupEngine::m_searchReady = false;
- BackupEngine::m_hotBytes = 0;
- BackupEngine::m_hotFiles = 0;
- BackupEngine::m_matchedFiles = 0;
- BackupEngine::m_totalDirs = 0;
- BackupEngine::m_totalFiles = 0;
- BackupEngine::m_processedFiles = 0;
- BackupEngine::m_processedBytes = 0;
- m_errors = 0;
QString target = BackupUtils::findTarget(item, &m_logger);
if (target.isEmpty()){
say(LOG_ERROR, tr("Target not available"));
} else {
ReQStringUtils::ensureLastChar(target, OS_SEPARATOR);
writeTargetConfiguration(item, target);
- startStop(true);
+ initializeStart();
delete m_searchTask;
- m_searchTask = new SearchTask(item.m_name,
+ m_searchTask = new SearchTask(true, item.m_name,
item.m_filePatterns, item.m_dirPatterns,
item.m_sources, target, this);
m_searchTask->start();
ui->actionStop->setEnabled(isStart);
ui->pushButtonBackup->setEnabled(! isStart);
ui->pushButtonStop->setEnabled(isStart);
+ ui->pushButtonChecksum->setEnabled(! isStart);
+ ui->actionChecksums->setEnabled(! isStart);
}
void restoreState();
void saveState();
+public slots:
private:
QString extractTarget(const QString& dir);
+ void initializeStart();
void writeTargetConfiguration(BackupItem& item, const QString& target);
private slots:
- virtual void aboutToQuit();
- virtual void guiTimerUpdate();
void onAbout();
+ virtual void onAboutToQuit();
void onAddItem();
void onAddSource();
+ void onChecksums();
void onClearFileList();
void onClearErrorList();
void onClearLog();
void onCurrentChanged(const QModelIndex& current, const QModelIndex& previous);
void onDeleteItem();
void onDeleteSource();
+ virtual void onGuiTimerUpdate();
void onSaveConfig();
void onStart();
void onSelectionChanged(const QItemSelection& prior, const QItemSelection& later);
QString m_lastSource;
SearchTask* m_searchTask;
BackupTask* m_backupTask;
+ ChecksumOfSourceTask* m_checksumOfSourceTask;
+ ChecksumOfTargetTask* m_checksumOfTargetTask;
int m_errors;
};
</property>
</spacer>
</item>
+ <item>
+ <widget class="QPushButton" name="pushButtonChecksum">
+ <property name="minimumSize">
+ <size>
+ <width>125</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Calculates checksums for source and target files and reports differences</string>
+ </property>
+ <property name="text">
+ <string>Checksums</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
</layout>
</property>
<addaction name="actionStart"/>
<addaction name="actionStop"/>
+ <addaction name="actionChecksums"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
</action>
<action name="actionStop">
<property name="text">
- <string>Stop backup</string>
+ <string>Stop</string>
</property>
</action>
<action name="actionAbout">
<string>About</string>
</property>
</action>
+ <action name="actionChecksums">
+ <property name="text">
+ <string>Checksums</string>
+ </property>
+ <property name="toolTip">
+ <string>Calculates checksums for source and target files and reports differences</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
*/
#include "base/rebase.hpp"
+#include <QCryptographicHash>
+
enum {
LOC_DELETE_TREE_1 = LOC_FIRST_OF(LOC_FILE_UTILS), // 12501
LOC_DELETE_TREE_2, // 12502
m_fileSizes(0L) {
}
+/**
+ * Builds a checksum of the given file.
+ *
+ * @param filename the name of the file to process
+ * @param buffer OUT: buffer for reading the files
+ * @param sizes OUT: size of the file content. May be NULL
+ * @return "": the file could not be read completely<br>
+ * otherwise: the checksum
+ */
+QByteArray ReFileUtils::buildChecksum(const char* filename, QByteArray& buffer,
+ qint64* size)
+{
+ if (buffer.capacity() < 0x10000)
+ buffer.reserve(0x10000);
+ // round it down to a multiple of the checksum size:
+ int blocksize = buffer.capacity() / 128 * 128;
+ buffer.resize(blocksize);
+ qint64 sumBytes = 0;
+ QByteArray rc;
+ FILE* fp = fopen(filename, "rb");
+ if (fp != NULL){
+ int bytesRead = 0;
+ char* bufferPointer = buffer.data();
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ while( (bytesRead = fread(bufferPointer, 1, blocksize, fp)) > 0){
+ hash.addData(bufferPointer, bytesRead);
+ sumBytes += bytesRead;
+ }
+ rc = hash.result();
+ fclose(fp);
+ if (size != NULL)
+ *size = sumBytes;
+ }
+ return rc;
+}
/** Normalizes a file path.
*
if (permissions.testFlag(QFile::ExeOther))
rc |= S_IXOTH;
#elif defined _WIN32
- if (permissions.testFlag(QFile::ReadOwner) || permissions.testFlag(QFile::ReadOther))
- rc |= _S_IREAD;
- if (permissions.testFlag(QFile::ReadOwner) ||permissions.testFlag(QFile::WriteOther))
- rc |= _S_IWRITE;
+ if (permissions.testFlag(QFile::ReadOwner) || permissions.testFlag(QFile::ReadOther))
+ rc |= _S_IREAD;
+ if (permissions.testFlag(QFile::ReadOwner) ||permissions.testFlag(QFile::WriteOther))
+ rc |= _S_IWRITE;
#endif
return rc;
}
else {
const char* end;
const char* start = path;
- rc = true;
- dir.clear();
+ rc = true;
+ dir.clear();
while (rc && (end = strchr(start, OS_SEPARATOR)) != NULL) {
if (end == path) {
start++;
dir.append(start, end - start);
start = end + 1;
#if defined _WIN32
- if (dir.length() == 2 && dir.at(1) == ':'){
- dir.append(OS_SEPARATOR);
+ if (dir.length() == 2 && dir.at(1) == ':'){
+ dir.append(OS_SEPARATOR);
continue;
- }
+ }
#endif
rc = makeDir(dir.constData(), logger);
dir += OS_SEPARATOR;
bool ReFileUtils::setPermissions(const char* filename,
QFile::Permissions permissions, ReLogger* logger) {
bool rc = true;
- if (chmod(filename, nativePermissions(permissions)) != 0){
+ if (chmod(filename, nativePermissions(permissions)) != 0){
if (logger != NULL)
logger->logv(LOG_ERROR, LOC_SET_TIMES_1,
"cannot change permissions (%d): $s", errno, filename);
*/
class ReFileUtils {
public:
- static bool deleteTree(const QString& path, bool withBase,
- ReLogger* logger = NULL);
+ static QByteArray buildChecksum(const char* filename, QByteArray& buffer,
+ qint64* size = NULL);
+ /**
+ * Builds a checksum of the given file.
+ *
+ * @param filename the name of the file to process
+ * @param buffer OUT: buffer for reading the files
+ * @param sizes OUT: size of the file content. May be NULL
+ * @return "": the file could not be read completely<br>
+ * otherwise: the checksum
+ */
+ inline static QByteArray buildChecksum(const QString& filename,
+ QByteArray& buffer, qint64* size = NULL){
+ return buildChecksum(I18N::s2b(filename).constData(), buffer, size);
+ }
+
static QByteArray cleanPath(const char* path);
static QString cleanPath(const QString& path);
static QString copy(const QString& source, const QString& target,
const QFileInfo* sourceInfo, QByteArray& buffer);
+ static bool deleteTree(const QString& path, bool withBase,
+ ReLogger* logger = NULL);
static QString extensionOf(const QString& filename);
static QByteArray extensionOf(const char* filename);
static QStringList findRootDirs();
/**
* Callback method at the application's end.
*/
-void ReGuiApplication::aboutToQuit()
+void ReGuiApplication::onAboutToQuit()
{
m_logger.log(LOG_INFO, LOC_QUIT_1, "end");
}
QString ReGuiApplication::buildHomeDir(QString homeDirBase, const QString& node){
QString homeDir;
if (homeDirBase.isEmpty()){
- homeDir = ReFileUtils::nativePath(QDir::home().absoluteFilePath(node));
+ homeDir = ReFileUtils::nativePath(QDir::home().absoluteFilePath(node));
} else if (ReFileUtils::isRootDir(homeDirBase.toLatin1().constData())){
homeDir = homeDirBase + node;
}
void ReGuiApplication::initializeGuiElements(){
QCoreApplication* app = QCoreApplication::instance();
QObject::connect(app, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
- connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(guiTimerUpdate()));
+ connect(m_guiTimer, SIGNAL(timeout()), this, SLOT(onGuiTimerUpdate()));
m_guiTimer->start(100);
statusBar()->addWidget(m_statusMessage);
}
/**
* Callback method called when the application is closed.
*/
- void aboutToQuit();
+ virtual void onAboutToQuit();
public:
const QByteArray& applicationName() const;
QString fileOfHome(const QString& node);
/**
* Reads the <code>m_guiQueue</code>.
*/
- virtual void guiTimerUpdate() = 0;
+ virtual void onGuiTimerUpdate() = 0;
protected:
QByteArray m_applicationName;
/// the base directory for resources of the program like configuration file.