summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:08:06 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:08:06 +0200
commitfbe76102e941b9f1edaf236788e42678f05fdf9a (patch)
treef5f538316019fa89be8dc478103490c3a826f3ac /library
parent3.8 (diff)
downloadFreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.tar.gz
FreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.tar.bz2
FreeFileSync-fbe76102e941b9f1edaf236788e42678f05fdf9a.zip
3.9
Diffstat (limited to 'library')
-rw-r--r--library/binary.cpp8
-rw-r--r--library/binary.h4
-rw-r--r--library/custom_grid.cpp (renamed from library/CustomGrid.cpp)34
-rw-r--r--library/custom_grid.h (renamed from library/CustomGrid.h)22
-rw-r--r--library/db_file.cpp (renamed from library/dbFile.cpp)84
-rw-r--r--library/db_file.h (renamed from library/dbFile.h)4
-rw-r--r--library/detect_renaming.cpp (renamed from library/detectRenaming.cpp)2
-rw-r--r--library/detect_renaming.h (renamed from library/detectRenaming.h)6
-rw-r--r--library/dir_lock.cpp448
-rw-r--r--library/dir_lock.h35
-rw-r--r--library/error_log.cpp (renamed from library/errorLogging.cpp)4
-rw-r--r--library/error_log.h (renamed from library/errorLogging.h)2
-rw-r--r--library/filter.cpp38
-rw-r--r--library/filter.h2
-rw-r--r--library/icon_buffer.cpp (renamed from library/iconBuffer.cpp)163
-rw-r--r--library/icon_buffer.h (renamed from library/iconBuffer.h)11
-rw-r--r--library/pch.h9
-rw-r--r--library/process_xml.cpp (renamed from library/processXml.cpp)270
-rw-r--r--library/process_xml.h (renamed from library/processXml.h)48
-rw-r--r--library/resources.cpp10
-rw-r--r--library/soft_filter.cpp (renamed from library/softFilter.cpp)2
-rw-r--r--library/soft_filter.h (renamed from library/softFilter.h)4
-rw-r--r--library/statistics.cpp42
-rw-r--r--library/statistics.h2
-rw-r--r--library/status_handler.cpp (renamed from library/statusHandler.cpp)2
-rw-r--r--library/status_handler.h (renamed from library/statusHandler.h)0
26 files changed, 926 insertions, 330 deletions
diff --git a/library/binary.cpp b/library/binary.cpp
index 8b8fd2ec..d4d35e92 100644
--- a/library/binary.cpp
+++ b/library/binary.cpp
@@ -5,7 +5,7 @@
// **************************************************************************
//
#include "binary.h"
-#include "../shared/fileIO.h"
+#include "../shared/file_io.h"
#include <vector>
#include <wx/stopwatch.h>
@@ -13,7 +13,7 @@
inline
void setMinSize(std::vector<char>& buffer, size_t minSize)
{
- if (buffer.size() < minSize) //this is similar to reserve(), but be need a "properly initialized" array here
+ if (buffer.size() < minSize) //this is similar to reserve(), but we need a "properly initialized" array here
buffer.resize(minSize);
}
@@ -66,7 +66,7 @@ private:
}
-bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback)
+bool ffs3::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback)
{
FileInput file1(filename1); //throw FileError()
FileInput file2(filename2); //throw FileError()
@@ -124,7 +124,7 @@ bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring&
}
while (!file1.eof());
- if (!file1.eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...)
+ if (!file2.eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...)
return false;
return true;
diff --git a/library/binary.h b/library/binary.h
index e33e46bf..bf477116 100644
--- a/library/binary.h
+++ b/library/binary.h
@@ -9,9 +9,9 @@
#include "../shared/zstring.h"
#include <wx/longlong.h>
-#include "../shared/fileError.h"
+#include "../shared/file_error.h"
-namespace FreeFileSync
+namespace ffs3
{
//callback functionality for status updates while comparing
diff --git a/library/CustomGrid.cpp b/library/custom_grid.cpp
index a9846f74..2537f529 100644
--- a/library/CustomGrid.cpp
+++ b/library/custom_grid.cpp
@@ -4,31 +4,31 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "customGrid.h"
-#include "../shared/systemConstants.h"
+#include "custom_grid.h"
+#include "../shared/system_constants.h"
#include "resources.h"
#include <wx/dc.h>
#include "../shared/util.h"
-#include "../shared/stringConv.h"
+#include "../shared/string_conv.h"
#include "resources.h"
#include <typeinfo>
-#include "../ui/gridView.h"
+#include "../ui/grid_view.h"
#include "../synchronization.h"
-#include "../shared/customTooltip.h"
+#include "../shared/custom_tooltip.h"
#include <wx/dcclient.h>
-#include "iconBuffer.h"
+#include "icon_buffer.h"
#include <wx/icon.h>
#ifdef FFS_WIN
#include <wx/timer.h>
-#include "statusHandler.h"
+#include "status_handler.h"
#include <cmath>
#elif defined FFS_LINUX
#include <gtk/gtk.h>
#endif
-using namespace FreeFileSync;
+using namespace ffs3;
const size_t MIN_ROW_COUNT = 15;
@@ -271,7 +271,7 @@ protected:
switch (colType_)
{
case xmlAccess::FULL_PATH:
- value = zToWx(fileObj.getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR));
+ value = zToWx(fileObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR));
break;
case xmlAccess::FILENAME: //filename
value = zToWx(fileObj.getShortName<side>());
@@ -283,10 +283,10 @@ protected:
value = zToWx(fileObj.getBaseDirPf<side>());
break;
case xmlAccess::SIZE: //file size
- value = FreeFileSync::numberToStringSep(fileObj.getFileSize<side>());
+ value = ffs3::numberToStringSep(fileObj.getFileSize<side>());
break;
case xmlAccess::DATE: //date
- value = FreeFileSync::utcTimeToLocalString(fileObj.getLastWriteTime<side>());
+ value = ffs3::utcTimeToLocalString(fileObj.getLastWriteTime<side>());
break;
case xmlAccess::EXTENSION: //file extension
value = zToWx(fileObj.getExtension<side>());
@@ -299,7 +299,7 @@ protected:
switch (colType_)
{
case xmlAccess::FULL_PATH:
- value = zToWx(linkObj.getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR));
+ value = zToWx(linkObj.getFullName<side>().BeforeLast(common::FILE_NAME_SEPARATOR));
break;
case xmlAccess::FILENAME: //filename
value = zToWx(linkObj.getShortName<side>());
@@ -314,7 +314,7 @@ protected:
value = _("<Symlink>");
break;
case xmlAccess::DATE: //date
- value = FreeFileSync::utcTimeToLocalString(linkObj.getLastWriteTime<side>());
+ value = ffs3::utcTimeToLocalString(linkObj.getLastWriteTime<side>());
break;
case xmlAccess::EXTENSION: //file extension
value = wxEmptyString;
@@ -624,7 +624,7 @@ void CustomGrid::initSettings(CustomGridLeft* gridLeft,
}
-void CustomGrid::release() //release connection to FreeFileSync::GridView
+void CustomGrid::release() //release connection to ffs3::GridView
{
setGridDataTable(NULL);
}
@@ -1472,7 +1472,7 @@ void CustomGridRim::getIconsToBeLoaded(std::vector<Zstring>& newLoad) //loads al
if (!fileName.empty())
{
//test if they are already loaded in buffer:
- if (FreeFileSync::IconBuffer::getInstance().requestFileIcon(fileName))
+ if (ffs3::IconBuffer::getInstance().requestFileIcon(fileName))
{
//exists in buffer: refresh Row
for (int k = 0; k < totalCols; ++k)
@@ -1520,7 +1520,7 @@ void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet)
//merge vectors
newLoad.insert(newLoad.end(), iconsLeft.begin(), iconsLeft.end());
- FreeFileSync::IconBuffer::getInstance().setWorkload(newLoad); //attention: newLoad is invalidated after this call!!!
+ ffs3::IconBuffer::getInstance().setWorkload(newLoad); //attention: newLoad is invalidated after this call!!!
//event.Skip();
}
@@ -2075,7 +2075,7 @@ void CustomGridMiddle::DrawColLabel(wxDC& dc, int col)
}
-const wxBitmap& FreeFileSync::getSyncOpImage(SyncOperation syncOp)
+const wxBitmap& ffs3::getSyncOpImage(SyncOperation syncOp)
{
switch (syncOp) //evaluate comparison result and sync direction
{
diff --git a/library/CustomGrid.h b/library/custom_grid.h
index 0cace1a9..6c35ffbe 100644
--- a/library/CustomGrid.h
+++ b/library/custom_grid.h
@@ -9,7 +9,7 @@
#include <vector>
#include <wx/grid.h>
-#include "processXml.h"
+#include "process_xml.h"
#include <map>
#include <memory>
#include <set>
@@ -27,7 +27,7 @@ class CustomGridMiddle;
class CustomGridRight;
-namespace FreeFileSync
+namespace ffs3
{
class GridView;
@@ -60,12 +60,12 @@ public:
virtual ~CustomGrid() {}
- void initSettings(CustomGridLeft* gridLeft, //create connection with FreeFileSync::GridView
+ void initSettings(CustomGridLeft* gridLeft, //create connection with ffs3::GridView
CustomGridMiddle* gridMiddle,
CustomGridRight* gridRight,
- const FreeFileSync::GridView* gridDataView);
+ const ffs3::GridView* gridDataView);
- void release(); //release connection to FreeFileSync::GridView
+ void release(); //release connection to ffs3::GridView
std::set<size_t> getAllSelectedRows() const;
@@ -89,7 +89,7 @@ protected:
virtual void DrawColLabel(wxDC& dc, int col);
private:
- virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView) = 0;
+ virtual void setGridDataTable(const ffs3::GridView* gridDataView) = 0;
//this method is called when grid view changes: useful for parallel updating of multiple grids
void OnPaintGrid(wxEvent& event);
@@ -198,7 +198,7 @@ public:
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
private:
- virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+ virtual void setGridDataTable(const ffs3::GridView* gridDataView);
virtual const CustomGridTableRim* getGridDataTable() const;
//this method is called when grid view changes: useful for parallel updating of multiple grids
@@ -221,7 +221,7 @@ public:
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
private:
- virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+ virtual void setGridDataTable(const ffs3::GridView* gridDataView);
virtual const CustomGridTableRim* getGridDataTable() const;
//this method is called when grid view changes: useful for parallel updating of multiple grids
@@ -257,7 +257,7 @@ private:
virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true);
#endif
- virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+ virtual void setGridDataTable(const ffs3::GridView* gridDataView);
//this method is called when grid view changes: useful for parallel updating of multiple grids
virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight);
@@ -331,7 +331,7 @@ extern const wxEventType FFS_SYNC_DIRECTION_EVENT; //define new event type
class FFSSyncDirectionEvent : public wxCommandEvent
{
public:
- FFSSyncDirectionEvent(const int from, const int to, const FreeFileSync::SyncDirection dir) :
+ FFSSyncDirectionEvent(const int from, const int to, const ffs3::SyncDirection dir) :
wxCommandEvent(FFS_SYNC_DIRECTION_EVENT),
rowFrom(from),
rowTo(to),
@@ -344,7 +344,7 @@ public:
const int rowFrom;
const int rowTo;
- const FreeFileSync::SyncDirection direction;
+ const ffs3::SyncDirection direction;
};
typedef void (wxEvtHandler::*FFSSyncDirectionEventFunction)(FFSSyncDirectionEvent&);
diff --git a/library/dbFile.cpp b/library/db_file.cpp
index 1919dd6d..1daa51f5 100644
--- a/library/dbFile.cpp
+++ b/library/db_file.cpp
@@ -4,25 +4,25 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "dbFile.h"
+#include "db_file.h"
#include <wx/wfstream.h>
#include <wx/zstream.h>
-#include "../shared/globalFunctions.h"
-#include "../shared/fileError.h"
+#include "../shared/global_func.h"
+#include "../shared/file_error.h"
#include <wx/intl.h>
-#include "../shared/stringConv.h"
-#include "../shared/fileHandling.h"
+#include "../shared/string_conv.h"
+#include "../shared/file_handling.h"
#include <wx/mstream.h>
#include "../shared/serialize.h"
-#include "../shared/fileIO.h"
+#include "../shared/file_io.h"
#include "../shared/loki/ScopeGuard.h"
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
-#include "../shared/longPathPrefix.h"
+#include "../shared/long_path_prefix.h"
#endif
-using namespace FreeFileSync;
+using namespace ffs3;
namespace
@@ -72,7 +72,7 @@ private:
-class ReadDirInfo : public Utility::ReadInputStream
+class ReadDirInfo : public util::ReadInputStream
{
public:
ReadDirInfo(wxInputStream& stream, const wxString& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName)
@@ -112,7 +112,7 @@ private:
const unsigned long sizeHigh = readNumberC<unsigned long>();
const unsigned long sizeLow = readNumberC<unsigned long>();
- //const Utility::FileID fileIdentifier(stream_);
+ //const util::FileID fileIdentifier(stream_);
//check();
dirCont.addSubFile(shortName,
@@ -144,9 +144,9 @@ private:
};
-typedef boost::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation
-typedef std::map<Utility::UniqueId, MemoryStreamPtr> DirectoryTOC; //list of streams ordered by a UUID pointing to their partner database
-typedef std::pair<Utility::UniqueId, DirectoryTOC> DbStreamData; //header data: UUID representing this database, item data: list of dir-streams
+typedef boost::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation
+typedef std::map<util::UniqueId, MemoryStreamPtr> DirectoryTOC; //list of streams ordered by a UUID pointing to their partner database
+typedef std::pair<util::UniqueId, DirectoryTOC> DbStreamData; //header data: UUID representing this database, item data: list of dir-streams
/* Example
left side right side
--------- ----------
@@ -157,7 +157,7 @@ Partner-ID 567 _/ \_ Partner-ID 123
... ...
*/
-class ReadFileStream : public Utility::ReadInputStream
+class ReadFileStream : public util::ReadInputStream
{
public:
ReadFileStream(wxInputStream& stream, const wxString& filename, DbStreamData& output) : ReadInputStream(stream, filename)
@@ -166,7 +166,7 @@ public:
throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + filename + wxT("\""));
//read DB id
- output.first = Utility::UniqueId(getStream());
+ output.first = util::UniqueId(getStream());
check();
DirectoryTOC& dbList = output.second;
@@ -175,7 +175,7 @@ public:
size_t dbCount = readNumberC<size_t>(); //number of databases: one for each sync-pair
while (dbCount-- != 0)
{
- const Utility::UniqueId partnerID(getStream()); //DB id of partner databases
+ const util::UniqueId partnerID(getStream()); //DB id of partner databases
check();
CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation)
@@ -188,7 +188,7 @@ public:
DbStreamData loadFile(const Zstring& filename) //throw (FileError)
{
- if (!FreeFileSync::fileExists(filename))
+ if (!ffs3::fileExists(filename))
throw FileError(wxString(_("Initial synchronization:")) + wxT(" \n\n") +
_("One of the FreeFileSync database files is not yet existing:") + wxT(" \n") +
wxT("\"") + zToWx(filename) + wxT("\""));
@@ -204,7 +204,7 @@ DbStreamData loadFile(const Zstring& filename) //throw (FileError)
}
-std::pair<DirInfoPtr, DirInfoPtr> FreeFileSync::loadFromDisk(const BaseDirMapping& baseMapping) //throw (FileError)
+std::pair<DirInfoPtr, DirInfoPtr> ffs3::loadFromDisk(const BaseDirMapping& baseMapping) //throw (FileError)
{
const Zstring fileNameLeft = baseMapping.getDBFilename<LEFT_SIDE>();
const Zstring fileNameRight = baseMapping.getDBFilename<RIGHT_SIDE>();
@@ -259,7 +259,7 @@ struct IsNonEmpty
template <SelectedSide side>
-class SaveDirInfo : public Utility::WriteOutputStream
+class SaveDirInfo : public util::WriteOutputStream
{
public:
SaveDirInfo(const BaseDirMapping& baseMapping, const wxString& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream)
@@ -273,11 +273,11 @@ public:
}
private:
- friend class Utility::Proxy<SaveDirInfo<side> >; //friend declaration of std::for_each is NOT sufficient as implementation is compiler dependent!
+ friend class util::ProxyForEach<SaveDirInfo<side> >; //friend declaration of std::for_each is NOT sufficient as implementation is compiler dependent!
void execute(const HierarchyObject& hierObj)
{
- Utility::Proxy<SaveDirInfo<side> > prx(*this); //grant std::for_each access to private parts of this class
+ util::ProxyForEach<SaveDirInfo<side> > prx(*this); //grant std::for_each access to private parts of this class
writeNumberC<size_t>(std::count_if(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), IsNonEmpty<side>())); //number of (existing) files
std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), prx);
@@ -327,7 +327,7 @@ private:
};
-class WriteFileStream : public Utility::WriteOutputStream
+class WriteFileStream : public util::WriteOutputStream
{
public:
WriteFileStream(const DbStreamData& input, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream)
@@ -373,26 +373,42 @@ void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (Fi
}
//(try to) hide database file
#ifdef FFS_WIN
- ::SetFileAttributes(FreeFileSync::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
+ ::SetFileAttributes(ffs3::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN);
#endif
}
-void FreeFileSync::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileError)
+bool entryExisting(const DirectoryTOC& table, const util::UniqueId& newKey, const MemoryStreamPtr& newValue)
+{
+ DirectoryTOC::const_iterator iter = table.find(newKey);
+ if (iter == table.end())
+ return false;
+
+ if (!iter->second.get())
+ return !newValue.get();
+
+ if (!newValue.get())
+ return false;
+
+ return newValue->size() == iter->second->size() && std::equal(newValue->begin(), newValue->end(), iter->second->begin());
+}
+
+
+void ffs3::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileError)
{
//transactional behaviour! write to tmp files first
const Zstring fileNameLeftTmp = baseMapping.getDBFilename<LEFT_SIDE>() + DefaultStr(".tmp");
const Zstring fileNameRightTmp = baseMapping.getDBFilename<RIGHT_SIDE>() + DefaultStr(".tmp");;
//delete old tmp file, if necessary -> throws if deletion fails!
- removeFile(fileNameLeftTmp);
- removeFile(fileNameRightTmp);
+ removeFile(fileNameLeftTmp); //
+ removeFile(fileNameRightTmp); //throw (FileError)
//load old database files...
//read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw!
DbStreamData dbEntriesLeft;
- if (FreeFileSync::fileExists(baseMapping.getDBFilename<LEFT_SIDE>()))
+ if (ffs3::fileExists(baseMapping.getDBFilename<LEFT_SIDE>()))
try
{
dbEntriesLeft = ::loadFile(baseMapping.getDBFilename<LEFT_SIDE>());
@@ -402,7 +418,7 @@ void FreeFileSync::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileEr
//read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw!
DbStreamData dbEntriesRight;
- if (FreeFileSync::fileExists(baseMapping.getDBFilename<RIGHT_SIDE>()))
+ if (ffs3::fileExists(baseMapping.getDBFilename<RIGHT_SIDE>()))
try
{
dbEntriesRight = ::loadFile(baseMapping.getDBFilename<RIGHT_SIDE>());
@@ -427,6 +443,14 @@ void FreeFileSync::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileEr
}
//create/update DirInfo-streams
+ {
+ const bool updateRequiredLeft = !entryExisting(dbEntriesLeft. second, dbEntriesRight.first, dbEntryLeft);
+ const bool updateRequiredRight = !entryExisting(dbEntriesRight.second, dbEntriesLeft. first, dbEntryRight);
+ //some users monitor the *.ffs_db file with RTS => don't touch the file if it isnt't strictly needed
+ if (!updateRequiredLeft && !updateRequiredRight)
+ return;
+ }
+
dbEntriesLeft.second[dbEntriesRight.first] = dbEntryLeft;
dbEntriesRight.second[dbEntriesLeft.first] = dbEntryRight;
@@ -454,9 +478,9 @@ void FreeFileSync::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileEr
//if there were no write access, creation of temp files would have failed
removeFile(baseMapping.getDBFilename<LEFT_SIDE>());
removeFile(baseMapping.getDBFilename<RIGHT_SIDE>());
- renameFile(fileNameLeftTmp, baseMapping.getDBFilename<LEFT_SIDE>()); //throw (FileError);
+ renameFile(fileNameLeftTmp, baseMapping.getDBFilename<LEFT_SIDE>()); //throw (FileError);
renameFile(fileNameRightTmp, baseMapping.getDBFilename<RIGHT_SIDE>()); //throw (FileError);
- guardTempFileLeft.Dismiss(); //no need to delete temp file anymore
+ guardTempFileLeft. Dismiss(); //no need to delete temp file anymore
guardTempFileRight.Dismiss(); //
}
diff --git a/library/dbFile.h b/library/db_file.h
index 9fa49c51..8e1f9c94 100644
--- a/library/dbFile.h
+++ b/library/db_file.h
@@ -7,9 +7,9 @@
#ifndef DBFILE_H_INCLUDED
#define DBFILE_H_INCLUDED
-#include "../fileHierarchy.h"
+#include "../file_hierarchy.h"
-namespace FreeFileSync
+namespace ffs3
{
void saveToDisk(const BaseDirMapping& baseMapping); //throw (FileError)
diff --git a/library/detectRenaming.cpp b/library/detect_renaming.cpp
index bd25874b..617a3eba 100644
--- a/library/detectRenaming.cpp
+++ b/library/detect_renaming.cpp
@@ -4,7 +4,7 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "detectRenaming.h"
+#include "detect_renaming.h"
#include <map>
#include <vector>
#include <boost/bind.hpp>
diff --git a/library/detectRenaming.h b/library/detect_renaming.h
index ecfa0344..45bdf59d 100644
--- a/library/detectRenaming.h
+++ b/library/detect_renaming.h
@@ -7,18 +7,18 @@
#ifndef DETECTRENAMING_H_INCLUDED
#define DETECTRENAMING_H_INCLUDED
-#include "../fileHierarchy.h"
+#include "../file_hierarchy.h"
//identify a file "create and delete"-operation as a file renaming!
-namespace FreeFileSync
+namespace ffs3
{
typedef FileMapping* CreateOnLeft;
typedef FileMapping* DeleteOnLeft;
typedef FileMapping* CreateOnRight;
typedef FileMapping* DeleteOnRight;
-void getRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping, //in
+void getRenameCandidates(ffs3::BaseDirMapping& baseMapping, //in
std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out
std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight); //out throw()!
}
diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp
new file mode 100644
index 00000000..c5ea37b1
--- /dev/null
+++ b/library/dir_lock.cpp
@@ -0,0 +1,448 @@
+#include "dir_lock.h"
+#include <wx/intl.h>
+#include "../shared/string_conv.h"
+#include "../shared/system_func.h"
+#include <wx/utils.h>
+#include <wx/timer.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/thread.hpp>
+#include "../shared/loki/ScopeGuard.h"
+#include <wx/msgdlg.h>
+#include "../shared/system_constants.h"
+#include "../shared/guid.h"
+#include "../shared/file_io.h"
+#include <utility>
+
+#ifdef FFS_WIN
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "../shared/long_path_prefix.h"
+
+#elif defined FFS_LINUX
+#include <sys/stat.h>
+#include <cerrno>
+#endif
+
+using namespace ffs3;
+using namespace std::rel_ops;
+
+
+namespace
+{
+const size_t EMIT_LIFE_SIGN_INTERVAL = 5000; //show life sign; unit [ms]
+const size_t POLL_LIFE_SIGN_INTERVAL = 6000; //poll for life sign; unit [ms]
+const size_t DETECT_EXITUS_INTERVAL = 30000; //assume abandoned lock; unit [ms]
+}
+
+class LifeSigns
+{
+public:
+ LifeSigns(const Zstring& lockfilename) : //throw()!!! siehe SharedDirLock()
+ lockfilename_(lockfilename.c_str()) //ref-counting structure is used by thread: make deep copy!
+ {
+ threadObj = boost::thread(boost::cref(*this)); //localize all thread logic to this class!
+ }
+
+ ~LifeSigns()
+ {
+ threadObj.interrupt(); //thread lifetime is subset of this instances's life
+ threadObj.join();
+ }
+
+ void operator()() const //thread entry
+ {
+ try
+ {
+ while (true)
+ {
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(EMIT_LIFE_SIGN_INTERVAL)); //interruption point!
+
+ //actual work
+ emitLifeSign(); //throw ()
+ }
+ }
+ catch (const std::exception& e) //exceptions must be catched per thread
+ {
+ wxMessageBox(wxString::FromAscii(e.what()), wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxOK | wxICON_ERROR);
+ }
+ }
+
+ void emitLifeSign() const //try to append one byte...; throw()
+ {
+ const char buffer[1] = {' '};
+
+#ifdef FFS_WIN
+ const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_).c_str(),
+ FILE_APPEND_DATA,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ return;
+
+ Loki::ScopeGuard dummy = Loki::MakeGuard(::CloseHandle, fileHandle);
+ (void)dummy; //silence warning "unused variable"
+
+ const DWORD fpLow = ::SetFilePointer(fileHandle, 0, NULL, FILE_END);
+ if (fpLow == INVALID_SET_FILE_POINTER)
+ return;
+
+ DWORD bytesWritten = 0;
+ ::WriteFile(
+ fileHandle, //__in HANDLE hFile,
+ buffer, //__out LPVOID lpBuffer,
+ 1, //__in DWORD nNumberOfBytesToRead,
+ &bytesWritten, //__out_opt LPDWORD lpNumberOfBytesWritten,
+ NULL); //__inout_opt LPOVERLAPPED lpOverlapped
+
+#elif defined FFS_LINUX
+ const int fileHandle = ::open(lockfilename_.c_str(), O_WRONLY | O_APPEND); //O_EXCL contains a race condition on NFS file systems: http://linux.die.net/man/2/open
+ if (fileHandle == -1)
+ return;
+
+ Loki::ScopeGuard dummy = Loki::MakeGuard(::close, fileHandle);
+ (void)dummy; //silence warning "unused variable"
+
+ const ssize_t bytesWritten = ::write(fileHandle, buffer, 1);
+ (void)bytesWritten;
+#endif
+ }
+
+private:
+ LifeSigns(const LifeSigns&); //just be sure this ref-counting Zstring doesn't bite
+ LifeSigns& operator=(const LifeSigns&); //
+
+ boost::thread threadObj;
+ const Zstring lockfilename_; //used by worker thread only! Not ref-counted!
+};
+
+
+namespace
+{
+bool somethingExists(const Zstring& objname) //throw() check whether any object with this name exists
+{
+#ifdef FFS_WIN
+ return ::GetFileAttributes(applyLongPathPrefix(objname).c_str()) != INVALID_FILE_ATTRIBUTES;
+
+#elif defined FFS_LINUX
+ struct stat fileInfo;
+ return ::lstat(objname.c_str(), &fileInfo) == 0;
+#endif
+}
+
+
+void deleteLockFile(const Zstring& filename) //throw (FileError)
+{
+#ifdef FFS_WIN
+ if (!::DeleteFile(applyLongPathPrefix(filename).c_str()))
+#elif defined FFS_LINUX
+ if (::unlink(filename.c_str()) != 0)
+#endif
+ {
+ wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + getLastErrorFormatted());
+ }
+}
+
+
+wxULongLong getLockFileSize(const Zstring& filename) //throw (FileError, ErrorNotExisting)
+{
+#ifdef FFS_WIN
+ WIN32_FIND_DATA fileMetaData;
+ const HANDLE searchHandle = ::FindFirstFile(applyLongPathPrefix(filename).c_str(), &fileMetaData);
+ if (searchHandle == INVALID_HANDLE_VALUE)
+ {
+ const DWORD lastError = ::GetLastError();
+ const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\"") +
+ wxT("\n\n") + getLastErrorFormatted(lastError);
+ if (lastError == ERROR_FILE_NOT_FOUND)
+ throw ErrorNotExisting(errorMessage);
+ else
+ throw FileError(errorMessage);
+ }
+
+ ::FindClose(searchHandle);
+
+ return wxULongLong(fileMetaData.nFileSizeHigh, fileMetaData.nFileSizeLow);
+
+#elif defined FFS_LINUX
+ struct stat fileInfo;
+ if (::stat(filename.c_str(), &fileInfo) != 0) //follow symbolic links
+ {
+ const int lastError = errno;
+ const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(filename) + wxT("\"") +
+ wxT("\n\n") + getLastErrorFormatted(lastError);
+ if (lastError == ENOENT)
+ throw ErrorNotExisting(errorMessage);
+ else
+ throw FileError(errorMessage);
+ }
+
+ return fileInfo.st_size;
+#endif
+}
+
+
+Zstring deleteAbandonedLockName(const Zstring& lockfilename)
+{
+ const size_t pos = lockfilename.Find(common::FILE_NAME_SEPARATOR, true); //search from end
+
+ return pos == Zstring::npos ? DefaultStr("Del.") + lockfilename :
+
+ Zstring(lockfilename.c_str(), pos + 1) + //include path separator
+ DefaultStr("Del.") +
+ lockfilename.AfterLast(common::FILE_NAME_SEPARATOR); //returns the whole string if ch not found
+}
+
+
+void writeLockId(const Zstring& lockfilename) //throw (FileError)
+{
+ //write GUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks ,etc.)
+ FileOutputStream lockFile(lockfilename); //throw FileError()
+ util::UniqueId().toStream(lockFile); //
+}
+
+
+util::UniqueId retrieveLockId(const Zstring& lockfilename) //throw (FileError, ErrorNotExisting)
+{
+ //read GUID from beginning of file
+ FileInputStream lockFile(lockfilename); //throw (FileError, ErrorNotExisting)
+ return util::UniqueId(lockFile); //
+}
+
+
+void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw (FileError)
+{
+ Zstring infoMsg;
+ infoMsg = wxToZ(_("Waiting while directory is locked (%x)..."));
+ infoMsg.Replace(DefaultStr("%x"), DefaultStr("\"") + lockfilename + DefaultStr("\""));
+ if (callback) callback->updateStatusText(infoMsg);
+ //---------------------------------------------------------------
+ try
+ {
+ const util::UniqueId lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
+
+ wxULongLong fileSizeOld;
+ wxLongLong lockSilentStart = wxGetLocalTimeMillis();
+
+ while (true)
+ {
+ const wxULongLong fileSizeNew = ::getLockFileSize(lockfilename); //throw (FileError, ErrorNotExisting)
+ const wxLongLong currentTime = wxGetLocalTimeMillis();
+
+ if (fileSizeNew != fileSizeOld)
+ {
+ //received life sign from lock
+ fileSizeOld = fileSizeNew;
+ lockSilentStart = currentTime;
+ }
+ else if (currentTime - lockSilentStart > DETECT_EXITUS_INTERVAL)
+ {
+ DirLock dummy(deleteAbandonedLockName(lockfilename), callback); //throw (FileError)
+
+ //now that the lock is in place check existence again: meanwhile another process may have deleted and created a new lock!
+
+ if (retrieveLockId(lockfilename) != lockId) //throw (FileError, ErrorNotExisting)
+ return; //another process has placed a new lock, leave scope: the wait for the old lock is technically over...
+
+ if (getLockFileSize(lockfilename) != fileSizeOld) //throw (FileError, ErrorNotExisting)
+ continue; //belated lifesign
+
+ //---------------------------------------------------------------
+ Zstring infoMsg2 = wxToZ(_("Removing abandoned directory lock (%x)..."));
+ infoMsg2.Replace(DefaultStr("%x"), DefaultStr("\"") + lockfilename + DefaultStr("\""));
+ if (callback) callback->updateStatusText(infoMsg2);
+ //---------------------------------------------------------------
+
+ ::deleteLockFile(lockfilename); //throw (FileError)
+ return;
+ }
+
+ //wait some time...
+ const size_t GUI_CALLBACK_INTERVAL = 100;
+ for (size_t i = 0; i < POLL_LIFE_SIGN_INTERVAL / GUI_CALLBACK_INTERVAL; ++i)
+ {
+ if (callback) callback->requestUiRefresh();
+ wxMilliSleep(GUI_CALLBACK_INTERVAL);
+
+ //show some countdown on abandoned locks
+ if (callback)
+ {
+ if (currentTime - lockSilentStart > EMIT_LIFE_SIGN_INTERVAL) //one signal missed: it's likely this is an abandoned lock:
+ {
+ long remainingSeconds = ((DETECT_EXITUS_INTERVAL - (wxGetLocalTimeMillis() - lockSilentStart)) / 1000).GetLo();
+ remainingSeconds = std::max(0L, remainingSeconds);
+
+ Zstring remSecMsg = wxToZ(_("%x sec"));
+ remSecMsg.Replace(DefaultStr("%x"), numberToZstring(remainingSeconds));
+ callback->updateStatusText(infoMsg + DefaultStr(" ") + remSecMsg);
+ }
+ else
+ callback->updateStatusText(infoMsg); //emit a message in any case (might clear other one)
+ }
+ }
+ }
+
+ }
+ catch (const ErrorNotExisting&)
+ {
+ return; //what we are waiting for...
+ }
+}
+
+
+void releaseLock(const Zstring& lockfilename) //throw ()
+{
+ try
+ {
+ ::deleteLockFile(lockfilename);
+ }
+ catch(...) {}
+}
+
+
+bool tryLock(const Zstring& lockfilename) //throw (FileError)
+{
+#ifdef FFS_WIN
+ const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename).c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ {
+ if (::GetLastError() == ERROR_FILE_EXISTS)
+ return false;
+ else
+ throw FileError(wxString(_("Error setting directory lock:")) + wxT("\n\"") + zToWx(lockfilename) + wxT("\"") +
+ wxT("\n\n") + getLastErrorFormatted());
+ }
+ ::CloseHandle(fileHandle);
+
+#elif defined FFS_LINUX
+ //O_EXCL contains a race condition on NFS file systems: http://linux.die.net/man/2/open
+ ::umask(0); //important!
+ const int fileHandle = ::open(lockfilename.c_str(), O_CREAT | O_WRONLY | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fileHandle == -1)
+ {
+ if (errno == EEXIST)
+ return false;
+ else
+ throw FileError(wxString(_("Error setting directory lock:")) + wxT("\n\"") + zToWx(lockfilename) + wxT("\"") +
+ wxT("\n\n") + getLastErrorFormatted());
+ }
+ ::close(fileHandle);
+#endif
+
+ Loki::ScopeGuard guardLockFile = Loki::MakeGuard(::releaseLock, lockfilename);
+
+ //write UUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks ,etc.)
+ writeLockId(lockfilename); //throw (FileError)
+
+ guardLockFile.Dismiss(); //lockfile created successfully
+ return true;
+}
+}
+
+
+class DirLock::SharedDirLock
+{
+public:
+ SharedDirLock(const Zstring& lockfilename, DirLockCallback* callback = NULL) : //throw (FileError)
+ lockfilename_(lockfilename)
+ {
+ while (!::tryLock(lockfilename)) //throw (FileError)
+ ::waitOnDirLock(lockfilename, callback); //
+
+ emitLifeSigns.reset(new LifeSigns(lockfilename)); //throw()! ownership of lockfile not yet managed!
+ }
+
+ ~SharedDirLock()
+ {
+ emitLifeSigns.reset();
+
+ ::releaseLock(lockfilename_); //throw ()
+ }
+
+private:
+ SharedDirLock(const DirLock&);
+ SharedDirLock& operator=(const DirLock&);
+
+ const Zstring lockfilename_;
+
+ std::auto_ptr<LifeSigns> emitLifeSigns;
+};
+
+
+class DirLock::LockAdmin //administrate all locks of this process to avoid deadlock by recursion
+{
+public:
+ static LockAdmin& instance()
+ {
+ static LockAdmin inst;
+ return inst;
+ }
+
+ //create or retrieve a SharedDirLock
+ boost::shared_ptr<SharedDirLock> retrieve(const Zstring& lockfilename, DirLockCallback* callback) //throw (FileError)
+ {
+ //optimization: check if there is an active(!) lock for "lockfilename"
+ FileToUuidMap::const_iterator iterUuid = fileToUuid.find(lockfilename);
+ if (iterUuid != fileToUuid.end())
+ {
+ const boost::shared_ptr<SharedDirLock>& activeLock = findActive(iterUuid->second); //returns null-lock if not found
+ if (activeLock)
+ return activeLock; //SharedDirLock is still active -> enlarge circle of shared ownership
+ }
+
+ try //actual check based on lock UUID, deadlock prevention: "lockfilename" may be an alternative name for an already active lock
+ {
+ const util::UniqueId lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
+
+ const boost::shared_ptr<SharedDirLock>& activeLock = findActive(lockId); //returns null-lock if not found
+ if (activeLock)
+ {
+ fileToUuid[lockfilename] = lockId; //perf-optimization: update relation
+ return activeLock;
+ }
+ }
+ catch (const ErrorNotExisting&) {} //let other FileError(s) propagate!
+
+ //not yet in buffer, so create a new directory lock
+ boost::shared_ptr<SharedDirLock> newLock(new SharedDirLock(lockfilename, callback)); //throw (FileError)
+ const util::UniqueId newLockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting)
+
+ //update registry
+ fileToUuid[lockfilename] = newLockId; //throw()
+ uuidToLock[newLockId] = newLock; //
+
+ return newLock;
+ }
+
+private:
+ LockAdmin() {}
+
+ boost::shared_ptr<SharedDirLock> findActive(const util::UniqueId& lockId) //returns null-lock if not found
+ {
+ UuidToLockMap::const_iterator iterLock = uuidToLock.find(lockId);
+ return iterLock != uuidToLock.end() ?
+ iterLock->second.lock() : //try to get shared_ptr; throw()
+ boost::shared_ptr<SharedDirLock>();
+ }
+
+ typedef boost::weak_ptr<SharedDirLock> SharedLock;
+
+ typedef std::map<Zstring, util::UniqueId, LessFilename> FileToUuidMap; //n:1 handle uppper/lower case correctly
+ typedef std::map<util::UniqueId, SharedLock> UuidToLockMap; //1:1
+
+ FileToUuidMap fileToUuid; //lockname |-> UUID; locks can be referenced by a lockfilename or alternatively a UUID
+ UuidToLockMap uuidToLock; //UUID |-> "shared lock ownership"
+};
+
+
+DirLock::DirLock(const Zstring& lockfilename, DirLockCallback* callback) : //throw (FileError)
+ sharedLock(LockAdmin::instance().retrieve(lockfilename, callback)) {}
diff --git a/library/dir_lock.h b/library/dir_lock.h
new file mode 100644
index 00000000..e3b6597c
--- /dev/null
+++ b/library/dir_lock.h
@@ -0,0 +1,35 @@
+#ifndef DIR_LOCK_H_INCLUDED
+#define DIR_LOCK_H_INCLUDED
+
+#include "../shared/zstring.h"
+#include "../shared/file_error.h"
+#include <boost/shared_ptr.hpp>
+
+
+struct DirLockCallback //while waiting for the lock
+{
+ virtual ~DirLockCallback() {}
+ virtual void requestUiRefresh() = 0; //allowed to throw exceptions
+ virtual void updateStatusText(const Zstring& text) = 0;
+};
+
+/*
+RAII structure to place a directory lock against other FFS processes:
+ - recursive locking supported, even with alternate lockfile names, e.g. via symlinks, network mounts etc.
+ - ownership shared between all object instances refering to a specific lock location(= UUID)
+ - can be copied safely and efficiently! (ref-counting)
+ - detects and resolves abandoned locks
+ - race-free (Windows, almost on Linux)
+*/
+class DirLock
+{
+public:
+ DirLock(const Zstring& lockfilename, DirLockCallback* callback = NULL); //throw (FileError)
+
+private:
+ class LockAdmin;
+ class SharedDirLock;
+ boost::shared_ptr<SharedDirLock> sharedLock;
+};
+
+#endif // DIR_LOCK_H_INCLUDED
diff --git a/library/errorLogging.cpp b/library/error_log.cpp
index 7e73f005..9936a2ea 100644
--- a/library/errorLogging.cpp
+++ b/library/error_log.cpp
@@ -4,12 +4,12 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "errorLogging.h"
+#include "error_log.h"
#include <wx/datetime.h>
#include <wx/intl.h>
-using FreeFileSync::ErrorLogging;
+using ffs3::ErrorLogging;
void ErrorLogging::logInfo(const wxString& infoMessage)
diff --git a/library/errorLogging.h b/library/error_log.h
index 6b27e1c1..dc3ef580 100644
--- a/library/errorLogging.h
+++ b/library/error_log.h
@@ -12,7 +12,7 @@
class Zstring;
-namespace FreeFileSync
+namespace ffs3
{
class ErrorLogging
{
diff --git a/library/filter.cpp b/library/filter.cpp
index a64c3a31..c4bc69d7 100644
--- a/library/filter.cpp
+++ b/library/filter.cpp
@@ -10,14 +10,14 @@
#include <set>
#include <stdexcept>
#include <vector>
-#include "../shared/systemConstants.h"
+#include "../shared/system_constants.h"
#include "../structures.h"
#include <boost/bind.hpp>
#include "../shared/loki/LokiTypeInfo.h"
#include "../shared/serialize.h"
-using FreeFileSync::BaseFilter;
-using FreeFileSync::NameFilter;
+using ffs3::BaseFilter;
+using ffs3::NameFilter;
//--------------------------------------------------------------------------------------------------
@@ -46,7 +46,7 @@ bool BaseFilter::operator<(const BaseFilter& other) const
void BaseFilter::saveFilter(wxOutputStream& stream) const //serialize derived object
{
//save type information
- Utility::writeString(stream, uniqueClassIdentifier());
+ util::writeString(stream, uniqueClassIdentifier());
//save actual object
save(stream);
@@ -56,7 +56,7 @@ void BaseFilter::saveFilter(wxOutputStream& stream) const //serialize derived ob
BaseFilter::FilterRef BaseFilter::loadFilter(wxInputStream& stream)
{
//read type information
- const Zstring uniqueClassId = Utility::readString(stream);
+ const Zstring uniqueClassId = util::readString(stream);
//read actual object
if (uniqueClassId == DefaultStr("NullFilter"))
@@ -83,17 +83,17 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
//Linux DOES distinguish between upper/lower-case: nothing to do here
#endif
- static const Zstring sepAsterisk = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + DefaultChar('*');
- static const Zstring sepQuestionMark = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + DefaultChar('?');
- static const Zstring asteriskSep = Zstring(DefaultStr("*")) + globalFunctions::FILE_NAME_SEPARATOR;
- static const Zstring questionMarkSep = Zstring(DefaultStr("?")) + globalFunctions::FILE_NAME_SEPARATOR;
+ static const Zstring sepAsterisk = Zstring() + common::FILE_NAME_SEPARATOR + DefaultChar('*');
+ static const Zstring sepQuestionMark = Zstring() + common::FILE_NAME_SEPARATOR + DefaultChar('?');
+ static const Zstring asteriskSep = Zstring(DefaultStr("*")) + common::FILE_NAME_SEPARATOR;
+ static const Zstring questionMarkSep = Zstring(DefaultStr("?")) + common::FILE_NAME_SEPARATOR;
//--------------------------------------------------------------------------------------------------
//add some syntactic sugar: handle beginning of filtername
- if (filterFormatted.StartsWith(globalFunctions::FILE_NAME_SEPARATOR))
+ if (filterFormatted.StartsWith(common::FILE_NAME_SEPARATOR))
{
//remove leading separators (keep BEFORE test for Zstring::empty()!)
- filterFormatted = filterFormatted.AfterFirst(globalFunctions::FILE_NAME_SEPARATOR);
+ filterFormatted = filterFormatted.AfterFirst(common::FILE_NAME_SEPARATOR);
}
else if (filterFormatted.StartsWith(asteriskSep) || // *\abc
filterFormatted.StartsWith(questionMarkSep)) // ?\abc
@@ -103,9 +103,9 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
//--------------------------------------------------------------------------------------------------
//even more syntactic sugar: handle end of filtername
- if (filterFormatted.EndsWith(globalFunctions::FILE_NAME_SEPARATOR))
+ if (filterFormatted.EndsWith(common::FILE_NAME_SEPARATOR))
{
- const Zstring candidate = filterFormatted.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR);
+ const Zstring candidate = filterFormatted.BeforeLast(common::FILE_NAME_SEPARATOR);
if (!candidate.empty())
directoryFilter.insert(candidate); //only relevant for directory filtering
}
@@ -115,7 +115,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
fileFilter.insert( filterFormatted);
directoryFilter.insert(filterFormatted);
- const Zstring candidate = filterFormatted.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR);
+ const Zstring candidate = filterFormatted.BeforeLast(common::FILE_NAME_SEPARATOR);
if (!candidate.empty())
directoryFilter.insert(candidate); //only relevant for directory filtering
}
@@ -251,7 +251,7 @@ bool NameFilter::passDirFilter(const Zstring& relDirname, bool* subObjMightMatch
{
if (subObjMightMatch)
{
- const Zstring& subNameBegin = relDirname + globalFunctions::FILE_NAME_SEPARATOR; //const-ref optimization
+ const Zstring& subNameBegin = relDirname + common::FILE_NAME_SEPARATOR; //const-ref optimization
*subObjMightMatch = matchesFilterBegin(subNameBegin, filterFileIn) || //might match a file in subdirectory
matchesFilterBegin(subNameBegin, filterFolderIn); //or another subdirectory
@@ -300,15 +300,15 @@ Zstring NameFilter::uniqueClassIdentifier() const
void NameFilter::save(wxOutputStream& stream) const
{
- Utility::writeString(stream, includeFilterTmp);
- Utility::writeString(stream, excludeFilterTmp);
+ util::writeString(stream, includeFilterTmp);
+ util::writeString(stream, excludeFilterTmp);
}
BaseFilter::FilterRef NameFilter::load(wxInputStream& stream) //"constructor"
{
- const Zstring include = Utility::readString(stream);
- const Zstring exclude = Utility::readString(stream);
+ const Zstring include = util::readString(stream);
+ const Zstring exclude = util::readString(stream);
return FilterRef(new NameFilter(include, exclude));
}
diff --git a/library/filter.h b/library/filter.h
index f27e06e6..9497eb8d 100644
--- a/library/filter.h
+++ b/library/filter.h
@@ -12,7 +12,7 @@
#include <boost/shared_ptr.hpp>
#include <wx/stream.h>
-namespace FreeFileSync
+namespace ffs3
{
//------------------------------------------------------------------
/* class hierarchy:
diff --git a/library/iconBuffer.cpp b/library/icon_buffer.cpp
index fa0b1673..81d14146 100644
--- a/library/iconBuffer.cpp
+++ b/library/icon_buffer.cpp
@@ -4,15 +4,12 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "iconBuffer.h"
-#include <wx/thread.h>
-#include <wx/bitmap.h>
+#include "icon_buffer.h"
#include <wx/msgdlg.h>
-#include <wx/icon.h>
#include <map>
#include <queue>
-#include <stdexcept>
#include <set>
+#include <boost/thread.hpp>
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
@@ -24,20 +21,11 @@
#endif
-using FreeFileSync::IconBuffer;
+using ffs3::IconBuffer;
namespace
{
-struct CmpFilename
-{
- bool operator()(const Zstring& a, const Zstring& b) const
- {
- return a.cmpFileName(b) < 0;
- }
-};
-
-
#ifdef FFS_WIN
Zstring getFileExtension(const Zstring& filename)
{
@@ -52,7 +40,7 @@ Zstring getFileExtension(const Zstring& filename)
//test for extension for icons that physically have to be retrieved from disc
bool isPriceyExtension(const Zstring& extension)
{
- static std::set<Zstring, CmpFilename> exceptions;
+ static std::set<Zstring, LessFilename> exceptions;
static bool isInitalized = false;
if (!isInitalized)
{
@@ -182,7 +170,7 @@ IconBuffer::IconHolder IconBuffer::getAssociatedIcon(const Zstring& filename)
//bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080
//NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup!
- ::SHGetFileInfo(filename.c_str(), //FreeFileSync::removeLongPathPrefix(fileName), //::SHGetFileInfo() can't handle \\?\-prefix!
+ ::SHGetFileInfo(filename.c_str(), //ffs3::removeLongPathPrefix(fileName), //::SHGetFileInfo() can't handle \\?\-prefix!
0,
&fileInfo,
sizeof(fileInfo),
@@ -224,17 +212,19 @@ IconBuffer::IconHolder IconBuffer::getAssociatedIcon(const Zstring& filename)
}
catch (const Glib::Error&) {}
-
- //fallback: icon lookup may fail because some icons are currently not present on system
- Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default();
- if (iconTheme)
+ try //fallback: icon lookup may fail because some icons are currently not present on system
{
- Glib::RefPtr<Gdk::Pixbuf> iconPixbuf = iconTheme->load_icon("misc", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN);
- if (!iconPixbuf)
- iconPixbuf = iconTheme->load_icon("text-x-generic", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN);
- if (iconPixbuf)
- return IconHolder(iconPixbuf->gobj_copy()); //copy and pass icon ownership (may be 0)
+ Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default();
+ if (iconTheme)
+ {
+ Glib::RefPtr<Gdk::Pixbuf> iconPixbuf = iconTheme->load_icon("misc", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN);
+ if (!iconPixbuf)
+ iconPixbuf = iconTheme->load_icon("text-x-generic", ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN);
+ if (iconPixbuf)
+ return IconHolder(iconPixbuf->gobj_copy()); //copy and pass icon ownership (may be 0)
+ }
}
+ catch (const Glib::Error&) {}
//fallback fallback
return IconHolder();
@@ -266,15 +256,15 @@ typedef std::vector<DefaultChar> BasicString; //simple thread safe string class:
//---------------------------------------------------------------------------------------------------
-class IconBuffer::WorkerThread : public wxThread
+class IconBuffer::WorkerThread
{
public:
- WorkerThread(IconBuffer* iconBuff);
+ WorkerThread(IconBuffer& iconBuff);
+ ~WorkerThread();
void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved
- void quitThread();
- virtual ExitCode Entry();
+ void operator()(); //thread entry
private:
void doWork();
@@ -282,88 +272,69 @@ private:
//---------------------- Shared Data -------------------------
typedef BasicString FileName;
- wxCriticalSection lockWorkload; //use for locking shared data
- std::vector<FileName> workload; //processes last elements of vector first!
- bool threadHasMutex;
+ struct SharedData
+ {
+ std::vector<FileName> workload; //processes last elements of vector first!
+ boost::mutex mutex;
+ boost::condition_variable condition; //signal event: data for processing available
+ } shared;
//------------------------------------------------------------
- //signal event: icon buffer(main thread) -> worker thread
- wxMutex threadIsListening;
- wxCondition continueWork; //wake up thread
+ IconBuffer& iconBuffer;
- IconBuffer* iconBuffer;
+ boost::thread threadObj;
};
-IconBuffer::WorkerThread::WorkerThread(IconBuffer* iconBuff) :
- wxThread(wxTHREAD_DETACHED), //we're using the thread encapsulated in a static object => use "detached" to avoid main thread waiting for this thread on exit(which in turn would prevent deletion of static object...ect.) => deadlock!
- threadHasMutex(false),
- threadIsListening(),
- continueWork(threadIsListening),
+IconBuffer::WorkerThread::WorkerThread(IconBuffer& iconBuff) :
iconBuffer(iconBuff)
{
- if (Create() != wxTHREAD_NO_ERROR)
- throw std::runtime_error("Error creating icon buffer worker thread!");
+ threadObj = boost::thread(boost::ref(*this)); //localize all thread logic to this class!
+}
- if (Run() != wxTHREAD_NO_ERROR)
- throw std::runtime_error("Error starting icon buffer worker thread!");
- //wait until thread has aquired mutex
- bool hasMutex = false;
- while (!hasMutex)
- {
- wxMilliSleep(5);
- wxCriticalSectionLocker dummy(lockWorkload);
- hasMutex = threadHasMutex;
- } //polling -> it's not nice, but works and is no issue
+IconBuffer::WorkerThread::~WorkerThread()
+{
+ setWorkload(std::vector<Zstring>()); //make sure interruption point is always reached!
+ threadObj.interrupt();
+ threadObj.join();
}
void IconBuffer::WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new workload of icons to be retrieved
{
- wxCriticalSectionLocker dummy(lockWorkload);
-
- workload.clear();
- for (std::vector<Zstring>::const_iterator i = load.begin(); i != load.end(); ++i)
- workload.push_back(FileName(i->c_str(), i->c_str() + i->length() + 1)); //make DEEP COPY from Zstring (include null-termination)!
-
- if (!workload.empty())
- continueWork.Signal(); //wake thread IF he is waiting
-}
+ {
+ boost::lock_guard<boost::mutex> dummy(shared.mutex);
+ shared.workload.clear();
+ for (std::vector<Zstring>::const_iterator i = load.begin(); i != load.end(); ++i)
+ shared.workload.push_back(FileName(i->c_str(), i->c_str() + i->length() + 1)); //make DEEP COPY from Zstring (include null-termination)!
+ }
-void IconBuffer::WorkerThread::quitThread()
-{
- setWorkload(std::vector<Zstring>());
- Delete(); //gracefully terminate a detached thread...
+ shared.condition.notify_one();
+ //condition handling, see: http://www.boost.org/doc/libs/1_43_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
}
-wxThread::ExitCode IconBuffer::WorkerThread::Entry()
+void IconBuffer::WorkerThread::operator()() //thread entry
{
try
{
- //this lock needs to be called from WITHIN the thread => calling it from constructor(Main thread) would be useless (signal direction: main -> thread)
- wxMutexLocker dummy(threadIsListening); //this mutex STAYS locked all the time except of continueWork.Wait()!
- {
- wxCriticalSectionLocker dummy2(lockWorkload);
- threadHasMutex = true;
- }
-
while (true)
{
- continueWork.WaitTimeout(100); //waiting for continueWork.Signal(); unlocks Mutex "threadIsListening"
-
- if (TestDestroy())
- return 0;
+ {
+ boost::unique_lock<boost::mutex> dummy(shared.mutex);
+ while(shared.workload.empty())
+ shared.condition.wait(dummy); //interruption point!
+ //shared.condition.timed_wait(dummy, boost::get_system_time() + boost::posix_time::milliseconds(100));
+ }
- doWork();
+ doWork(); //no need to lock the complete method!
}
}
catch (const std::exception& e) //exceptions must be catched per thread
{
- wxMessageBox(wxString::FromAscii(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR);
- return 0;
+ wxMessageBox(wxString::FromAscii(e.what()), wxString(_("An exception occurred!")) + wxT("(Icon buffer)"), wxOK | wxICON_ERROR);
}
}
@@ -375,14 +346,14 @@ void IconBuffer::WorkerThread::doWork()
{
Zstring fileName;
{
- wxCriticalSectionLocker dummy(lockWorkload);
- if (workload.empty())
+ boost::lock_guard<boost::mutex> dummy(shared.mutex);
+ if (shared.workload.empty())
break; //enter waiting state
- fileName = &workload.back()[0]; //deep copy (includes NULL-termination)
- workload.pop_back();
+ fileName = &shared.workload.back()[0]; //deep copy (includes NULL-termination)
+ shared.workload.pop_back();
}
- if (iconBuffer->requestFileIcon(fileName)) //thread safety: Zstring okay, won't be reference-counted in requestIcon()
+ if (iconBuffer.requestFileIcon(fileName)) //thread safety: Zstring okay, won't be reference-counted in requestIcon()
continue; //icon already in buffer: skip
#ifdef FFS_WIN
@@ -390,16 +361,16 @@ void IconBuffer::WorkerThread::doWork()
if (isPriceyExtension(extension)) //"pricey" extensions are stored with fullnames and are read from disk, while cheap ones require just the extension
{
const IconHolder newIcon = IconBuffer::getAssociatedIcon(fileName);
- iconBuffer->insertIntoBuffer(fileName, newIcon);
+ iconBuffer.insertIntoBuffer(fileName, newIcon);
}
else //no read-access to disk! determine icon by extension
{
const IconHolder newIcon = IconBuffer::getAssociatedIconByExt(extension);
- iconBuffer->insertIntoBuffer(extension, newIcon);
+ iconBuffer.insertIntoBuffer(extension, newIcon);
}
#elif defined FFS_LINUX
const IconHolder newIcon = IconBuffer::getAssociatedIcon(fileName);
- iconBuffer->insertIntoBuffer(fileName, newIcon);
+ iconBuffer.insertIntoBuffer(fileName, newIcon);
#endif
}
}
@@ -419,22 +390,18 @@ IconBuffer& IconBuffer::getInstance()
IconBuffer::IconBuffer() :
- lockIconDB( new wxCriticalSection),
buffer( new IconDB),
bufSequence(new IconDbSequence),
- worker( new WorkerThread(this)) //might throw exceptions!
+ worker( new WorkerThread(*this)) //might throw exceptions!
{}
-IconBuffer::~IconBuffer()
-{
- worker->quitThread();
-}
+IconBuffer::~IconBuffer() {} //auto_ptr<>: keep destructor non-inline
bool IconBuffer::requestFileIcon(const Zstring& fileName, wxIcon* icon)
{
- wxCriticalSectionLocker dummy(*lockIconDB);
+ boost::lock_guard<boost::mutex> dummy(lockIconDB);
#ifdef FFS_WIN
//"pricey" extensions are stored with fullnames and are read from disk, while cheap ones require just the extension
@@ -462,7 +429,7 @@ void IconBuffer::setWorkload(const std::vector<Zstring>& load)
void IconBuffer::insertIntoBuffer(const DefaultChar* entryName, const IconHolder& icon) //called by worker thread
{
- wxCriticalSectionLocker dummy(*lockIconDB);
+ boost::lock_guard<boost::mutex> dummy(lockIconDB);
//thread safety, ref-counting: (implicitly) make deep copy!
const Zstring fileNameZ = entryName;
diff --git a/library/iconBuffer.h b/library/icon_buffer.h
index 4a19af3d..9dc1ee55 100644
--- a/library/iconBuffer.h
+++ b/library/icon_buffer.h
@@ -10,12 +10,11 @@
#include <vector>
#include "../shared/zstring.h"
#include <memory>
+#include <wx/icon.h>
+#include <boost/thread/mutex.hpp>
-class wxCriticalSection;
-class wxIcon;
-
-namespace FreeFileSync
+namespace ffs3
{
class IconBuffer
@@ -50,13 +49,13 @@ private:
static IconHolder getAssociatedIconByExt(const Zstring& extension);
//---------------------- Shared Data -------------------------
- std::auto_ptr<wxCriticalSection> lockIconDB;
+ boost::mutex lockIconDB;
std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this!
std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delete oldest elements (implicitly shared by sharing Zstring with IconDB!!!)
//------------------------------------------------------------
class WorkerThread;
- WorkerThread* worker; //detached thread => destroys itself
+ std::auto_ptr<WorkerThread> worker;
};
}
diff --git a/library/pch.h b/library/pch.h
index 573ae73f..798319c7 100644
--- a/library/pch.h
+++ b/library/pch.h
@@ -8,7 +8,7 @@
#define FFS_PRECOMPILED_HEADER
//pay attention when using this file: might cause issues!
-#ifndef __WXDEBUG__
+#ifdef NDEBUG
do NOT use in release build!
#endif
@@ -102,13 +102,10 @@ do NOT use in release build!
//Boost
#include <boost/shared_ptr.hpp>
-//#include <boost/bind.hpp> <- conflict with #include <boost/lambda/bind.hpp>
#include <boost/scoped_array.hpp>
-#include <boost/lambda/lambda.hpp>
-#ifdef FFS_WIN
+#ifdef __WXMSW__
#include <wx/msw/wrapwin.h> //includes "windows.h"
-#endif //FFS_WIN
-//#####################################################
+#endif //__WXMSW__
#endif //FFS_PRECOMPILED_HEADER
diff --git a/library/processXml.cpp b/library/process_xml.cpp
index c9b641fb..e81fb3f9 100644
--- a/library/processXml.cpp
+++ b/library/process_xml.cpp
@@ -4,15 +4,15 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "processXml.h"
-#include "../shared/xmlBase.h"
+#include "process_xml.h"
+#include "../shared/xml_base.h"
#include <wx/intl.h>
#include <wx/filefn.h>
-#include "../shared/globalFunctions.h"
-#include "../shared/standardPaths.h"
-#include "../shared/stringConv.h"
+#include "../shared/global_func.h"
+#include "../shared/standard_paths.h"
+#include "../shared/string_conv.h"
-using namespace FreeFileSync;
+using namespace ffs3;
using namespace xmlAccess; //functionally needed!!!
@@ -49,7 +49,7 @@ void writeXmlLocalConfig(const FolderPairEnh& enhPair, TiXmlElement& parent);
bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc);
-void xmlAccess::readGuiConfig(const wxString& filename, xmlAccess::XmlGuiConfig& config)
+void xmlAccess::readConfig(const wxString& filename, xmlAccess::XmlGuiConfig& config)
{
//load XML
if (!wxFileExists(filename))
@@ -61,13 +61,13 @@ void xmlAccess::readGuiConfig(const wxString& filename, xmlAccess::XmlGuiConfig&
FfsXmlParser parser(doc.RootElement());
parser.readXmlGuiConfig(config); //read GUI layout configuration
- if (parser.errorsOccured())
+ if (parser.errorsOccurred())
throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\"\n\n") +
parser.getErrorMessageFormatted(), XmlError::WARNING);
}
-void xmlAccess::readBatchConfig(const wxString& filename, xmlAccess::XmlBatchConfig& config)
+void xmlAccess::readConfig(const wxString& filename, xmlAccess::XmlBatchConfig& config)
{
//load XML
if (!wxFileExists(filename))
@@ -79,13 +79,13 @@ void xmlAccess::readBatchConfig(const wxString& filename, xmlAccess::XmlBatchCon
FfsXmlParser parser(doc.RootElement());
parser.readXmlBatchConfig(config); //read GUI layout configuration
- if (parser.errorsOccured())
+ if (parser.errorsOccurred())
throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\"\n\n") +
parser.getErrorMessageFormatted(), XmlError::WARNING);
}
-void xmlAccess::readGlobalSettings(xmlAccess::XmlGlobalSettings& config)
+void xmlAccess::readConfig(xmlAccess::XmlGlobalSettings& config)
{
//load XML
if (!wxFileExists(getGlobalConfigFile()))
@@ -97,13 +97,13 @@ void xmlAccess::readGlobalSettings(xmlAccess::XmlGlobalSettings& config)
FfsXmlParser parser(doc.RootElement());
parser.readXmlGlobalSettings(config); //read GUI layout configuration
- if (parser.errorsOccured())
+ if (parser.errorsOccurred())
throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + getGlobalConfigFile() + wxT("\"\n\n") +
parser.getErrorMessageFormatted(), XmlError::WARNING);
}
-void xmlAccess::writeGuiConfig(const XmlGuiConfig& outputCfg, const wxString& filename)
+void xmlAccess::writeConfig(const XmlGuiConfig& outputCfg, const wxString& filename)
{
TiXmlDocument doc;
getDefaultXmlDocument(XML_GUI_CONFIG, doc);
@@ -116,7 +116,7 @@ void xmlAccess::writeGuiConfig(const XmlGuiConfig& outputCfg, const wxString& fi
}
-void xmlAccess::writeBatchConfig(const XmlBatchConfig& outputCfg, const wxString& filename)
+void xmlAccess::writeConfig(const XmlBatchConfig& outputCfg, const wxString& filename)
{
TiXmlDocument doc;
getDefaultXmlDocument(XML_BATCH_CONFIG, doc);
@@ -129,7 +129,7 @@ void xmlAccess::writeBatchConfig(const XmlBatchConfig& outputCfg, const wxString
}
-void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg)
+void xmlAccess::writeConfig(const XmlGlobalSettings& outputCfg)
{
TiXmlDocument doc;
getDefaultXmlDocument(XML_GLOBAL_SETTINGS, doc);
@@ -148,9 +148,9 @@ bool readXmlElement(const std::string& name, const TiXmlElement* parent, Compare
if (xmlAccess::readXmlElement(name, parent, dummy))
{
if (dummy == "ByTimeAndSize")
- output = FreeFileSync::CMP_BY_TIME_SIZE;
+ output = ffs3::CMP_BY_TIME_SIZE;
else if (dummy == "ByContent")
- output = FreeFileSync::CMP_BY_CONTENT;
+ output = ffs3::CMP_BY_CONTENT;
else
return false;
@@ -199,17 +199,17 @@ bool readXmlElement(const std::string& name, const TiXmlElement* parent, xmlAcce
}
-bool readXmlElement(const std::string& name, const TiXmlElement* parent , FreeFileSync::DeletionPolicy& output)
+bool readXmlElement(const std::string& name, const TiXmlElement* parent , ffs3::DeletionPolicy& output)
{
std::string dummy;
if (xmlAccess::readXmlElement(name, parent, dummy))
{
if (dummy == "DeletePermanently")
- output = FreeFileSync::DELETE_PERMANENTLY;
+ output = ffs3::DELETE_PERMANENTLY;
else if (dummy == "MoveToRecycleBin")
- output = FreeFileSync::MOVE_TO_RECYCLE_BIN;
+ output = ffs3::MOVE_TO_RECYCLE_BIN;
else if (dummy == "MoveToCustomDirectory")
- output = FreeFileSync::MOVE_TO_CUSTOM_DIRECTORY;
+ output = ffs3::MOVE_TO_CUSTOM_DIRECTORY;
else
return false;
@@ -219,17 +219,17 @@ bool readXmlElement(const std::string& name, const TiXmlElement* parent , FreeFi
}
-bool readXmlElement(const std::string& name, const TiXmlElement* parent , FreeFileSync::SymLinkHandling& output)
+bool readXmlElement(const std::string& name, const TiXmlElement* parent , ffs3::SymLinkHandling& output)
{
std::string dummy;
if (xmlAccess::readXmlElement(name, parent, dummy))
{
if (dummy == "Ignore")
- output = FreeFileSync::SYMLINK_IGNORE;
+ output = ffs3::SYMLINK_IGNORE;
else if (dummy == "UseDirectly")
- output = FreeFileSync::SYMLINK_USE_DIRECTLY;
+ output = ffs3::SYMLINK_USE_DIRECTLY;
else if (dummy == "FollowLink")
- output = FreeFileSync::SYMLINK_FOLLOW_LINK;
+ output = ffs3::SYMLINK_FOLLOW_LINK;
else
return false;
@@ -318,9 +318,6 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg)
//read compare variant
readXmlElementLogging("Variant", cmpSettings, mainCfg.compareVar);
- //max. allowed file time deviation
- readXmlElementLogging("FileTimeTolerance", cmpSettings, mainCfg.hidden.fileTimeTolerance);
-
//include symbolic links at all?
readXmlElementLogging("HandleSymlinks", cmpSettings, mainCfg.handleSymlinks);
@@ -338,12 +335,6 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg)
readXmlElementLogging("Conflict", syncDirections, mainCfg.syncConfiguration.conflict);
//###########################################################
- const TiXmlElement* syncConfig = hRoot.FirstChild("MainConfig").FirstChild("Synchronization").ToElement();
-
- //verify file copying
- readXmlElementLogging("VerifyCopiedFiles", syncConfig, mainCfg.hidden.verifyFileCopy);
-
-//###########################################################
const TiXmlElement* miscSettings = hRoot.FirstChild("MainConfig").FirstChild("Miscellaneous").ToElement();
//misc
@@ -430,6 +421,15 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg
//copy locked files using VSS
readXmlElementLogging("CopyLockedFiles", global, outputCfg.copyLockedFiles);
+ //file permissions
+ readXmlElementLogging("CopyFilePermissions", global, outputCfg.copyFilePermissions);
+
+ //verify file copying
+ readXmlElementLogging("VerifyCopiedFiles", global, outputCfg.verifyFileCopy);
+
+ //max. allowed file time deviation
+ readXmlElementLogging("FileTimeTolerance", global, outputCfg.fileTimeTolerance);
+
const TiXmlElement* optionalDialogs = TiXmlHandleConst(getRoot()).FirstChild("Shared").FirstChild("ShowOptionalDialogs").ToElement();
@@ -559,10 +559,10 @@ void addXmlElement(const std::string& name, const CompareVariant variant, TiXmlE
{
switch (variant)
{
- case FreeFileSync::CMP_BY_TIME_SIZE:
+ case ffs3::CMP_BY_TIME_SIZE:
xmlAccess::addXmlElement(name, std::string("ByTimeAndSize"), parent);
break;
- case FreeFileSync::CMP_BY_CONTENT:
+ case ffs3::CMP_BY_CONTENT:
xmlAccess::addXmlElement(name, std::string("ByContent"), parent);
break;
}
@@ -603,34 +603,34 @@ void addXmlElement(const std::string& name, const xmlAccess::OnError value, TiXm
}
-void addXmlElement(const std::string& name, const FreeFileSync::DeletionPolicy value, TiXmlElement* parent)
+void addXmlElement(const std::string& name, const ffs3::DeletionPolicy value, TiXmlElement* parent)
{
switch (value)
{
- case FreeFileSync::DELETE_PERMANENTLY:
+ case ffs3::DELETE_PERMANENTLY:
xmlAccess::addXmlElement(name, std::string("DeletePermanently"), parent);
break;
- case FreeFileSync::MOVE_TO_RECYCLE_BIN:
+ case ffs3::MOVE_TO_RECYCLE_BIN:
xmlAccess::addXmlElement(name, std::string("MoveToRecycleBin"), parent);
break;
- case FreeFileSync::MOVE_TO_CUSTOM_DIRECTORY:
+ case ffs3::MOVE_TO_CUSTOM_DIRECTORY:
xmlAccess::addXmlElement(name, std::string("MoveToCustomDirectory"), parent);
break;
}
}
-void addXmlElement(const std::string& name, const FreeFileSync::SymLinkHandling value, TiXmlElement* parent)
+void addXmlElement(const std::string& name, const ffs3::SymLinkHandling value, TiXmlElement* parent)
{
switch (value)
{
- case FreeFileSync::SYMLINK_IGNORE:
+ case ffs3::SYMLINK_IGNORE:
xmlAccess::addXmlElement(name, std::string("Ignore"), parent);
break;
- case FreeFileSync::SYMLINK_USE_DIRECTLY:
+ case ffs3::SYMLINK_USE_DIRECTLY:
xmlAccess::addXmlElement(name, std::string("UseDirectly"), parent);
break;
- case FreeFileSync::SYMLINK_FOLLOW_LINK:
+ case ffs3::SYMLINK_FOLLOW_LINK:
xmlAccess::addXmlElement(name, std::string("FollowLink"), parent);
break;
}
@@ -704,11 +704,6 @@ void writeXmlLocalConfig(const FolderPairEnh& enhPair, TiXmlElement& parent)
bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc)
{
- //reset hidden settings: we don't want implicit behaviour! Hidden settings are loaded but changes are not saved!
- MainConfiguration mainCfgLocal = mainCfg;
- mainCfgLocal.hidden = HiddenSettings();
-
-
TiXmlElement* root = doc.RootElement();
if (!root) return false;
@@ -720,34 +715,27 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc)
settings->LinkEndChild(cmpSettings);
//write compare algorithm
- addXmlElement("Variant", mainCfgLocal.compareVar, cmpSettings);
-
- //max. allowed file time deviation
- addXmlElement("FileTimeTolerance", mainCfgLocal.hidden.fileTimeTolerance, cmpSettings);
+ addXmlElement("Variant", mainCfg.compareVar, cmpSettings);
//include symbolic links at all?
- addXmlElement("HandleSymlinks", mainCfgLocal.handleSymlinks, cmpSettings);
+ addXmlElement("HandleSymlinks", mainCfg.handleSymlinks, cmpSettings);
//###########################################################
TiXmlElement* syncSettings = new TiXmlElement("Synchronization");
settings->LinkEndChild(syncSettings);
//write sync configuration
- addXmlElement("Automatic", mainCfgLocal.syncConfiguration.automatic, syncSettings);
+ addXmlElement("Automatic", mainCfg.syncConfiguration.automatic, syncSettings);
TiXmlElement* syncDirections = new TiXmlElement("Directions");
syncSettings->LinkEndChild(syncDirections);
- addXmlElement("LeftOnly", mainCfgLocal.syncConfiguration.exLeftSideOnly, syncDirections);
- addXmlElement("RightOnly", mainCfgLocal.syncConfiguration.exRightSideOnly, syncDirections);
- addXmlElement("LeftNewer", mainCfgLocal.syncConfiguration.leftNewer, syncDirections);
- addXmlElement("RightNewer", mainCfgLocal.syncConfiguration.rightNewer, syncDirections);
- addXmlElement("Different", mainCfgLocal.syncConfiguration.different, syncDirections);
- addXmlElement("Conflict", mainCfgLocal.syncConfiguration.conflict, syncDirections);
-
-//###########################################################
- //verify file copying
- addXmlElement("VerifyCopiedFiles", mainCfgLocal.hidden.verifyFileCopy, syncSettings);
+ addXmlElement("LeftOnly", mainCfg.syncConfiguration.exLeftSideOnly, syncDirections);
+ addXmlElement("RightOnly", mainCfg.syncConfiguration.exRightSideOnly, syncDirections);
+ addXmlElement("LeftNewer", mainCfg.syncConfiguration.leftNewer, syncDirections);
+ addXmlElement("RightNewer", mainCfg.syncConfiguration.rightNewer, syncDirections);
+ addXmlElement("Different", mainCfg.syncConfiguration.different, syncDirections);
+ addXmlElement("Conflict", mainCfg.syncConfiguration.conflict, syncDirections);
//###########################################################
TiXmlElement* miscSettings = new TiXmlElement("Miscellaneous");
@@ -757,22 +745,22 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc)
TiXmlElement* filter = new TiXmlElement("Filter");
miscSettings->LinkEndChild(filter);
- addXmlElement("Include", mainCfgLocal.globalFilter.includeFilter, filter);
- addXmlElement("Exclude", mainCfgLocal.globalFilter.excludeFilter, filter);
+ addXmlElement("Include", mainCfg.globalFilter.includeFilter, filter);
+ addXmlElement("Exclude", mainCfg.globalFilter.excludeFilter, filter);
//other
- addXmlElement("DeletionPolicy", mainCfgLocal.handleDeletion, miscSettings);
- addXmlElement("CustomDeletionFolder", mainCfgLocal.customDeletionDirectory, miscSettings);
+ addXmlElement("DeletionPolicy", mainCfg.handleDeletion, miscSettings);
+ addXmlElement("CustomDeletionFolder", mainCfg.customDeletionDirectory, miscSettings);
//###########################################################
TiXmlElement* pairs = new TiXmlElement("FolderPairs");
settings->LinkEndChild(pairs);
//write first folder pair
- writeXmlLocalConfig(mainCfgLocal.firstPair, *pairs);
+ writeXmlLocalConfig(mainCfg.firstPair, *pairs);
//write additional folder pairs
- for (std::vector<FolderPairEnh>::const_iterator i = mainCfgLocal.additionalPairs.begin(); i != mainCfgLocal.additionalPairs.end(); ++i)
+ for (std::vector<FolderPairEnh>::const_iterator i = mainCfg.additionalPairs.begin(); i != mainCfg.additionalPairs.end(); ++i)
writeXmlLocalConfig(*i, *pairs);
return true;
@@ -842,6 +830,15 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD
//copy locked files using VSS
addXmlElement("CopyLockedFiles", inputCfg.copyLockedFiles, global);
+ //file permissions
+ addXmlElement("CopyFilePermissions", inputCfg.copyFilePermissions, global);
+
+ //verify file copying
+ addXmlElement("VerifyCopiedFiles", inputCfg.verifyFileCopy, global);
+
+ //max. allowed file time deviation
+ addXmlElement("FileTimeTolerance", inputCfg.fileTimeTolerance, global);
+
//optional dialogs
TiXmlElement* optionalDialogs = new TiXmlElement("ShowOptionalDialogs");
@@ -984,6 +981,12 @@ int xmlAccess::retrieveSystemLanguage()
}
+wxString xmlAccess::getGlobalConfigFile()
+{
+ return ffs3::getConfigDir() + wxT("GlobalSettings.xml");
+}
+
+
void xmlAccess::OptionalDialogs::resetDialogs()
{
warningDependentFolders = true;
@@ -998,40 +1001,137 @@ void xmlAccess::OptionalDialogs::resetDialogs()
xmlAccess::XmlGuiConfig xmlAccess::convertBatchToGui(const xmlAccess::XmlBatchConfig& batchCfg)
{
- xmlAccess::XmlGuiConfig output;
+ XmlGuiConfig output;
output.mainCfg = batchCfg.mainCfg;
return output;
}
-void xmlAccess::readGuiOrBatchConfig(const wxString& filename, XmlGuiConfig& config) //throw (xmlAccess::XmlError);
+xmlAccess::XmlBatchConfig xmlAccess::convertGuiToBatch(const xmlAccess::XmlGuiConfig& guiCfg)
{
- if (xmlAccess::getXmlType(filename) != xmlAccess::XML_BATCH_CONFIG)
+ XmlBatchConfig output;
+ output.mainCfg = guiCfg.mainCfg;
+
+ if (guiCfg.ignoreErrors)
+ output.handleError = xmlAccess::ON_ERROR_IGNORE;
+ else
+ output.handleError = xmlAccess::ON_ERROR_POPUP;
+
+ return output;
+}
+
+
+xmlAccess::MergeType xmlAccess::getMergeType(const std::vector<wxString>& filenames) //throw ()
+{
+ bool guiCfgExists = false;
+ bool batchCfgExists = false;
+
+ for (std::vector<wxString>::const_iterator i = filenames.begin(); i != filenames.end(); ++i)
{
- xmlAccess::readGuiConfig(filename, config);
- return;
+ switch (xmlAccess::getXmlType(*i)) //throw()
+ {
+ case XML_GUI_CONFIG:
+ guiCfgExists = true;
+ break;
+
+ case XML_BATCH_CONFIG:
+ batchCfgExists = true;
+ break;
+
+ case XML_GLOBAL_SETTINGS:
+ case XML_REAL_CONFIG:
+ case XML_OTHER:
+ return MERGE_OTHER;
+ }
}
- //convert batch config to gui config
- xmlAccess::XmlBatchConfig batchCfg;
+ if (guiCfgExists && batchCfgExists)
+ return MERGE_GUI_BATCH;
+ else if (guiCfgExists && !batchCfgExists)
+ return MERGE_GUI;
+ else if (!guiCfgExists && batchCfgExists)
+ return MERGE_BATCH;
+ else
+ return MERGE_OTHER;
+}
+
+
+namespace
+{
+template <class XmlCfg>
+XmlCfg loadCfgImpl(const wxString& filename, std::auto_ptr<xmlAccess::XmlError>& exeption) //throw (xmlAccess::XmlError)
+{
+ XmlCfg cfg;
try
{
- xmlAccess::readBatchConfig(filename, batchCfg); //throw (xmlAccess::XmlError);
+ xmlAccess::readConfig(filename, cfg); //throw (xmlAccess::XmlError);
}
catch (const xmlAccess::XmlError& e)
{
- if (e.getSeverity() != xmlAccess::XmlError::WARNING)
+ if (e.getSeverity() == xmlAccess::XmlError::FATAL)
throw;
+ else
+ exeption.reset(new xmlAccess::XmlError(e));
+ }
+ return cfg;
+}
+
+
+template <class XmlCfg>
+void mergeConfigFilesImpl(const std::vector<wxString>& filenames, XmlCfg& config) //throw (xmlAccess::XmlError)
+{
+ using namespace xmlAccess;
- config = convertBatchToGui(batchCfg); //do work despite parsing errors, then re-throw
- throw; //
+ assert(!filenames.empty());
+ if (filenames.empty())
+ return;
+
+ std::vector<ffs3::MainConfiguration> mainCfgs;
+ std::auto_ptr<XmlError> savedException;
+
+ for (std::vector<wxString>::const_iterator i = filenames.begin(); i != filenames.end(); ++i)
+ {
+ switch (getXmlType(*i))
+ {
+ case XML_GUI_CONFIG:
+ mainCfgs.push_back(loadCfgImpl<XmlGuiConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError)
+ break;
+
+ case XML_BATCH_CONFIG:
+ mainCfgs.push_back(loadCfgImpl<XmlBatchConfig>(*i, savedException).mainCfg); //throw (xmlAccess::XmlError)
+ break;
+
+ case XML_GLOBAL_SETTINGS:
+ case XML_REAL_CONFIG:
+ case XML_OTHER:
+ break;
+ }
}
- config = convertBatchToGui(batchCfg);
+ if (mainCfgs.empty())
+ throw XmlError(_("Invalid FreeFileSync config file!"));
+
+ try //...to init all non-"mainCfg" settings with first config file
+ {
+ xmlAccess::readConfig(filenames[0], config); //throw (xmlAccess::XmlError);
+ }
+ catch (...) {}
+
+ config.mainCfg = merge(mainCfgs);
+
+ if (savedException.get()) //"re-throw" exception
+ throw *savedException;
+}
}
-wxString xmlAccess::getGlobalConfigFile()
+void xmlAccess::convertConfig(const std::vector<wxString>& filenames, XmlGuiConfig& config) //throw (xmlAccess::XmlError)
+{
+ mergeConfigFilesImpl(filenames, config); //throw (xmlAccess::XmlError)
+}
+
+
+void xmlAccess::convertConfig(const std::vector<wxString>& filenames, XmlBatchConfig& config) //throw (xmlAccess::XmlError);
{
- return FreeFileSync::getConfigDir() + wxT("GlobalSettings.xml");
+ mergeConfigFilesImpl(filenames, config); //throw (xmlAccess::XmlError)
}
diff --git a/library/processXml.h b/library/process_xml.h
index b46f0163..22465739 100644
--- a/library/processXml.h
+++ b/library/process_xml.h
@@ -8,7 +8,7 @@
#define PROCESSXML_H_INCLUDED
#include "../structures.h"
-#include "../shared/xmlError.h"
+#include "../shared/xml_error.h"
namespace xmlAccess
@@ -54,7 +54,7 @@ struct XmlGuiConfig
ignoreErrors(false),
syncPreviewEnabled(true) {} //initialize values
- FreeFileSync::MainConfiguration mainCfg;
+ ffs3::MainConfiguration mainCfg;
bool hideFilteredElements;
bool ignoreErrors; //reaction on error situation during synchronization
@@ -79,13 +79,14 @@ struct XmlBatchConfig
{
XmlBatchConfig() : silent(false), handleError(ON_ERROR_POPUP) {}
- FreeFileSync::MainConfiguration mainCfg;
+ ffs3::MainConfiguration mainCfg;
bool silent;
wxString logFileDirectory;
OnError handleError; //reaction on error situation during synchronization
};
+
int retrieveSystemLanguage();
@@ -117,12 +118,18 @@ struct XmlGlobalSettings
XmlGlobalSettings() :
programLanguage(retrieveSystemLanguage()),
ignoreOneHourDiff(false),
- copyLockedFiles(true)
- {}
+ copyLockedFiles(true),
+ copyFilePermissions(false),
+ fileTimeTolerance(2), //default 2s: FAT vs NTFS
+ verifyFileCopy(false) {}
int programLanguage;
bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change
bool copyLockedFiles; //VSS usage
+ bool copyFilePermissions;
+
+ size_t fileTimeTolerance; //max. allowed file time deviation
+ bool verifyFileCopy; //verify copied files
OptionalDialogs optDialogs;
@@ -229,16 +236,31 @@ bool sortByPositionAndVisibility(const ColumnAttrib& a, const ColumnAttrib& b)
return a.position < b.position;
}
-void readGuiConfig( const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError);
-void readBatchConfig(const wxString& filename, XmlBatchConfig& config); //throw (xmlAccess::XmlError);
-void readGlobalSettings( XmlGlobalSettings& config); //throw (xmlAccess::XmlError);
+void readConfig(const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError)
+void readConfig(const wxString& filename, XmlBatchConfig& config); //throw (xmlAccess::XmlError)
+void readConfig( XmlGlobalSettings& config); //throw (xmlAccess::XmlError)
+
+void writeConfig(const XmlGuiConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError)
+void writeConfig(const XmlBatchConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError)
+void writeConfig(const XmlGlobalSettings& outputCfg); //throw (xmlAccess::XmlError)
+
+//config conversion utilities
+XmlGuiConfig convertBatchToGui(const XmlBatchConfig& batchCfg);
+XmlBatchConfig convertGuiToBatch(const XmlGuiConfig& guiCfg);
-void readGuiOrBatchConfig(const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError);
-XmlGuiConfig convertBatchToGui(const XmlBatchConfig& batchCfg);
-void writeGuiConfig( const XmlGuiConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError);
-void writeBatchConfig( const XmlBatchConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError);
-void writeGlobalSettings(const XmlGlobalSettings& outputCfg); //throw (xmlAccess::XmlError);
+//convert (multiple) *.ffs_gui, *.ffs_batch files or combinations of both into target config structure:
+enum MergeType
+{
+ MERGE_GUI, //pure gui config files
+ MERGE_BATCH, // " batch "
+ MERGE_GUI_BATCH, //gui and batch files
+ MERGE_OTHER
+};
+MergeType getMergeType(const std::vector<wxString>& filenames); //throw ()
+
+void convertConfig(const std::vector<wxString>& filenames, XmlGuiConfig& config); //throw (xmlAccess::XmlError)
+void convertConfig(const std::vector<wxString>& filenames, XmlBatchConfig& config); //throw (xmlAccess::XmlError)
}
diff --git a/library/resources.cpp b/library/resources.cpp
index 2104efc3..637dfea3 100644
--- a/library/resources.cpp
+++ b/library/resources.cpp
@@ -10,12 +10,12 @@
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/mstream.h>
-#include "../shared/stringConv.h"
-#include "../shared/systemConstants.h"
+#include "../shared/string_conv.h"
+#include "../shared/system_constants.h"
#include <memory>
-#include "../shared/standardPaths.h"
+#include "../shared/standard_paths.h"
-using namespace FreeFileSync;
+using namespace ffs3;
const GlobalResources& GlobalResources::getInstance()
@@ -67,7 +67,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation)
void GlobalResources::load() const
{
- wxFFileInputStream input(FreeFileSync::getResourceDir() + wxT("Resources.dat"));
+ wxFFileInputStream input(ffs3::getResourceDir() + wxT("Resources.dat"));
if (input.IsOk()) //if not... we don't want to react too harsh here
{
//activate support for .png files
diff --git a/library/softFilter.cpp b/library/soft_filter.cpp
index 496c185e..18dcfd54 100644
--- a/library/softFilter.cpp
+++ b/library/soft_filter.cpp
@@ -4,7 +4,7 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "softFilter.h"
+#include "soft_filter.h"
diff --git a/library/softFilter.h b/library/soft_filter.h
index 275aa9bd..dc889245 100644
--- a/library/softFilter.h
+++ b/library/soft_filter.h
@@ -7,7 +7,7 @@
#ifndef SOFTFILTER_H_INCLUDED
#define SOFTFILTER_H_INCLUDED
-#include "../fileHierarchy.h"
+#include "../file_hierarchy.h"
#include <wx/timer.h>
/*
Semantics of SoftFilter:
@@ -18,7 +18,7 @@ Semantics of SoftFilter:
-> SoftFilter is equivalent to a user temporarily (de-)selecting rows
*/
-namespace FreeFileSync
+namespace ffs3
{
class SoftFilter
diff --git a/library/statistics.cpp b/library/statistics.cpp
index 3a6970d9..d246a7cc 100644
--- a/library/statistics.cpp
+++ b/library/statistics.cpp
@@ -7,13 +7,13 @@
#include "statistics.h"
#include <wx/ffile.h>
-#include "../shared/globalFunctions.h"
-#include "statusHandler.h"
-//#include "../algorithm.h"
+#include "../shared/global_func.h"
+#include "status_handler.h"
#include "../shared/util.h"
#include <wx/intl.h>
#include <limits>
#include <wx/stopwatch.h>
+#include "../shared/assert_static.h"
RetrieveStatistics::RetrieveStatistics() :
@@ -31,7 +31,7 @@ RetrieveStatistics::~RetrieveStatistics()
for (std::vector<statEntry>::const_iterator i = data.begin(); i != data.end(); ++i)
{
- using globalFunctions::numberToString;
+ using common::numberToString;
outputFile.Write(numberToString(i->time));
outputFile.Write(wxT(";"));
outputFile.Write(numberToString(i->objects));
@@ -53,42 +53,42 @@ void RetrieveStatistics::writeEntry(const double value, const int objects)
//########################################################################################
-
+namespace
+{
+template <class T>
inline
-bool isNull(double number)
+bool isNull(T number)
{
- return globalFunctions::abs(number) < std::numeric_limits<double>::epsilon();
+ return common::abs(number) <= std::numeric_limits<T>::epsilon(); //epsilon == 0 for integer types, therefore less-equal(!)
+}
}
inline
wxString Statistics::formatRemainingTime(double timeInMs) const
{
-#ifndef _MSC_VER
-#warning adapt units "%x sec"
-#endif
-
bool unitSec = true;
double remainingTime = timeInMs / 1000;
- wxString unit = _(" sec");
+
+ wxString output = _("%x sec");
if (remainingTime > 55)
{
unitSec = false;
remainingTime /= 60;
- unit = _(" min");
+ output = _("%x min");
if (remainingTime > 59)
{
remainingTime /= 60;
- unit = _(" hour(s)");
+ output = _("%x hour(s)");
if (remainingTime > 23)
{
remainingTime /= 24;
- unit = _(" day(s)");
+ output = _("%x day(s)");
}
}
}
- int formattedTime = globalFunctions::round(remainingTime);
+ int formattedTime = common::round(remainingTime);
//reduce precision to 5 seconds
if (unitSec && formattedTime % 5 != 0)
@@ -100,7 +100,7 @@ wxString Statistics::formatRemainingTime(double timeInMs) const
{
if (unitSec)
{
- formattedTime = globalFunctions::round(remainingTime);
+ formattedTime = common::round(remainingTime);
formattedTime -= formattedTime % 5; //"floor"
}
else
@@ -108,8 +108,10 @@ wxString Statistics::formatRemainingTime(double timeInMs) const
}
remainingTimeLast = formattedTime;
- return globalFunctions::numberToString(formattedTime) + unit;
- //+ wxT("(") + globalFunctions::numberToWxString(globalFunctions::round(timeInMs / 1000)) + wxT(")");
+ output.Replace(wxT("%x"), common::numberToString(formattedTime));
+
+ return output;
+ //+ wxT("(") + common::numberToWxString(common::round(timeInMs / 1000)) + wxT(")");
}
@@ -191,7 +193,7 @@ wxString Statistics::getBytesPerSecond() const
const double dataDelta = measurements.back().data - frontElement->data;
if (!isNull(timeDelta))
- return FreeFileSync::formatFilesizeToShortString(dataDelta * 1000 / timeDelta) + _("/sec");
+ return ffs3::formatFilesizeToShortString(dataDelta * 1000 / timeDelta) + _("/sec");
}
return wxT("-"); //fallback
diff --git a/library/statistics.h b/library/statistics.h
index ba9d8afb..26e8c196 100644
--- a/library/statistics.h
+++ b/library/statistics.h
@@ -11,6 +11,8 @@
#include <list>
#include <memory>
#include <wx/defs.h>
+
+
#include <wx/string.h>
class wxStopWatch;
diff --git a/library/statusHandler.cpp b/library/status_handler.cpp
index 7ac46134..0f953a32 100644
--- a/library/statusHandler.cpp
+++ b/library/status_handler.cpp
@@ -4,7 +4,7 @@
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
// **************************************************************************
//
-#include "statusHandler.h"
+#include "status_handler.h"
#include <wx/app.h>
#include <wx/timer.h>
diff --git a/library/statusHandler.h b/library/status_handler.h
index a1226c54..a1226c54 100644
--- a/library/statusHandler.h
+++ b/library/status_handler.h
bgstack15