diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/CustomGrid.cpp | 10 | ||||
-rw-r--r-- | library/CustomGrid.h | 2 | ||||
-rw-r--r-- | library/Taskbar_Seven/Taskbar_Seven.vcproj | 409 | ||||
-rw-r--r-- | library/Taskbar_Seven/dllmain.cpp | 27 | ||||
-rw-r--r-- | library/Taskbar_Seven/taskbar.cpp | 160 | ||||
-rw-r--r-- | library/Taskbar_Seven/taskbar.h | 62 | ||||
-rw-r--r-- | library/binary.cpp | 99 | ||||
-rw-r--r-- | library/binary.h | 2 | ||||
-rw-r--r-- | library/dbFile.cpp | 419 | ||||
-rw-r--r-- | library/dbFile.h | 20 | ||||
-rw-r--r-- | library/filter.cpp | 4 | ||||
-rw-r--r-- | library/filter.h | 17 | ||||
-rw-r--r-- | library/processXml.cpp | 81 | ||||
-rw-r--r-- | library/processXml.h | 10 | ||||
-rw-r--r-- | library/softFilter.cpp | 10 | ||||
-rw-r--r-- | library/softFilter.h | 79 | ||||
-rw-r--r-- | library/statistics.cpp | 10 |
17 files changed, 1259 insertions, 162 deletions
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp index a04548a3..e9fe9eb6 100644 --- a/library/CustomGrid.cpp +++ b/library/CustomGrid.cpp @@ -8,7 +8,7 @@ #include "../shared/systemConstants.h" #include "resources.h" #include <wx/dc.h> -#include "../ui/util.h" +#include "../shared/util.h" #include "../shared/stringConv.h" #include "resources.h" #include <typeinfo> @@ -296,7 +296,7 @@ protected: case xmlAccess::DIRECTORY: return zToWx(fileObj->getBaseDirPf<side>()); case xmlAccess::SIZE: //file size - return FreeFileSync::includeNumberSeparator(fileObj->getFileSize<side>().ToString()); + return FreeFileSync::numberToWxString(fileObj->getFileSize<side>(), true); case xmlAccess::DATE: //date return FreeFileSync::utcTimeToLocalString(fileObj->getLastWriteTime<side>(), fileObj->getFullName<side>()); case xmlAccess::EXTENSION: //file extension @@ -896,14 +896,14 @@ void CustomGrid::DrawColLabel(wxDC& dc, int col) } -std::set<unsigned int> CustomGrid::getAllSelectedRows() const +std::set<size_t> CustomGrid::getAllSelectedRows() const { - std::set<unsigned int> output; + std::set<size_t> output; const wxArrayInt selectedRows = this->GetSelectedRows(); if (!selectedRows.IsEmpty()) { - for (unsigned int i = 0; i < selectedRows.GetCount(); ++i) + for (size_t i = 0; i < selectedRows.GetCount(); ++i) output.insert(selectedRows[i]); } diff --git a/library/CustomGrid.h b/library/CustomGrid.h index 7a0d1b10..35915811 100644 --- a/library/CustomGrid.h +++ b/library/CustomGrid.h @@ -65,7 +65,7 @@ public: CustomGridRight* gridRight, const FreeFileSync::GridView* gridDataView); - std::set<unsigned int> getAllSelectedRows() const; + std::set<size_t> getAllSelectedRows() const; //set sort direction indicator on UI typedef int SortColumn; diff --git a/library/Taskbar_Seven/Taskbar_Seven.vcproj b/library/Taskbar_Seven/Taskbar_Seven.vcproj new file mode 100644 index 00000000..bf8e0993 --- /dev/null +++ b/library/Taskbar_Seven/Taskbar_Seven.vcproj @@ -0,0 +1,409 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9,00" + Name="Taskbar_Seven" + ProjectGUID="{70394AEF-5897-4911-AFA1-82EAF0581EFA}" + RootNamespace="ShadowDll" + Keyword="Win32Proj" + TargetFrameworkVersion="196613" + > + <Platforms> + <Platform + Name="Win32" + /> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + IntermediateDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + ConfigurationType="2" + CharacterSet="1" + BuildLogFile="$(IntDir)\Build.html" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + SuppressStartupBanner="false" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Taskbar7_$(PlatformName).dll" + LinkIncremental="1" + SuppressStartupBanner="false" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)$(TargetName).pdb" + SubSystem="2" + ProfileGuidedDatabase="" + ImportLibrary="$(IntDir)$(TargetName).lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Debug|x64" + OutputDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + IntermediateDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + ConfigurationType="2" + CharacterSet="1" + BuildLogFile="$(IntDir)\Build.html" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TargetEnvironment="3" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="_DEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + SuppressStartupBanner="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Taskbar7_$(PlatformName).dll" + LinkIncremental="1" + SuppressStartupBanner="false" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(IntDir)$(TargetName).pdb" + SubSystem="2" + ProfileGuidedDatabase="" + ImportLibrary="$(IntDir)$(TargetName).lib" + TargetMachine="17" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + IntermediateDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + ConfigurationType="2" + CharacterSet="1" + WholeProgramOptimization="1" + BuildLogFile="$(IntDir)\Build.html" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + PreprocessorDefinitions="NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + UsePrecompiledHeader="0" + WarningLevel="3" + SuppressStartupBanner="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Taskbar7_$(PlatformName).dll" + LinkIncremental="1" + SuppressStartupBanner="false" + GenerateDebugInformation="false" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + LinkTimeCodeGeneration="1" + ProfileGuidedDatabase="" + ImportLibrary="$(IntDir)$(TargetName).lib" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + OutputDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + IntermediateDirectory="OBJ\$(ProjectName)_$(ConfigurationName)_$(PlatformName)\" + ConfigurationType="2" + CharacterSet="1" + WholeProgramOptimization="1" + BuildLogFile="$(IntDir)\Build.html" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + TargetEnvironment="3" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + EnableIntrinsicFunctions="true" + PreprocessorDefinitions="NDEBUG;_WINDOWS;_USRDLL;TASKBAR_SEVEN_DLL_EXPORTS" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + UsePrecompiledHeader="0" + WarningLevel="3" + SuppressStartupBanner="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="Taskbar7_$(PlatformName).dll" + LinkIncremental="1" + SuppressStartupBanner="false" + GenerateDebugInformation="false" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + LinkTimeCodeGeneration="1" + ProfileGuidedDatabase="" + ImportLibrary="$(IntDir)$(TargetName).lib" + TargetMachine="17" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Quelldateien" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\dllmain.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Debug|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + > + <Tool + Name="VCCLCompilerTool" + UsePrecompiledHeader="0" + CompileAsManaged="0" + /> + </FileConfiguration> + </File> + <File + RelativePath=".\taskbar.cpp" + > + </File> + </Filter> + <Filter + Name="Headerdateien" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\taskbar.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/library/Taskbar_Seven/dllmain.cpp b/library/Taskbar_Seven/dllmain.cpp new file mode 100644 index 00000000..7db39bff --- /dev/null +++ b/library/Taskbar_Seven/dllmain.cpp @@ -0,0 +1,27 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/library/Taskbar_Seven/taskbar.cpp b/library/Taskbar_Seven/taskbar.cpp new file mode 100644 index 00000000..4baf2392 --- /dev/null +++ b/library/Taskbar_Seven/taskbar.cpp @@ -0,0 +1,160 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include "taskbar.h" + +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#include <ShObjIdl.h> + +#include <map> +#include <string> +#include <comdef.h> + + +namespace +{ +void writeString(const std::wstring& input, wchar_t* output, size_t outputBufferLen) +{ + const size_t newSize = min(input.length() + 1, outputBufferLen); //including null-termination + memcpy(output, input.c_str(), newSize * sizeof(wchar_t)); + output[newSize-1] = 0; //if output buffer is too small... +} + + +std::wstring numberToHexString(const long number) +{ + wchar_t result[100]; + swprintf(result, 100, L"0x%08x", number); + return std::wstring(result); +} + + +std::wstring writeErrorMsg(const wchar_t* input, HRESULT hr) +{ + std::wstring output(input); + output += L" ("; + output += numberToHexString(hr); + output += L": "; + output += _com_error(hr).ErrorMessage(); + output += L")"; + return output; +} + + +using TaskbarSeven::TBHandle; +typedef std::map<TBHandle, ITaskbarList3*> TaskBarHandleMap; + +TaskbarSeven::TBHandle generateHandle() +{ + static TBHandle handle = 0; + return ++handle; //don't return 0! 0 is reserved for indicating failure +} + +TaskBarHandleMap taskBarHandles; + +std::wstring lastErrorMessage; +} +//################################################################################################## + + +TaskbarSeven::TBHandle TaskbarSeven::init() //call on app initializaiton; returns handle +{ + ITaskbarList3* pto = NULL; + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, + NULL, + CLSCTX_ALL, + IID_PPV_ARGS(&pto)); + if (FAILED(hr)) + { + lastErrorMessage = writeErrorMsg(L"Error calling \"CoCreateInstance\".", hr); + return 0; + } + + TBHandle newHandle = ::generateHandle(); + taskBarHandles[newHandle] = pto; + return newHandle; +} + + +void TaskbarSeven::release(TBHandle handle) //release handle on app exit +{ + TaskBarHandleMap::const_iterator iter = taskBarHandles.find(handle); + if (iter != taskBarHandles.end()) + { + if (iter->second != NULL) + iter->second->Release(); + taskBarHandles.erase(iter); + } +} + + +bool TaskbarSeven::setStatus(TBHandle handle, + void* hwnd, //HWND: window assciated to the taskbar icon + TaskBarStatus status) +{ + TBPFLAG flag = TBPF_NORMAL; + switch (status) + { + case STATUS_NOPROGRESS: + flag = TBPF_NOPROGRESS; + break; + case STATUS_INDETERMINATE: + flag = TBPF_INDETERMINATE; + break; + case STATUS_NORMAL: + flag = TBPF_NORMAL; + break; + case STATUS_ERROR: + flag = TBPF_ERROR; + break; + case STATUS_PAUSED: + flag = TBPF_PAUSED; + break; + } + + ITaskbarList3* pto = taskBarHandles[handle]; + if (pto) + { + HRESULT hr = pto->SetProgressState(static_cast<HWND>(hwnd), //[in] HWND hwnd, + flag); //[in] TBPFLAG tbpFlags + if (FAILED(hr)) + { + lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressState\".", hr); + return false; + } + } + return true; +} + + +bool TaskbarSeven::setProgress(TBHandle handle, + void* hwnd, //HWND: window assciated to the taskbar icon + size_t current, + size_t total) +{ + ITaskbarList3* pto = taskBarHandles[handle]; + + if (pto) + { + HRESULT hr = pto->SetProgressValue( + static_cast<HWND>(hwnd), //[in] HWND hwnd, + current, //[in] ULONGLONG ullCompleted, + total); //[in] ULONGLONG ullTotal + if (FAILED(hr)) + { + lastErrorMessage = writeErrorMsg(L"Error calling \"SetProgressValue\".", hr); + return false; + } + } + return true; +} + + +void TaskbarSeven::getLastError(wchar_t* errorMessage, size_t errorBufferLen) +{ + writeString(lastErrorMessage, errorMessage, errorBufferLen); +} diff --git a/library/Taskbar_Seven/taskbar.h b/library/Taskbar_Seven/taskbar.h new file mode 100644 index 00000000..835f02ec --- /dev/null +++ b/library/Taskbar_Seven/taskbar.h @@ -0,0 +1,62 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef TASKBAR_SEVEN_DLL_H +#define TASKBAR_SEVEN_DLL_H + +#ifdef TASKBAR_SEVEN_DLL_EXPORTS +#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllexport) +#else +#define DLL_FUNCTION_DECLARATION extern "C" __declspec(dllimport) +#endif + + +namespace TaskbarSeven +{ +enum TaskBarStatus +{ + STATUS_NOPROGRESS, + STATUS_INDETERMINATE, + STATUS_NORMAL, + STATUS_ERROR, + STATUS_PAUSED +}; + +typedef size_t TBHandle; + + +//COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize +DLL_FUNCTION_DECLARATION +TBHandle init(); //returns handle; 0 on failure + +DLL_FUNCTION_DECLARATION +void release(TBHandle handle); //release taskbar handle + +DLL_FUNCTION_DECLARATION +bool setStatus(TBHandle handle, + void* hwnd, //HWND: window assciated to the taskbar icon + TaskBarStatus status); + + +DLL_FUNCTION_DECLARATION +bool setProgress(TBHandle handle, + void* hwnd, //HWND: window assciated to the taskbar icon + size_t current, + size_t total); + +//if any of the functions above returns 'false', this message returns last error +void getLastError(wchar_t* errorMessage, size_t errorBufferLen); + + +//function typedefs +typedef TBHandle (*initFct)(); +typedef void (*releaseFct)(TBHandle handle); +typedef bool (*setStatusFct)(TBHandle handle, void* hwnd, TaskBarStatus status); +typedef bool (*setProgressFct)(TBHandle handle, void* hwnd, size_t current, size_t total); +typedef void (*getLastErrorFct)(wchar_t* errorMessage, size_t errorBufferLen); +} + +#endif //TASKBAR_SEVEN_DLL_H
\ No newline at end of file diff --git a/library/binary.cpp b/library/binary.cpp index bc5ba814..409b024a 100644 --- a/library/binary.cpp +++ b/library/binary.cpp @@ -6,103 +6,23 @@ // #include "binary.h" #include <boost/scoped_array.hpp> -#include <wx/intl.h> -#include "../shared/stringConv.h" +#include "../shared/fileIO.h" -#ifdef FFS_WIN -#include "../shared/longPathPrefix.h" -#include <wx/msw/wrapwin.h> //includes "windows.h" -#include <boost/shared_ptr.hpp> -#elif defined FFS_LINUX -#include <wx/ffile.h> -#endif - - -bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback) +bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback) { const size_t BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]); static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]); -#ifdef FFS_WIN - const HANDLE hFile1 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename1).c_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (hFile1 == INVALID_HANDLE_VALUE) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - - boost::shared_ptr<void> dummy1(hFile1, &::CloseHandle); - - const HANDLE hFile2 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename2).c_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); - - boost::shared_ptr<void> dummy2(hFile2, &::CloseHandle); - - wxLongLong bytesCompared; - DWORD length1 = 0; - do - { - if (!::ReadFile( - hFile1, //__in HANDLE hFile, - memory1.get(), //__out LPVOID lpBuffer, - BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead, - &length1, //__out_opt LPDWORD lpNumberOfBytesRead, - NULL)) //__inout_opt LPOVERLAPPED lpOverlapped - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - - DWORD length2 = 0; - if (!::ReadFile( - hFile2, //__in HANDLE hFile, - memory2.get(), //__out LPVOID lpBuffer, - BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead, - &length2, //__out_opt LPDWORD lpNumberOfBytesRead, - NULL)) //__inout_opt LPOVERLAPPED lpOverlapped - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); - - if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) - return false; - - bytesCompared += length1 * 2; - - //send progress updates - callback->updateCompareStatus(bytesCompared); - } - while (length1 == BUFFER_SIZE); - - return true; - - -#elif defined FFS_LINUX - wxFFile file1(::fopen(filename1.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename - if (!file1.IsOpened()) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - - wxFFile file2(::fopen(filename2.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename - if (!file2.IsOpened()) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + FileInput file1(filename1); //throw FileError() + FileInput file2(filename2); //throw FileError() wxLongLong bytesCompared; do { - const size_t length1 = file1.Read(memory1.get(), BUFFER_SIZE); - if (file1.Error()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - - const size_t length2 = file2.Read(memory2.get(), BUFFER_SIZE); - if (file2.Error()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); + const size_t length1 = file1.read(memory1.get(), BUFFER_SIZE); //returns actual number of bytes read; throw FileError() + const size_t length2 = file2.read(memory2.get(), BUFFER_SIZE); // if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) return false; @@ -110,13 +30,12 @@ bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& bytesCompared += length1 * 2; //send progress updates - callback->updateCompareStatus(bytesCompared); + callback.updateCompareStatus(bytesCompared); } - while (!file1.Eof()); + while (!file1.eof()); - if (!file2.Eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...) + if (!file1.eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...) return false; return true; -#endif } diff --git a/library/binary.h b/library/binary.h index c4e9c928..e33e46bf 100644 --- a/library/binary.h +++ b/library/binary.h @@ -22,7 +22,7 @@ public: virtual void updateCompareStatus(const wxLongLong& totalBytesTransferred) = 0; }; -bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback); //throw FileError +bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback); //throw FileError } #endif // BINARY_H_INCLUDED diff --git a/library/dbFile.cpp b/library/dbFile.cpp new file mode 100644 index 00000000..c08c8ae8 --- /dev/null +++ b/library/dbFile.cpp @@ -0,0 +1,419 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include "dbFile.h" +#include <wx/wfstream.h> +#include <wx/zstream.h> +#include "../shared/globalFunctions.h" +#include "../shared/fileError.h" +#include <wx/intl.h> +#include "../shared/stringConv.h" +#include "../shared/fileHandling.h" +#include <wx/mstream.h> +#include "../shared/serialize.h" +#include "../shared/fileIO.h" + +#ifdef FFS_WIN +#include <wx/msw/wrapwin.h> //includes "windows.h" +#include "../shared/longPathPrefix.h" +#endif + +using namespace FreeFileSync; + + +namespace +{ +//------------------------------------------------------------------------------------------------------------------------------- +const char FILE_FORMAT_DESCR[] = "FreeFileSync"; +const int FILE_FORMAT_VER = 3; +//------------------------------------------------------------------------------------------------------------------------------- + + +//yet another layer of indirection: Since 32/64 bit builds are binary incompatible, we want them to write into "distinct parts" of the db-file +//just like we were actually accessing different files +class FileInputStreamDB : public FileInputStream +{ +public: + FileInputStreamDB(const Zstring& filename) : //throw FileError() + FileInputStream(filename) + { + //read FreeFileSync file identifier + char formatDescr[sizeof(FILE_FORMAT_DESCR)]; + Read(formatDescr, sizeof(formatDescr)); //throw (FileError) + formatDescr[sizeof(formatDescr) - 1] = 0; + + if (std::string(formatDescr) != FILE_FORMAT_DESCR) + throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + zToWx(filename) + wxT("\"")); + } + +private: +}; + + +class FileOutputStreamDB : public FileOutputStream +{ +public: + FileOutputStreamDB(const Zstring& filename) : //throw FileError() + FileOutputStream(filename) + { + //write FreeFileSync file identifier + Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw (FileError) + } + +private: +}; +} +//####################################################################################################################################### + + + + +class ReadDirInfo : public Utility::ReadInputStream +{ +public: + ReadDirInfo(wxInputStream& stream, const wxString& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName) + { + //read filter settings + dirInfo.filter = BaseFilter::loadFilter(getStream()); + check(); + + //start recursion + execute(dirInfo.baseDirContainer); + } + +private: + void execute(DirContainer& dirCont) + { + unsigned int fileCount = readNumberC<unsigned int>(); + while (fileCount-- != 0) + readSubFile(dirCont); + + unsigned int dirCount = readNumberC<unsigned int>(); + while (dirCount-- != 0) + readSubDirectory(dirCont); + } + + void readSubFile(DirContainer& dirCont) + { + //attention: order of function argument evaluation is undefined! So do it one after the other... + const Zstring shortName = readStringC(); //file name + + const long modHigh = readNumberC<long>(); + const unsigned long modLow = readNumberC<unsigned long>(); + + const unsigned long sizeHigh = readNumberC<unsigned long>(); + const unsigned long sizeLow = readNumberC<unsigned long>(); + + //const Utility::FileID fileIdentifier(stream_); + //check(); + + dirCont.addSubFile(shortName, + FileDescriptor(wxLongLong(modHigh, modLow), + wxULongLong(sizeHigh, sizeLow))); + } + + void readSubDirectory(DirContainer& dirCont) + { + const Zstring shortName = readStringC(); //directory name + DirContainer& subDir = dirCont.addSubDir(shortName); + execute(subDir); //recurse + } +}; + + +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 +/* Example +left side right side +--------- ---------- +DB-ID 123 <-\ /-> DB-ID 567 + \/ +Partner-ID 111 /\ Partner-ID 222 +Partner-ID 567 _/ \_ Partner-ID 123 + ... ... +*/ + +class ReadFileStream : public Utility::ReadInputStream +{ +public: + ReadFileStream(wxInputStream& stream, const wxString& filename, DbStreamData& output) : ReadInputStream(stream, filename) + { + if (readNumberC<int>() != FILE_FORMAT_VER) //read file format version + throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + filename + wxT("\"")); + + //read DB id + output.first = Utility::UniqueId(getStream()); + check(); + + DirectoryTOC& dbList = output.second; + dbList.clear(); + + 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 + check(); + + CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation) + + dbList.insert(std::make_pair(partnerID, buffer)); + } + } +}; + + +DbStreamData loadFile(const Zstring& filename) //throw (FileError) +{ + if (!FreeFileSync::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("\"")); + + + //read format description (uncompressed) + FileInputStreamDB uncompressed(filename); //throw (FileError) + + wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); + + DbStreamData output; + ReadFileStream(input, zToWx(filename), output); + return output; +} + + +std::pair<DirInfoPtr, DirInfoPtr> FreeFileSync::loadFromDisk(const BaseDirMapping& baseMapping) //throw (FileError) +{ + const Zstring fileNameLeft = baseMapping.getDBFilename<LEFT_SIDE>(); + const Zstring fileNameRight = baseMapping.getDBFilename<RIGHT_SIDE>(); + + //read file data: db ID + mapping of partner-ID/DirInfo-stream + const DbStreamData dbEntriesLeft = ::loadFile(fileNameLeft); + const DbStreamData dbEntriesRight = ::loadFile(fileNameRight); + + //find associated DirInfo-streams + DirectoryTOC::const_iterator dbLeft = dbEntriesLeft.second.find(dbEntriesRight.first); //find left db-entry that corresponds to right database + if (dbLeft == dbEntriesLeft.second.end()) + throw FileError(wxString(_("Initial synchronization:")) + wxT(" \n\n") + + _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + + wxT("\"") + zToWx(fileNameLeft) + wxT("\"")); + + DirectoryTOC::const_iterator dbRight = dbEntriesRight.second.find(dbEntriesLeft.first); //find left db-entry that corresponds to right database + if (dbRight == dbEntriesRight.second.end()) + throw FileError(wxString(_("Initial synchronization:")) + wxT(" \n\n") + + _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + + wxT("\"") + zToWx(fileNameRight) + wxT("\"")); + + //read streams into DirInfo + boost::shared_ptr<DirInformation> dirInfoLeft(new DirInformation); + wxMemoryInputStream buffer(&(*dbLeft->second)[0], dbLeft->second->size()); //convert char-array to inputstream: no copying, ownership not transferred + ReadDirInfo(buffer, zToWx(fileNameLeft), *dirInfoLeft); //read file/dir information + + boost::shared_ptr<DirInformation> dirInfoRight(new DirInformation); + wxMemoryInputStream buffer2(&(*dbRight->second)[0], dbRight->second->size()); //convert char-array to inputstream: no copying, ownership not transferred + ReadDirInfo(buffer2, zToWx(fileNameRight), *dirInfoRight); //read file/dir information + + return std::make_pair(dirInfoLeft, dirInfoRight); +} + + +//------------------------------------------------------------------------------------------------------------------------- + +template <SelectedSide side> +struct IsNonEmpty +{ + bool operator()(const FileSystemObject& fsObj) const + { + return !fsObj.isEmpty<side>(); + } +}; + + +template <SelectedSide side> +class SaveDirInfo : public Utility::WriteOutputStream +{ +public: + SaveDirInfo(const BaseDirMapping& baseMapping, const wxString& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream) + { + //save filter settings + baseMapping.getFilter()->saveFilter(getStream()); + check(); + + //start recursion + execute(baseMapping); + } + +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); + + void execute(const HierarchyObject& hierObj) + { + writeNumberC<unsigned int>(std::count_if(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), IsNonEmpty<side>())); //number of (existing) files + std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), *this); + + writeNumberC<unsigned int>(std::count_if(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), IsNonEmpty<side>())); //number of (existing) directories + std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), *this); + } + + void operator()(const FileMapping& fileMap) + { + if (!fileMap.isEmpty<side>()) + { + writeStringC(fileMap.getObjShortName()); //file name + writeNumberC<long>( fileMap.getLastWriteTime<side>().GetHi()); //last modification time + writeNumberC<unsigned long>(fileMap.getLastWriteTime<side>().GetLo()); // + writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetHi()); //filesize + writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetLo()); // + + //fileMap.getFileID<side>().toStream(stream_); //unique file identifier + //check(); + } + } + + void operator()(const DirMapping& dirMap) + { + if (!dirMap.isEmpty<side>()) + { + writeStringC(dirMap.getObjShortName()); //directory name + execute(dirMap); //recurse + } + } +}; + + +class WriteFileStream : public Utility::WriteOutputStream +{ +public: + WriteFileStream(const DbStreamData& input, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) + { + //save file format version + writeNumberC<int>(FILE_FORMAT_VER); + + //write DB id + input.first.toStream(getStream()); + check(); + + const DirectoryTOC& dbList = input.second; + + writeNumberC<size_t>(dbList.size()); //number of database records: one for each sync-pair + + for (DirectoryTOC::const_iterator i = dbList.begin(); i != dbList.end(); ++i) + { + i->first.toStream(getStream()); //DB id of partner database + check(); + + writeArrayC(*(i->second)); //write DirInformation stream + } + } +}; + + +//save/load DirContainer +void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (FileError) +{ + { + //write format description (uncompressed) + FileOutputStreamDB uncompressed(filename); //throw (FileError) + + wxZlibOutputStream output(uncompressed, 4, wxZLIB_ZLIB); + /* 4 - best compromise between speed and compression: (scanning 200.000 objects) + 0 (uncompressed) 8,95 MB - 422 ms + 2 2,07 MB - 470 ms + 4 1,87 MB - 500 ms + 6 1,77 MB - 613 ms + 9 (maximal compression) 1,74 MB - 3330 ms */ + + WriteFileStream(dbStream, zToWx(filename), output); + } + //(try to) hide database file +#ifdef FFS_WIN + ::SetFileAttributes(FreeFileSync::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN); +#endif +} + + +void FreeFileSync::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); + + try + { + //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>())) + try + { + dbEntriesLeft = ::loadFile(baseMapping.getDBFilename<LEFT_SIDE>()); + } + catch(FileError&) {} //if error occurs: just overwrite old file! User is informed about issues right after comparing! + //else -> dbEntriesLeft has empty mapping, but already a DB-ID! + + //read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw! + DbStreamData dbEntriesRight; + if (FreeFileSync::fileExists(baseMapping.getDBFilename<RIGHT_SIDE>())) + try + { + dbEntriesRight = ::loadFile(baseMapping.getDBFilename<RIGHT_SIDE>()); + } + catch(FileError&) {} //if error occurs: just overwrite old file! User is informed about issues right after comparing! + + //create new database entries + MemoryStreamPtr dbEntryLeft(new std::vector<char>); + { + wxMemoryOutputStream buffer; + SaveDirInfo<LEFT_SIDE>(baseMapping, zToWx(baseMapping.getDBFilename<LEFT_SIDE>()), buffer); + dbEntryLeft->resize(buffer.GetSize()); //convert output stream to char-array + buffer.CopyTo(&(*dbEntryLeft)[0], buffer.GetSize()); // + } + + MemoryStreamPtr dbEntryRight(new std::vector<char>); + { + wxMemoryOutputStream buffer; + SaveDirInfo<RIGHT_SIDE>(baseMapping, zToWx(baseMapping.getDBFilename<RIGHT_SIDE>()), buffer); + dbEntryRight->resize(buffer.GetSize()); //convert output stream to char-array + buffer.CopyTo(&(*dbEntryRight)[0], buffer.GetSize()); // + } + + //create/update DirInfo-streams + dbEntriesLeft.second[dbEntriesRight.first] = dbEntryLeft; + dbEntriesRight.second[dbEntriesLeft.first] = dbEntryRight; + + //write (temp-) files... + saveFile(dbEntriesLeft, fileNameLeftTmp); //throw (FileError) + saveFile(dbEntriesRight, fileNameRightTmp); //throw (FileError) + + //operation finished: rename temp files -> this should work transactionally: + //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(fileNameRightTmp, baseMapping.getDBFilename<RIGHT_SIDE>()); //throw (FileError); + } + catch (...) + { + try //clean up: (try to) delete old tmp files + { + removeFile(fileNameLeftTmp); + } + catch (...) {} + try + { + removeFile(fileNameRightTmp); + } + catch (...) {} + + throw; + } +} diff --git a/library/dbFile.h b/library/dbFile.h new file mode 100644 index 00000000..e7db0393 --- /dev/null +++ b/library/dbFile.h @@ -0,0 +1,20 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef DBFILE_H_INCLUDED +#define DBFILE_H_INCLUDED + +#include "../fileHierarchy.h" + +namespace FreeFileSync +{ +void saveToDisk(const BaseDirMapping& baseMapping); //throw (FileError) + +typedef boost::shared_ptr<const DirInformation> DirInfoPtr; +std::pair<DirInfoPtr, DirInfoPtr> loadFromDisk(const BaseDirMapping& baseMapping); //throw (FileError) -> return value always bound! +} + +#endif // DBFILE_H_INCLUDED diff --git a/library/filter.cpp b/library/filter.cpp index b1b67b86..d7f12bec 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -273,8 +273,8 @@ bool NameFilter::isNull() const bool NameFilter::cmpLessSameType(const BaseFilter& other) const { - //typeid(*this) == typeid(other) in this context! - assert(typeid(*this) == typeid(other)); + assert(typeid(*this) == typeid(other)); //always given in this context! + const NameFilter& otherNameFilt = static_cast<const NameFilter&>(other); if (filterFileIn != otherNameFilt.filterFileIn) diff --git a/library/filter.h b/library/filter.h index 6ec5a3d5..5df74997 100644 --- a/library/filter.h +++ b/library/filter.h @@ -55,7 +55,7 @@ public: static FilterRef loadFilter(wxInputStream& stream); //CAVEAT!!! adapt this method for each new derivation!!! private: - virtual Zstring uniqueClassIdentifier() const = 0; //get identifier, used for serialization + virtual Zstring uniqueClassIdentifier() const = 0; //get identifier, used for serialization virtual void save(wxOutputStream& stream) const = 0; //serialization virtual bool cmpLessSameType(const BaseFilter& other) const = 0; //typeid(*this) == typeid(other) in this context! }; @@ -91,10 +91,10 @@ private: virtual void save(wxOutputStream& stream) const; virtual bool cmpLessSameType(const BaseFilter& other) const; - std::set<Zstring> filterFileIn; - std::set<Zstring> filterFolderIn; - std::set<Zstring> filterFileEx; - std::set<Zstring> filterFolderEx; + std::set<Zstring> filterFileIn; //upper case (windows) + std::set<Zstring> filterFolderIn; // + std::set<Zstring> filterFileEx; // + std::set<Zstring> filterFolderEx; // const Zstring includeFilterTmp; //save constructor arguments for serialization const Zstring excludeFilterTmp; // @@ -175,8 +175,7 @@ bool NullFilter::isNull() const inline bool NullFilter::cmpLessSameType(const BaseFilter& other) const { - //typeid(*this) == typeid(other) in this context! - assert(typeid(*this) == typeid(other)); + assert(typeid(*this) == typeid(other)); //always given in this context! return false; } @@ -214,8 +213,8 @@ bool CombinedFilter::isNull() const inline bool CombinedFilter::cmpLessSameType(const BaseFilter& other) const { - //typeid(*this) == typeid(other) in this context! - assert(typeid(*this) == typeid(other)); + assert(typeid(*this) == typeid(other)); //always given in this context! + const CombinedFilter& otherCombFilt = static_cast<const CombinedFilter&>(other); if (*first_ != *otherCombFilt.first_) diff --git a/library/processXml.cpp b/library/processXml.cpp index 69cf8baf..1cc279b0 100644 --- a/library/processXml.cpp +++ b/library/processXml.cpp @@ -6,16 +6,12 @@ // #include "processXml.h" #include "../shared/xmlBase.h" -#include <wx/filefn.h> #include <wx/intl.h> +#include <wx/filefn.h> #include "../shared/globalFunctions.h" #include "../shared/standardPaths.h" #include "../shared/stringConv.h" -#ifdef FFS_WIN -#include <wx/msw/wrapwin.h> //includes "windows.h" -#endif - using namespace FreeFileSync; using namespace xmlAccess; //functionally needed!!! @@ -57,17 +53,16 @@ void xmlAccess::readGuiConfig(const wxString& filename, xmlAccess::XmlGuiConfig& { //load XML if (!wxFileExists(filename)) - throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + filename + wxT("\"")); + throw XmlError(wxString(_("File does not exist:")) + wxT("\n\"") + filename + wxT("\"")); TiXmlDocument doc; - if (!loadXmlDocument(filename, XML_GUI_CONFIG, doc)) - throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\"")); + loadXmlDocument(filename, XML_GUI_CONFIG, doc); //throw (XmlError) FfsXmlParser parser(doc.RootElement()); parser.readXmlGuiConfig(config); //read GUI layout configuration if (parser.errorsOccured()) - throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\"\n\n") + + throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\"\n\n") + parser.getErrorMessageFormatted(), XmlError::WARNING); } @@ -76,17 +71,16 @@ void xmlAccess::readBatchConfig(const wxString& filename, xmlAccess::XmlBatchCon { //load XML if (!wxFileExists(filename)) - throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + filename + wxT("\"")); + throw XmlError(wxString(_("File does not exist:")) + wxT("\n\"") + filename + wxT("\"")); TiXmlDocument doc; - if (!loadXmlDocument(filename, XML_BATCH_CONFIG, doc)) - throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\"")); + loadXmlDocument(filename, XML_BATCH_CONFIG, doc); //throw (XmlError) FfsXmlParser parser(doc.RootElement()); parser.readXmlBatchConfig(config); //read GUI layout configuration if (parser.errorsOccured()) - throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\"\n\n") + + throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\"\n\n") + parser.getErrorMessageFormatted(), XmlError::WARNING); } @@ -95,17 +89,16 @@ void xmlAccess::readGlobalSettings(xmlAccess::XmlGlobalSettings& config) { //load XML if (!wxFileExists(getGlobalConfigFile())) - throw XmlError(wxString(_("File does not exist:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); + throw XmlError(wxString(_("File does not exist:")) + wxT("\n\"") + getGlobalConfigFile() + wxT("\"")); TiXmlDocument doc; - if (!loadXmlDocument(getGlobalConfigFile(), XML_GLOBAL_SETTINGS, doc)) - throw XmlError(wxString(_("Error reading file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); + loadXmlDocument(getGlobalConfigFile(), XML_GLOBAL_SETTINGS, doc); //throw (XmlError) FfsXmlParser parser(doc.RootElement()); parser.readXmlGlobalSettings(config); //read GUI layout configuration if (parser.errorsOccured()) - throw XmlError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"\n\n") + + throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + getGlobalConfigFile() + wxT("\"\n\n") + parser.getErrorMessageFormatted(), XmlError::WARNING); } @@ -116,10 +109,10 @@ void xmlAccess::writeGuiConfig(const XmlGuiConfig& outputCfg, const wxString& fi getDefaultXmlDocument(XML_GUI_CONFIG, doc); //populate and write XML tree - if ( !writeXmlGuiConfig(outputCfg, doc) || //add GUI layout configuration settings - !saveXmlDocument(filename, doc)) //save XML - throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\"")); - return; + if (!writeXmlGuiConfig(outputCfg, doc)) //add GUI layout configuration settings + throw XmlError(wxString(_("Error writing file:")) + wxT("\n\"") + filename + wxT("\"")); + + saveXmlDocument(filename, doc); //throw (XmlError) } @@ -129,10 +122,10 @@ void xmlAccess::writeBatchConfig(const XmlBatchConfig& outputCfg, const wxString getDefaultXmlDocument(XML_BATCH_CONFIG, doc); //populate and write XML tree - if ( !writeXmlBatchConfig(outputCfg, doc) || //add batch configuration settings - !saveXmlDocument(filename, doc)) //save XML - throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\"")); - return; + if (!writeXmlBatchConfig(outputCfg, doc)) //add batch configuration settings + throw XmlError(wxString(_("Error writing file:")) + wxT("\n\"") + filename + wxT("\"")); + + saveXmlDocument(filename, doc); //throw (XmlError) } @@ -142,10 +135,10 @@ void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg) getDefaultXmlDocument(XML_GLOBAL_SETTINGS, doc); //populate and write XML tree - if ( !writeXmlGlobalSettings(outputCfg, doc) || //add GUI layout configuration settings - !saveXmlDocument(getGlobalConfigFile(), doc)) //save XML - throw XmlError(wxString(_("Error writing file:")) + wxT(" \"") + getGlobalConfigFile() + wxT("\"")); - return; + if (!writeXmlGlobalSettings(outputCfg, doc)) //add GUI layout configuration settings + throw XmlError(wxString(_("Error writing file:")) + wxT("\n\"") + getGlobalConfigFile() + wxT("\"")); + + saveXmlDocument(getGlobalConfigFile(), doc); //throw (XmlError) } @@ -298,7 +291,7 @@ void FfsXmlParser::readXmlLocalConfig(const TiXmlElement& folderPair, FolderPair void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) { - TiXmlHandleConst hRoot(root); //custom const handle: TiXml API seems broken in this regard + TiXmlHandleConst hRoot(getRoot()); //custom const handle: TiXml API seems broken in this regard //########################################################### const TiXmlElement* cmpSettings = hRoot.FirstChild("MainConfig").FirstChild("Comparison").ToElement(); @@ -378,7 +371,7 @@ void FfsXmlParser::readXmlGuiConfig(xmlAccess::XmlGuiConfig& outputCfg) readXmlMainConfig(outputCfg.mainCfg); //read GUI specific config data - const TiXmlElement* guiConfig = TiXmlHandleConst(root).FirstChild("GuiConfig").ToElement(); + const TiXmlElement* guiConfig = TiXmlHandleConst(getRoot()).FirstChild("GuiConfig").ToElement(); readXmlElementLogging("HideFiltered", guiConfig, outputCfg.hideFilteredElements); @@ -396,7 +389,7 @@ void FfsXmlParser::readXmlBatchConfig(xmlAccess::XmlBatchConfig& outputCfg) readXmlMainConfig(outputCfg.mainCfg); //read batch specific config - const TiXmlElement* batchConfig = TiXmlHandleConst(root).FirstChild("BatchConfig").ToElement(); + const TiXmlElement* batchConfig = TiXmlHandleConst(getRoot()).FirstChild("BatchConfig").ToElement(); readXmlElementLogging("Silent", batchConfig, outputCfg.silent); readXmlElementLogging("LogfileDirectory", batchConfig, outputCfg.logFileDirectory); @@ -407,7 +400,7 @@ void FfsXmlParser::readXmlBatchConfig(xmlAccess::XmlBatchConfig& outputCfg) void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg) { //read global settings - const TiXmlElement* global = TiXmlHandleConst(root).FirstChild("Shared").ToElement(); + const TiXmlElement* global = TiXmlHandleConst(getRoot()).FirstChild("Shared").ToElement(); //try to read program language setting readXmlElementLogging("Language", global, outputCfg.programLanguage); @@ -418,11 +411,8 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //copy locked files using VSS readXmlElementLogging("CopyLockedFiles", global, outputCfg.copyLockedFiles); - //last update check - readXmlElementLogging("LastCheckForUpdates", global, outputCfg.lastUpdateCheck); - - const TiXmlElement* optionalDialogs = TiXmlHandleConst(root).FirstChild("Shared").FirstChild("ShowOptionalDialogs").ToElement(); + const TiXmlElement* optionalDialogs = TiXmlHandleConst(getRoot()).FirstChild("Shared").FirstChild("ShowOptionalDialogs").ToElement(); //folder dependency check readXmlElementLogging("CheckForDependentFolders", optionalDialogs, outputCfg.optDialogs.warningDependentFolders); @@ -441,7 +431,8 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //gui specific global settings (optional) - const TiXmlElement* mainWindow = TiXmlHandleConst(root).FirstChild("Gui").FirstChild("Windows").FirstChild("Main").ToElement(); + const TiXmlElement* gui = TiXmlHandleConst(getRoot()).FirstChild("Gui").ToElement(); + const TiXmlElement* mainWindow = TiXmlHandleConst(gui).FirstChild("Windows").FirstChild("Main").ToElement(); //read application window size and position readXmlElementLogging("Width", mainWindow, outputCfg.gui.widthNotMaximized); @@ -509,8 +500,6 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg readXmlElementLogging("SelectedTabBottomLeft", mainWindow, outputCfg.gui.selectedTabBottomLeft); - const TiXmlElement* gui = TiXmlHandleConst(root).FirstChild("Gui").ToElement(); - //external applications const TiXmlElement* extApps = TiXmlHandleConst(gui).FirstChild("ExternalApplications").FirstChild("Commandline").ToElement(); if (extApps) @@ -530,7 +519,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg } } //load config file history - const TiXmlElement* cfgHistory = TiXmlHandleConst(root).FirstChild("Gui").FirstChild("ConfigHistory").ToElement(); + const TiXmlElement* cfgHistory = TiXmlHandleConst(gui).FirstChild("ConfigHistory").ToElement(); //load max. history size readXmlAttributeLogging("MaximumSize", cfgHistory, outputCfg.gui.cfgHistoryMax); @@ -538,6 +527,9 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //load config history elements readXmlElementLogging("File", cfgHistory, outputCfg.gui.cfgFileHistory); + //last update check + readXmlElementLogging("LastUpdateCheck", gui, outputCfg.gui.lastUpdateCheck); + //batch specific global settings //const TiXmlElement* batch = TiXmlHandleConst(root).FirstChild("Batch").ToElement(); @@ -818,9 +810,6 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD //copy locked files using VSS addXmlElement("CopyLockedFiles", inputCfg.copyLockedFiles, global); - //last update check - addXmlElement("LastCheckForUpdates", inputCfg.lastUpdateCheck, global); - //optional dialogs TiXmlElement* optionalDialogs = new TiXmlElement("ShowOptionalDialogs"); @@ -943,6 +932,10 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD addXmlAttribute("MaximumSize", inputCfg.gui.cfgHistoryMax, cfgHistory); addXmlElement("File", inputCfg.gui.cfgFileHistory, cfgHistory); + + //last update check + addXmlElement("LastUpdateCheck", inputCfg.gui.lastUpdateCheck, gui); + //################################################################### //write global batch settings diff --git a/library/processXml.h b/library/processXml.h index ad8465ff..13282de9 100644 --- a/library/processXml.h +++ b/library/processXml.h @@ -8,7 +8,6 @@ #define PROCESSXML_H_INCLUDED #include "../structures.h" -#include <wx/intl.h> namespace xmlAccess { @@ -116,14 +115,12 @@ struct XmlGlobalSettings XmlGlobalSettings() : programLanguage(retrieveSystemLanguage()), ignoreOneHourDiff(false), - copyLockedFiles(true), - lastUpdateCheck(0) + copyLockedFiles(true) {} int programLanguage; bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change bool copyLockedFiles; //VSS usage - long lastUpdateCheck; //time of last update check OptionalDialogs optDialogs; @@ -150,7 +147,8 @@ struct XmlGlobalSettings textSearchRespectCase(true), #endif showFileIconsLeft(true), - showFileIconsRight(true) + showFileIconsRight(true), + lastUpdateCheck(0) { //default external apps will be translated "on the fly"!!! #ifdef FFS_WIN @@ -194,6 +192,8 @@ struct XmlGlobalSettings bool textSearchRespectCase; bool showFileIconsLeft; bool showFileIconsRight; + + long lastUpdateCheck; //time of last update check } gui; //--------------------------------------------------------------------- diff --git a/library/softFilter.cpp b/library/softFilter.cpp new file mode 100644 index 00000000..496c185e --- /dev/null +++ b/library/softFilter.cpp @@ -0,0 +1,10 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#include "softFilter.h" + + + diff --git a/library/softFilter.h b/library/softFilter.h new file mode 100644 index 00000000..e4735e38 --- /dev/null +++ b/library/softFilter.h @@ -0,0 +1,79 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef SOFTFILTER_H_INCLUDED +#define SOFTFILTER_H_INCLUDED + +#include "../fileHierarchy.h" +#include <wx/timer.h> +/* +Semantics of SoftFilter: +1. It potentially can match only one side => it MUST NOT be applied while traversing a single folder to avoid mismatches +2. => it is applied after traversing and just marks rows, (NO deletions after comparison are allowed) +3. => not relevant for <Automatic>-mode! ;) + +-> SoftFilter is equivalent to a user temporarily (de-)selecting rows +*/ + +namespace FreeFileSync +{ + +class SoftFilter +{ +public: + SoftFilter(size_t timeWindow) : + timeWindow_(timeWindow), + currentTime(wxGetUTCTime()) {} + + bool passFilter(const FileMapping& fileMap) const; + bool passFilter(const DirMapping& dirMap) const; + +private: + const size_t timeWindow_; //point in time from "now" (in seconds) for oldest modification date to be allowed + const long currentTime; //number of seconds since GMT 00:00:00 Jan 1st 1970. +}; + + + + + + + + + + + + + + + + + + + + + + + +//---------------Inline Implementation--------------------------------------------------- +inline +bool SoftFilter::passFilter(const FileMapping& fileMap) const +{ + return (!fileMap.isEmpty<LEFT_SIDE>() && + currentTime <= fileMap.getLastWriteTime<LEFT_SIDE>() + timeWindow_) || + (!fileMap.isEmpty<RIGHT_SIDE>() && + currentTime <= fileMap.getLastWriteTime<RIGHT_SIDE>() + timeWindow_); +} + + +inline +bool SoftFilter::passFilter(const DirMapping& dirMap) const +{ + return false; +} +} + +#endif // SOFTFILTER_H_INCLUDED diff --git a/library/statistics.cpp b/library/statistics.cpp index ac968d1f..6e64be1c 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -10,7 +10,7 @@ #include "../shared/globalFunctions.h" #include "statusHandler.h" //#include "../algorithm.h" -#include "../ui/util.h" +#include "../shared/util.h" #include <wx/intl.h> #include <limits> #include <wx/stopwatch.h> @@ -31,11 +31,11 @@ RetrieveStatistics::~RetrieveStatistics() for (std::vector<statEntry>::const_iterator i = data.begin(); i != data.end(); ++i) { - outputFile.Write(globalFunctions::numberToWxString(int(i->time))); + outputFile.Write(FreeFileSync::numberToWxString(static_cast<int>(i->time), false)); outputFile.Write(wxT(";")); - outputFile.Write(globalFunctions::numberToWxString(i->objects)); + outputFile.Write(FreeFileSync::numberToWxString(i->objects, false)); outputFile.Write(wxT(";")); - outputFile.Write(globalFunctions::numberToWxString(float(i->value))); + outputFile.Write(FreeFileSync::numberToWxString(static_cast<int>(i->value), false)); outputFile.Write(wxT("\n")); } } @@ -104,7 +104,7 @@ wxString Statistics::formatRemainingTime(const double timeInMs) const } remainingTimeLast = formattedTime; - return globalFunctions::numberToWxString(formattedTime) + unit; + return FreeFileSync::numberToWxString(formattedTime, false) + unit; //+ wxT("(") + globalFunctions::numberToWxString(globalFunctions::round(timeInMs / 1000)) + wxT(")"); } |