summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/custom_grid.cpp27
-rw-r--r--lib/db_file.cpp8
-rw-r--r--lib/dir_lock.cpp6
-rw-r--r--lib/dir_name.cpp174
-rw-r--r--lib/dir_name.h51
-rw-r--r--lib/folder_history_box.cpp141
-rw-r--r--lib/folder_history_box.h106
-rw-r--r--lib/localization.cpp18
-rw-r--r--lib/parallel_scan.cpp2
-rw-r--r--lib/parse_plural.h2
-rw-r--r--lib/process_xml.cpp110
-rw-r--r--lib/process_xml.h32
-rw-r--r--lib/statistics.cpp15
-rw-r--r--lib/statistics.h12
-rw-r--r--lib/status_handler.h10
15 files changed, 137 insertions, 577 deletions
diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp
index 736bc49d..92f3b718 100644
--- a/lib/custom_grid.cpp
+++ b/lib/custom_grid.cpp
@@ -1080,20 +1080,23 @@ void CustomGridRim::updateGridSizes()
CustomGrid::updateGridSizes();
//set row label size
+ if (GetRowLabelSize() > 0)
+ {
+ //SetRowLabelSize(wxGRID_AUTOSIZE); -> we can do better
+ wxClientDC dc(GetGridRowLabelWindow());
+ dc.SetFont(GetLabelFont());
- //SetRowLabelSize(wxGRID_AUTOSIZE); -> we can do better
- wxClientDC dc(GetGridRowLabelWindow());
- dc.SetFont(GetLabelFont());
+ wxArrayString lines;
+ lines.push_back(GetRowLabelValue(GetNumberRows()));
- wxArrayString lines;
- lines.push_back(GetRowLabelValue(GetNumberRows()));
+ long width = 0;
+ long dummy = 0;
+ GetTextBoxSize(dc, lines, &width, &dummy);
- long width = 0;
- long dummy = 0;
- GetTextBoxSize(dc, lines, &width, &dummy);
+ width += 8;
- width += 8;
- SetRowLabelSize(width);
+ SetRowLabelSize(width);
+ }
}
@@ -1377,7 +1380,7 @@ void CustomGridRim::setTooltip(const wxMouseEvent& event)
virtual void visit(const FileMapping& fileObj)
{
tipMsg_ = copyStringTo<wxString>(std::wstring() + fileObj.getRelativeName<side>() + L"\n" +
- _("Size") + L": " + zen::filesizeToShortString(fileObj.getFileSize<side>()) + L"\n" +
+ _("Size") + L": " + zen::filesizeToShortString(to<Int64>(fileObj.getFileSize<side>())) + L"\n" +
_("Date") + L": " + zen::utcToLocalTimeString(fileObj.getLastWriteTime<side>()));
}
@@ -1449,7 +1452,7 @@ xmlAccess::ColumnAttributes CustomGridRim::getDefaultColumnAttributes()
newEntry.type = xmlAccess::SIZE;
newEntry.position = 4;
- newEntry.width = 70;
+ newEntry.width = 80;
defaultColumnSettings.push_back(newEntry);
newEntry.type = xmlAccess::DATE;
diff --git a/lib/db_file.cpp b/lib/db_file.cpp
index 60a721b1..51333687 100644
--- a/lib/db_file.cpp
+++ b/lib/db_file.cpp
@@ -37,9 +37,9 @@ typedef Zbase<char> MemoryStream; //ref-counted byte strea
typedef std::map<UniqueId, MemoryStream> StreamMapping; //list of streams ordered by session UUID
-//------------------------------------------------------------------------------------
-//| ensure 32/64 bit portability: used fixed size data types only e.g. std::uint32_t |
-//------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+//| ensure 32/64 bit portability: use fixed size data types only e.g. std::uint32_t |
+//-----------------------------------------------------------------------------------
template <SelectedSide side> inline
@@ -48,7 +48,7 @@ Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false)
//Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity?
//however 32 and 64 bit db files *are* designed to be binary compatible!
//Give db files different names.
- //make sure they end with ".ffs_db". These files will not be included into comparison when located in base sync directories
+ //make sure they end with ".ffs_db". These files will not be included into comparison
#ifdef FFS_WIN
Zstring dbname = Zstring(Zstr("sync")) + (tempfile ? Zstr(".tmp") : Zstr("")) + SYNC_DB_FILE_ENDING;
#elif defined FFS_LINUX
diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp
index ab3c84ea..9ca76310 100644
--- a/lib/dir_lock.cpp
+++ b/lib/dir_lock.cpp
@@ -447,10 +447,6 @@ bool tryLock(const Zstring& lockfilename) //throw FileError
NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
-#ifndef _MSC_VER
-#warning fix this problem!
- //read-only FTP may return: ERROR_FILE_EXISTS (NetDrive @ GNU)
-#endif
if (::GetLastError() == ERROR_FILE_EXISTS)
return false;
else
@@ -545,7 +541,7 @@ public:
return activeLock;
}
}
- catch (...) {} //catch everything, let SharedDirLock constructor deal with errors, e.g. 0-sized/corrupted lock file
+ catch (FileError&) {} //catch everything, let SharedDirLock constructor deal with errors, e.g. 0-sized/corrupted lock file
//not yet in buffer, so create a new directory lock
std::shared_ptr<SharedDirLock> newLock(new SharedDirLock(lockfilename, callback)); //throw FileError
diff --git a/lib/dir_name.cpp b/lib/dir_name.cpp
deleted file mode 100644
index 55a4185c..00000000
--- a/lib/dir_name.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-// **************************************************************************
-// * 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-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "dir_name.h"
-#include <wx/dnd.h>
-#include <wx/window.h>
-#include <wx/textctrl.h>
-#include <wx/statbox.h>
-#include <zen/thread.h>
-#include <zen/file_handling.h>
-#include "resolve_path.h"
-#include <wx+/string_conv.h>
-#include "folder_history_box.h"
-
-using namespace zen;
-
-
-namespace
-{
-void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, wxWindow& tooltipWnd, wxStaticBoxSizer* staticBox, size_t timeout)
-{
- const wxString dirFormatted = toWx(getFormattedDirectoryName(toZ(dirname)));
-
- tooltipWnd.SetToolTip(dirFormatted); //wxComboBox bug: the edit control is not updated... http://trac.wxwidgets.org/ticket/12659
-
- if (staticBox)
- {
- //change static box label only if there is a real difference to what is shown in wxTextCtrl anyway
- wxString dirNormalized = dirname;
- trim(dirNormalized);
- if (!dirNormalized.empty() && !endsWith(dirNormalized, FILE_NAME_SEPARATOR))
- dirNormalized += FILE_NAME_SEPARATOR;
-
- staticBox->GetStaticBox()->SetLabel(dirNormalized == dirFormatted ? wxString(_("Drag && drop")) : dirFormatted);
- }
-
- if (dirPicker && !dirFormatted.empty())
- {
- Zstring dir = toZ(dirFormatted); //convert to Zstring first: we don't want to pass wxString by value and risk MT issues!
- auto ft = async([=] { return zen::dirExists(dir); });
-
- if (ft.timed_wait(boost::posix_time::milliseconds(timeout)) && ft.get()) //potentially slow network access: wait 200ms at most
- dirPicker->SetPath(dirFormatted);
- }
-}
-
-
-void setDirectoryName(const wxString& dirname,
- wxTextCtrl* txtCtrl,
- wxDirPickerCtrl* dirPicker,
- wxWindow& tooltipWnd,
- wxStaticBoxSizer* staticBox,
- size_t timeout = 200) //pointers are optional
-{
- if (txtCtrl)
- txtCtrl->ChangeValue(dirname);
- setDirectoryNameImpl(dirname, dirPicker, tooltipWnd, staticBox, timeout);
-}
-
-
-void setDirectoryName(const wxString& dirname,
- FolderHistoryBox* comboBox,
- wxDirPickerCtrl* dirPicker,
- wxWindow& tooltipWnd,
- wxStaticBoxSizer* staticBox,
- size_t timeout = 200) //pointers are optional
-{
- if (comboBox)
- comboBox->setValue(dirname);
- setDirectoryNameImpl(dirname, dirPicker, tooltipWnd, staticBox, timeout);
-}
-}
-//##############################################################################################################
-
-template <class NameControl>
-DirectoryName<NameControl>::DirectoryName(wxWindow& dropWindow,
- wxDirPickerCtrl& dirPicker,
- NameControl& dirName,
- wxStaticBoxSizer* staticBox,
- wxWindow* dropWindow2) :
- dropWindow_(dropWindow),
- dropWindow2_(dropWindow2),
- dirPicker_(dirPicker),
- dirName_(dirName),
- staticBox_(staticBox)
-{
- //prepare drag & drop
- setupFileDrop(dropWindow);
- if (dropWindow2)
- setupFileDrop(*dropWindow2);
-
- //redirect drag & drop event back to this class
- dropWindow.Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DirectoryName::OnFilesDropped), NULL, this);
- if (dropWindow2)
- dropWindow2->Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DirectoryName::OnFilesDropped), NULL, this);
-
- //keep dirPicker and dirName synchronous
- dirName_ .Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DirectoryName::OnWriteDirManually), NULL, this);
- dirPicker_.Connect(wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler(DirectoryName::OnDirSelected ), NULL, this);
-}
-
-
-template <class NameControl>
-DirectoryName<NameControl>::~DirectoryName()
-{
- dirName_ .Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DirectoryName::OnWriteDirManually), NULL, this);
- dirPicker_.Disconnect(wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler(DirectoryName::OnDirSelected ), NULL, this);
-}
-
-
-template <class NameControl>
-void DirectoryName<NameControl>::OnFilesDropped(FFSFileDropEvent& event)
-{
- if (event.getFiles().empty())
- return;
-
- if (acceptDrop(event.getFiles()))
- {
- const wxString fileName = event.getFiles()[0];
- if (dirExists(toZ(fileName)))
- setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_);
- else
- {
- wxString parentName = beforeLast(fileName, utf8CvrtTo<wxString>(FILE_NAME_SEPARATOR)); //returns empty string if ch not found
-#ifdef FFS_WIN
- if (endsWith(parentName, L":")) //volume name
- parentName += FILE_NAME_SEPARATOR;
-#endif
- if (dirExists(toZ(parentName)))
- setDirectoryName(parentName, &dirName_, &dirPicker_, dirName_, staticBox_);
- else //set original name unconditionally: usecase: inactive mapped network shares
- setDirectoryName(fileName, &dirName_, &dirPicker_, dirName_, staticBox_);
- }
- }
-}
-
-
-template <class NameControl>
-void DirectoryName<NameControl>::OnWriteDirManually(wxCommandEvent& event)
-{
- setDirectoryName(event.GetString(), static_cast<NameControl*>(NULL), &dirPicker_, dirName_, staticBox_, 100); //potentially slow network access: wait 100 ms at most
- event.Skip();
-}
-
-
-template <class NameControl>
-void DirectoryName<NameControl>::OnDirSelected(wxFileDirPickerEvent& event)
-{
- const wxString newPath = event.GetPath();
- setDirectoryName(newPath, &dirName_, NULL, dirName_, staticBox_);
- event.Skip();
-}
-
-
-template <class NameControl>
-wxString DirectoryName<NameControl>::getName() const
-{
- return dirName_.GetValue();
-}
-
-
-template <class NameControl>
-void DirectoryName<NameControl>::setName(const wxString& dirname)
-{
- setDirectoryName(dirname, &dirName_, &dirPicker_, dirName_, staticBox_);
-}
-
-
-//explicit template instantiations
-template class DirectoryName<wxTextCtrl>;
-template class DirectoryName<FolderHistoryBox>;
diff --git a/lib/dir_name.h b/lib/dir_name.h
deleted file mode 100644
index 43f2015d..00000000
--- a/lib/dir_name.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// **************************************************************************
-// * 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-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef DRAGANDDROP_H_INCLUDED
-#define DRAGANDDROP_H_INCLUDED
-
-#include <vector>
-#include <wx/event.h>
-#include <wx/sizer.h>
-#include <wx/filepicker.h>
-#include <wx+/file_drop.h>
-
-namespace zen
-{
-//handle drag and drop, tooltip, label and manual input, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl
-
-template <class NameControl> //NameControl may be wxTextCtrl, FolderHistoryBox
-class DirectoryName: private wxEvtHandler
-{
-public:
- DirectoryName(wxWindow& dropWindow,
- wxDirPickerCtrl& dirPicker,
- NameControl& dirName,
- wxStaticBoxSizer* staticBox = NULL,
- wxWindow* dropWindow2 = NULL); //optional
-
- ~DirectoryName();
-
- wxString getName() const;
- void setName(const wxString& dirname);
-
-private:
- virtual bool acceptDrop(const std::vector<wxString>& droppedFiles) { return true; }; //return true if drop should be processed
-
- void OnFilesDropped(FFSFileDropEvent& event);
- void OnWriteDirManually(wxCommandEvent& event);
- void OnDirSelected(wxFileDirPickerEvent& event);
-
- const wxWindow& dropWindow_;
- const wxWindow* dropWindow2_;
- wxDirPickerCtrl& dirPicker_;
- NameControl& dirName_;
- wxStaticBoxSizer* staticBox_; //optional
-};
-}
-
-
-#endif // DRAGANDDROP_H_INCLUDED
diff --git a/lib/folder_history_box.cpp b/lib/folder_history_box.cpp
deleted file mode 100644
index c8bd042a..00000000
--- a/lib/folder_history_box.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-// **************************************************************************
-// * 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-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#include "folder_history_box.h"
-#include <list>
-#include "resolve_path.h"
-
-using namespace zen;
-
-
-FolderHistoryBox::FolderHistoryBox(wxWindow* parent,
- wxWindowID id,
- const wxString& value,
- const wxPoint& pos,
- const wxSize& size,
- int n,
- const wxString choices[],
- long style,
- const wxValidator& validator,
- const wxString& name) :
- wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name)
-#if wxCHECK_VERSION(2, 9, 1)
- , dropDownShown(false)
-#endif
-{
- //#####################################
- /*##*/ SetMinSize(wxSize(150, -1)); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
- //#####################################
-
- //register key event to enable item deletion
- Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(FolderHistoryBox::OnKeyEvent), NULL, this);
-
- //refresh history list on mouse click
- Connect(wxEVT_LEFT_DOWN, wxEventHandler(FolderHistoryBox::OnUpdateList), NULL, this);
-
- Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(FolderHistoryBox::OnSelection), NULL, this);
-
-#if wxCHECK_VERSION(2, 9, 1)
- Connect(wxEVT_COMMAND_COMBOBOX_DROPDOWN, wxCommandEventHandler(FolderHistoryBox::OnShowDropDown), NULL, this);
- Connect(wxEVT_COMMAND_COMBOBOX_CLOSEUP, wxCommandEventHandler(FolderHistoryBox::OnHideDropDown), NULL, this);
-#endif
-}
-
-
-#if wxCHECK_VERSION(2, 9, 1)
-void FolderHistoryBox::OnShowDropDown(wxCommandEvent& event)
-{
- dropDownShown = true;
- event.Skip();
-}
-
-
-void FolderHistoryBox::OnHideDropDown(wxCommandEvent& event)
-{
- dropDownShown = false;
- event.Skip();
-}
-#endif
-
-//set value and update list are technically entangled: see potential bug description below
-void FolderHistoryBox::setValueAndUpdateList(const wxString& dirname)
-{
- //it may be a little lame to update the list on each mouse-button click, but it should be working and we dont't have to manipulate wxComboBox internals
-
- std::list<Zstring> dirList;
-
- //add some aliases to allow user changing to volume name and back, if possible
-#ifdef FFS_WIN
- std::vector<Zstring> aliases = getDirectoryAliases(toZ(dirname));
- dirList.insert(dirList.end(), aliases.begin(), aliases.end());
-#endif
-
- if (sharedHistory_.get())
- {
- auto tmp = sharedHistory_->getList();
- //std::sort(tmp.begin(), tmp.end(), LessFilename());
-
- if (!dirList.empty() && !tmp.empty())
- dirList.push_back(FolderHistory::lineSeparator());
-
- dirList.insert(dirList.end(), tmp.begin(), tmp.end());
- }
- //###########################################################################################
-
- //attention: if the target value is not part of the dropdown list, SetValue() will look for a string that *starts with* this value:
- //e.g. if the dropdown list contains "222" SetValue("22") will erroneously set and select "222" instead, while "111" would be set correctly!
- // -> by design on Windows!
- if (std::find(dirList.begin(), dirList.end(), toZ(dirname)) == dirList.end())
- dirList.push_front(toZ(dirname));
-
- Clear();
- std::for_each(dirList.begin(), dirList.end(), [&](const Zstring& dir) { this->Append(toWx(dir)); });
- //this->SetSelection(wxNOT_FOUND); //don't select anything
- this->SetValue(dirname); //preserve main text!
-}
-
-
-void FolderHistoryBox::OnSelection(wxCommandEvent& event)
-{
- event.Skip();
-}
-
-
-void FolderHistoryBox::OnKeyEvent(wxKeyEvent& event)
-{
- const int keyCode = event.GetKeyCode();
- if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE)
- {
- //try to delete the currently selected config history item
- int pos = this->GetCurrentSelection();
- if (0 <= pos && pos < static_cast<int>(this->GetCount()) &&
-#if wxCHECK_VERSION(2, 9, 1)
- dropDownShown)
-#else
- //what a mess...:
- (GetValue() != GetString(pos) || //avoid problems when a character shall be deleted instead of list item
- GetValue() == wxEmptyString)) //exception: always allow removing empty entry
-#endif
- {
- //save old (selected) value: deletion seems to have influence on this
- const wxString currentVal = this->GetValue();
- //this->SetSelection(wxNOT_FOUND);
-
- //delete selected row
- if (sharedHistory_.get())
- sharedHistory_->delItem(toZ(GetString(pos)));
- SetString(pos, wxString()); //in contrast to Delete(), this one does not kill the drop-down list and gives a nice visual feedback!
- //Delete(pos);
-
- //(re-)set value
- this->SetValue(currentVal);
-
- //eat up key event
- return;
- }
- }
- event.Skip();
-}
diff --git a/lib/folder_history_box.h b/lib/folder_history_box.h
deleted file mode 100644
index 859234cc..00000000
--- a/lib/folder_history_box.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// **************************************************************************
-// * 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-2011 ZenJu (zhnmju123 AT gmx.de) *
-// **************************************************************************
-
-#ifndef CUSTOMCOMBOBOX_H_INCLUDED
-#define CUSTOMCOMBOBOX_H_INCLUDED
-
-#include <wx/combobox.h>
-#include <memory>
-#include <zen/zstring.h>
-#include <wx+/string_conv.h>
-#include <zen/stl_tools.h>
-
-//combobox with history function + functionality to delete items (DEL)
-
-
-class FolderHistory
-{
-public:
- FolderHistory() : maxSize_(0) {}
-
- FolderHistory(const std::vector<Zstring>& dirnames, size_t maxSize) :
- maxSize_(maxSize),
- dirnames_(dirnames)
- {
- if (dirnames_.size() > maxSize_) //keep maximal size of history list
- dirnames_.resize(maxSize_);
- }
-
- const std::vector<Zstring>& getList() const { return dirnames_; }
-
- static const Zstring lineSeparator() { return Zstr("---------------------------------------------------------------------------------------------------------------"); }
-
- void addItem(const Zstring& dirname)
- {
- if (dirname.empty() || dirname == lineSeparator())
- return;
-
- Zstring nameTmp = dirname;
- zen::trim(nameTmp);
-
- //insert new folder or put it to the front if already existing
- auto iter = std::find_if(dirnames_.begin(), dirnames_.end(),
- [&](const Zstring& entry) { return ::EqualFilename()(entry, nameTmp); });
-
- if (iter != dirnames_.end())
- dirnames_.erase(iter);
- dirnames_.insert(dirnames_.begin(), nameTmp);
-
- if (dirnames_.size() > maxSize_) //keep maximal size of history list
- dirnames_.resize(maxSize_);
- }
-
- void delItem(const Zstring& dirname) { zen::vector_remove_if(dirnames_, [&](const Zstring& entry) { return ::EqualFilename()(entry, dirname); }); }
-
-private:
-
- size_t maxSize_;
- std::vector<Zstring> dirnames_;
-};
-
-
-class FolderHistoryBox : public wxComboBox
-{
-public:
- FolderHistoryBox(wxWindow* parent,
- wxWindowID id,
- const wxString& value = wxEmptyString,
- const wxPoint& pos = wxDefaultPosition,
- const wxSize& size = wxDefaultSize,
- int n = 0,
- const wxString choices[] = NULL,
- long style = 0,
- const wxValidator& validator = wxDefaultValidator,
- const wxString& name = wxComboBoxNameStr);
-
- void init(const std::shared_ptr<FolderHistory>& sharedHistory) { sharedHistory_ = sharedHistory; }
-
- void setValue(const wxString& dirname)
- {
- setValueAndUpdateList(dirname); //required for setting value correctly + Linux to ensure the dropdown is shown as being populated
- }
-
- // GetValue
-
-private:
- void OnKeyEvent(wxKeyEvent& event);
- void OnSelection(wxCommandEvent& event);
- void OnUpdateList(wxEvent& event) { setValueAndUpdateList(GetValue()); event.Skip(); }
-
- void setValueAndUpdateList(const wxString& dirname);
-
-#if wxCHECK_VERSION(2, 9, 1)
- void OnShowDropDown(wxCommandEvent& event);
- void OnHideDropDown(wxCommandEvent& event);
-
- bool dropDownShown;
-#endif
-
- std::shared_ptr<FolderHistory> sharedHistory_;
-};
-
-
-#endif // CUSTOMCOMBOBOX_H_INCLUDED
diff --git a/lib/localization.cpp b/lib/localization.cpp
index 574910ea..8084eb42 100644
--- a/lib/localization.cpp
+++ b/lib/localization.cpp
@@ -28,8 +28,6 @@ using namespace zen;
namespace
{
//global objects
-std::wstring THOUSANDS_SEPARATOR = L",";
-
class FFSLocale : public TranslationHandler
{
@@ -38,8 +36,6 @@ public:
wxLanguage langId() const { return langId_; }
- virtual std::wstring thousandsSeparator() { return THOUSANDS_SEPARATOR; };
-
virtual std::wstring translate(const std::wstring& text)
{
//look for translation in buffer table
@@ -352,23 +348,13 @@ public:
const wxLanguageInfo* sysLngInfo = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage());
const wxLanguageInfo* selLngInfo = wxLocale::GetLanguageInfo(selectedLng);
- bool sysLangIsRTL = sysLngInfo ? sysLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
- bool selectedLangIsRTL = selLngInfo ? selLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
+ const bool sysLangIsRTL = sysLngInfo ? sysLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
+ const bool selectedLangIsRTL = selLngInfo ? selLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
if (sysLangIsRTL == selectedLangIsRTL)
loc.Init(wxLANGUAGE_DEFAULT); //use sys-lang to preserve sub-language specific rules (e.g. german swiss number punctation)
else
loc.Init(selectedLng);
-
- //::setlocale (LC_ALL, ""); -> implicitly called by wxLocale
- const lconv* localInfo = ::localeconv();
-
- //actually these two parameters are language dependent, but we take system setting to handle all kinds of language derivations
- THOUSANDS_SEPARATOR = utf8CvrtTo<wxString>(localInfo->thousands_sep);
-
- // why not working?
- // THOUSANDS_SEPARATOR = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).thousands_sep();
- // DECIMAL_POINT = std::use_facet<std::numpunct<wchar_t> >(std::locale("")).decimal_point();
}
private:
wxLocale loc; //required for RTL language support (and nothing else)
diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp
index 1052a408..a98623cf 100644
--- a/lib/parallel_scan.cpp
+++ b/lib/parallel_scan.cpp
@@ -345,7 +345,7 @@ void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const
{
boost::this_thread::interruption_point();
- const Zstring fileNameShort = shortName;
+ const Zstring fileNameShort(shortName);
//do not list the database file(s) sync.ffs_db, sync.x64.ffs_db, etc. or lock files
if (endsWith(fileNameShort, SYNC_DB_FILE_ENDING) ||
diff --git a/lib/parse_plural.h b/lib/parse_plural.h
index 4ac9e47b..c4466320 100644
--- a/lib/parse_plural.h
+++ b/lib/parse_plural.h
@@ -212,7 +212,7 @@ private:
private:
bool startsWith(const Wstring& prefix) const
{
- if (stream.end() - pos < static_cast<int>(prefix.size()))
+ if (stream.end() - pos < static_cast<ptrdiff_t>(prefix.size()))
return false;
return std::equal(prefix.begin(), prefix.end(), pos);
}
diff --git a/lib/process_xml.cpp b/lib/process_xml.cpp
index 78e14ff5..ef324246 100644
--- a/lib/process_xml.cpp
+++ b/lib/process_xml.cpp
@@ -736,27 +736,24 @@ void readConfig(const XmlIn& in, FolderPairEnh& enhPair)
void readConfig(const XmlIn& in, MainConfiguration& mainCfg)
{
//read compare settings
- XmlIn inCmp = in["MainConfig"]["Comparison"];
+ XmlIn inMain = in["MainConfig"];
- readConfig(inCmp, mainCfg.cmpConfig);
+ readConfig(inMain["Comparison"], mainCfg.cmpConfig);
//###########################################################
- XmlIn inSync = in["MainConfig"]["SyncConfig"];
-
//read sync configuration
- readConfig(inSync, mainCfg.syncCfg);
+ readConfig(inMain["SyncConfig"], mainCfg.syncCfg);
//###########################################################
- XmlIn inFilter = in["MainConfig"]["GlobalFilter"];
//read filter settings
- readConfig(inFilter, mainCfg.globalFilter);
+ readConfig(inMain["GlobalFilter"], mainCfg.globalFilter);
//###########################################################
//read all folder pairs
mainCfg.additionalPairs.clear();
bool firstIter = true;
- for (XmlIn inPair = in["MainConfig"]["FolderPairs"]["Pair"]; inPair; inPair.next())
+ for (XmlIn inPair = inMain["FolderPairs"]["Pair"]; inPair; inPair.next())
{
FolderPairEnh newPair;
readConfig(inPair, newPair);
@@ -769,6 +766,8 @@ void readConfig(const XmlIn& in, MainConfiguration& mainCfg)
else
mainCfg.additionalPairs.push_back(newPair); //set additional folder pairs
}
+
+ inMain["ExecuteWhenFinished"](mainCfg.onCompletion);
}
@@ -792,7 +791,16 @@ void readConfig(const XmlIn& in, xmlAccess::XmlBatchConfig& config)
//read GUI specific config data
XmlIn inBatchCfg = in["BatchConfig"];
- inBatchCfg["Silent" ](config.silent);
+ //-----------------------------------------------------------------------------
+ if (inBatchCfg["Silent"])
+ {
+ inBatchCfg["Silent"](config.showProgress);
+ config.showProgress = !config.showProgress;
+ }
+ else
+ //-----------------------------------------------------------------------------
+
+ inBatchCfg["ShowProgress" ](config.showProgress);
inBatchCfg["LogfileDirectory"](config.logFileDirectory);
inBatchCfg["LogfileCountMax" ](config.logFileCountMax);
inBatchCfg["HandleError" ](config.handleError);
@@ -828,14 +836,20 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config)
//gui specific global settings (optional)
XmlIn inGui = in["Gui"];
- XmlIn inWnd = inGui["Windows"]["Main"];
+ XmlIn inWnd = inGui["MainDialog"];
//read application window size and position
- inWnd["Width" ](config.gui.dlgSize.x);
- inWnd["Height" ](config.gui.dlgSize.y);
- inWnd["PosX" ](config.gui.dlgPos.x);
- inWnd["PosY" ](config.gui.dlgPos.y);
- inWnd["Maximized"](config.gui.isMaximized);
+ inWnd.attribute("Width", config.gui.dlgSize.x);
+ inWnd.attribute("Height", config.gui.dlgSize.y);
+ inWnd.attribute("PosX", config.gui.dlgPos.x);
+ inWnd.attribute("PosY", config.gui.dlgPos.y);
+ inWnd.attribute("Maximized", config.gui.isMaximized);
+
+ // inWnd["Width" ](config.gui.dlgSize.x);
+ // inWnd["Height" ](config.gui.dlgSize.y);
+ // inWnd["PosX" ](config.gui.dlgPos.x);
+ // inWnd["PosY" ](config.gui.dlgPos.y);
+ // inWnd["Maximized"](config.gui.isMaximized);
inWnd["MaxFolderPairsVisible"](config.gui.maxFolderPairsVisible);
@@ -862,11 +876,15 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config)
for (size_t i = 0; i < config.gui.columnAttribRight.size(); ++i)
config.gui.columnAttribRight[i].position = i;
- inWnd["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
- inWnd["FolderHistoryRight"](config.gui.folderHistoryRight);
- inWnd["MaximumHistorySize"](config.gui.folderHistMax);
inWnd["Perspective" ](config.gui.guiPerspectiveLast);
+ inGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
+ inGui["FolderHistoryRight"](config.gui.folderHistoryRight);
+ inGui["FolderHistoryLeft"].attribute("MaxSize", config.gui.folderHistMax);
+
+ inGui["OnCompletionHistory"](config.gui.onCompletionHistory);
+ inGui["OnCompletionHistory"].attribute("MaxSize", config.gui.onCompletionHistoryMax);
+
//external applications
inGui["ExternalApplications"](config.gui.externelApplications);
@@ -1002,24 +1020,26 @@ void writeConfigFolderPair(const FolderPairEnh& enhPair, XmlOut& out)
void writeConfig(const MainConfiguration& mainCfg, XmlOut& out)
{
- XmlOut outCmp = out["MainConfig"]["Comparison"];
+ XmlOut outMain = out["MainConfig"];
+
+ XmlOut outCmp = outMain["Comparison"];
writeConfig(mainCfg.cmpConfig, outCmp);
//###########################################################
- XmlOut outSync = out["MainConfig"]["SyncConfig"];
+ XmlOut outSync = outMain["SyncConfig"];
writeConfig(mainCfg.syncCfg, outSync);
//###########################################################
- XmlOut outFilter = out["MainConfig"]["GlobalFilter"];
+ XmlOut outFilter = outMain["GlobalFilter"];
//write filter settings
writeConfig(mainCfg.globalFilter, outFilter);
//###########################################################
//write all folder pairs
- XmlOut outFp = out["MainConfig"]["FolderPairs"];
+ XmlOut outFp = outMain["FolderPairs"];
//write first folder pair
writeConfigFolderPair(mainCfg.firstPair, outFp);
@@ -1027,6 +1047,8 @@ void writeConfig(const MainConfiguration& mainCfg, XmlOut& out)
//write additional folder pairs
std::for_each(mainCfg.additionalPairs.begin(), mainCfg.additionalPairs.end(),
[&](const FolderPairEnh& fp) { writeConfigFolderPair(fp, outFp); });
+
+ outMain["ExecuteWhenFinished"](mainCfg.onCompletion);
}
@@ -1050,7 +1072,7 @@ void writeConfig(const XmlBatchConfig& config, XmlOut& out)
//write GUI specific config data
XmlOut outBatchCfg = out["BatchConfig"];
- outBatchCfg["Silent" ](config.silent);
+ outBatchCfg["ShowProgress" ](config.showProgress);
outBatchCfg["LogfileDirectory"](config.logFileDirectory);
outBatchCfg["LogfileCountMax" ](config.logFileCountMax);
outBatchCfg["HandleError" ](config.handleError);
@@ -1077,23 +1099,23 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
outOpt["CheckForDependentFolders" ](config.optDialogs.warningDependentFolders);
outOpt["CheckForMultipleWriteAccess" ](config.optDialogs.warningMultiFolderWriteAccess);
outOpt["CheckForSignificantDifference"](config.optDialogs.warningSignificantDifference);
- outOpt["CheckForFreeDiskSpace"](config.optDialogs.warningNotEnoughDiskSpace);
- outOpt["CheckForUnresolvedConflicts"](config.optDialogs.warningUnresolvedConflicts);
- outOpt["NotifyDatabaseError"](config.optDialogs.warningSyncDatabase);
- outOpt["CheckMissingRecycleBin"](config.optDialogs.warningRecyclerMissing);
- outOpt["PopupOnConfigChange"](config.optDialogs.popupOnConfigChange);
- outOpt["SummaryBeforeSync" ](config.optDialogs.showSummaryBeforeSync);
+ outOpt["CheckForFreeDiskSpace" ](config.optDialogs.warningNotEnoughDiskSpace);
+ outOpt["CheckForUnresolvedConflicts" ](config.optDialogs.warningUnresolvedConflicts);
+ outOpt["NotifyDatabaseError" ](config.optDialogs.warningSyncDatabase);
+ outOpt["CheckMissingRecycleBin" ](config.optDialogs.warningRecyclerMissing);
+ outOpt["PopupOnConfigChange" ](config.optDialogs.popupOnConfigChange);
+ outOpt["SummaryBeforeSync" ](config.optDialogs.showSummaryBeforeSync);
//gui specific global settings (optional)
XmlOut outGui = out["Gui"];
- XmlOut outWnd = outGui["Windows"]["Main"];
+ XmlOut outWnd = outGui["MainDialog"];
//write application window size and position
- outWnd["Width" ](config.gui.dlgSize.x);
- outWnd["Height" ](config.gui.dlgSize.y);
- outWnd["PosX" ](config.gui.dlgPos.x);
- outWnd["PosY" ](config.gui.dlgPos.y);
- outWnd["Maximized"](config.gui.isMaximized);
+ outWnd.attribute("Width", config.gui.dlgSize.x);
+ outWnd.attribute("Height", config.gui.dlgSize.y);
+ outWnd.attribute("PosX", config.gui.dlgPos.x);
+ outWnd.attribute("PosY", config.gui.dlgPos.y);
+ outWnd.attribute("Maximized", config.gui.isMaximized);
outWnd["MaxFolderPairsVisible"](config.gui.maxFolderPairsVisible);
@@ -1107,27 +1129,29 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
//write column attributes
XmlOut outColLeft = outWnd["LeftColumns"];
- outColLeft.attribute("AutoAdjust", config.gui.autoAdjustColumnsLeft);
-
+ outColLeft.attribute("AutoAdjust", config.gui.autoAdjustColumnsLeft);
outColLeft(config.gui.columnAttribLeft);
//###########################################################
XmlOut outColRight = outWnd["RightColumns"];
- outColRight.attribute("AutoAdjust", config.gui.autoAdjustColumnsRight);
-
+ outColRight.attribute("AutoAdjust", config.gui.autoAdjustColumnsRight);
outColRight(config.gui.columnAttribRight);
- outWnd["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
- outWnd["FolderHistoryRight"](config.gui.folderHistoryRight);
- outWnd["MaximumHistorySize"](config.gui.folderHistMax);
outWnd["Perspective" ](config.gui.guiPerspectiveLast);
+ outGui["FolderHistoryLeft" ](config.gui.folderHistoryLeft);
+ outGui["FolderHistoryRight"](config.gui.folderHistoryRight);
+ outGui["FolderHistoryLeft" ].attribute("MaxSize", config.gui.folderHistMax);
+
+ outGui["OnCompletionHistory"](config.gui.onCompletionHistory);
+ outGui["OnCompletionHistory"].attribute("MaxSize", config.gui.onCompletionHistoryMax);
+
//external applications
outGui["ExternalApplications"](config.gui.externelApplications);
//load config file history
outGui["LastConfigActive"](config.gui.lastUsedConfigFiles);
- outGui["ConfigHistory"](config.gui.cfgFileHistory);
+ outGui["ConfigHistory" ](config.gui.cfgFileHistory);
//last update check
outGui["LastUpdateCheck"](config.gui.lastUpdateCheck);
diff --git a/lib/process_xml.h b/lib/process_xml.h
index 7f8b273b..d8ca7e54 100644
--- a/lib/process_xml.h
+++ b/lib/process_xml.h
@@ -93,13 +93,13 @@ struct XmlGuiConfig
struct XmlBatchConfig
{
XmlBatchConfig() :
- silent(false),
+ showProgress(true),
logFileCountMax(200),
handleError(ON_ERROR_POPUP) {}
zen::MainConfiguration mainCfg;
- bool silent;
+ bool showProgress;
wxString logFileDirectory;
size_t logFileCountMax;
OnError handleError; //reaction on error situation during synchronization
@@ -160,9 +160,9 @@ struct XmlGlobalSettings
OptionalDialogs optDialogs;
//---------------------------------------------------------------------
- struct _Gui
+ struct Gui
{
- _Gui() :
+ Gui() :
dlgPos(wxDefaultCoord, wxDefaultCoord),
dlgSize(wxDefaultCoord, wxDefaultCoord),
isMaximized(false),
@@ -170,6 +170,7 @@ struct XmlGlobalSettings
autoAdjustColumnsLeft(false),
autoAdjustColumnsRight(false),
folderHistMax(15),
+ onCompletionHistoryMax(8),
deleteOnBothSides(false),
useRecyclerForManualDeletion(true), //enable if OS supports it; else user will have to activate first and then get an error message
#ifdef FFS_WIN
@@ -180,17 +181,17 @@ struct XmlGlobalSettings
iconSize(ICON_SIZE_SMALL),
lastUpdateCheck(0)
{
- //default external apps will be translated "on the fly"!!!
+ //default external apps will be translated "on the fly"!!! First entry will be used for [Enter] or mouse double-click!
#ifdef FFS_WIN
- externelApplications.push_back(std::make_pair(wxT("Show in Explorer"), //mark for extraction: _("Show in Explorer")
- wxT("explorer /select, \"%name\"")));
- externelApplications.push_back(std::make_pair(wxT("Open with default application"), //mark for extraction: _("Open with default application")
- wxT("\"%name\"")));
+ externelApplications.push_back(std::make_pair(L"Show in Explorer", //mark for extraction: _("Show in Explorer")
+ L"explorer /select, \"%name\""));
+ externelApplications.push_back(std::make_pair(L"Open with default application", //mark for extraction: _("Open with default application")
+ L"\"%name\""));
#elif defined FFS_LINUX
- externelApplications.push_back(std::make_pair(wxT("Browse directory"), //mark for extraction: _("Browse directory")
- wxT("xdg-open \"%dir\"")));
- externelApplications.push_back(std::make_pair(wxT("Open with default application"), //mark for extraction: _("Open with default application")
- wxT("xdg-open \"%name\"")));
+ externelApplications.push_back(std::make_pair(L"Browse directory", //mark for extraction: _("Browse directory")
+ L"xdg-open \"%dir\""));
+ externelApplications.push_back(std::make_pair(L"Open with default application", //mark for extraction: _("Open with default application")
+ L"xdg-open \"%name\""));
#endif
}
@@ -215,6 +216,9 @@ struct XmlGlobalSettings
std::vector<Zstring> folderHistoryRight;
unsigned int folderHistMax;
+ std::vector<std::wstring> onCompletionHistory;
+ size_t onCompletionHistoryMax;
+
bool deleteOnBothSides;
bool useRecyclerForManualDeletion;
bool textSearchRespectCase;
@@ -227,7 +231,7 @@ struct XmlGlobalSettings
} gui;
//---------------------------------------------------------------------
- //struct _Batch
+ //struct Batch
};
diff --git a/lib/statistics.cpp b/lib/statistics.cpp
index 9924091c..6cc3c0cd 100644
--- a/lib/statistics.cpp
+++ b/lib/statistics.cpp
@@ -79,6 +79,13 @@ void Statistics::addMeasurement(int objectsCurrent, double dataCurrent)
}
+void Statistics::setNewTotal(int totalObjectCount, double totalDataAmount)
+{
+ objectsTotal = totalObjectCount;
+ dataTotal = totalDataAmount;
+}
+
+
wxString Statistics::getRemainingTime() const
{
if (!measurements.empty())
@@ -92,12 +99,14 @@ wxString Statistics::getRemainingTime() const
const TimeRecordMap::value_type& frontRecord = *windowBegin;
//-----------------------------------------------------------------------------------------------
- const double timeDelta = backRecord.first - frontRecord.first;
+ const double timeDelta = backRecord.first - frontRecord.first;
const double dataDelta = backRecord.second.data - frontRecord.second.data;
const double dataRemaining = dataTotal - backRecord.second.data;
+ //objects do *NOT* correspond to disk accesses, so we better play safe and use "bytes" only!
+ //https://sourceforge.net/tracker/index.php?func=detail&aid=3452469&group_id=234430&atid=1093083
- if (!numeric::isNull(dataDelta))
+ if (!numeric::isNull(dataDelta)) //sign(dataRemaining) != sign(dataDelta) usually an error, so show it!
{
int remTimeSec = dataRemaining * timeDelta / (1000.0 * dataDelta);
return zen::remainingTimeToShortString(remTimeSec);
@@ -126,7 +135,7 @@ wxString Statistics::getBytesPerSecond() const
if (!numeric::isNull(timeDelta))
if (dataDelta > 0) //may be negative if user cancels copying
- return zen::filesizeToShortString(zen::UInt64(dataDelta * 1000 / timeDelta)) + _("/sec");
+ return zen::filesizeToShortString(zen::Int64(dataDelta * 1000 / timeDelta)) + _("/sec");
}
return wxT("-"); //fallback
diff --git a/lib/statistics.h b/lib/statistics.h
index 718e4f19..62a30b99 100644
--- a/lib/statistics.h
+++ b/lib/statistics.h
@@ -42,6 +42,8 @@ public:
unsigned windowSizeBytesPerSecond); //time in ms
void addMeasurement(int objectsCurrent, double dataCurrent);
+ void setNewTotal(int totalObjectCount, double totalDataAmount); //may change during sync!
+
wxString getRemainingTime() const; //returns the remaining time in milliseconds
wxString getBytesPerSecond() const;
@@ -49,12 +51,12 @@ public:
void resumeTimer();
private:
- const int objectsTotal;
- const double dataTotal;
+ int objectsTotal;
+ double dataTotal;
- const unsigned windowSizeRemTime; //"window width" of statistics used for calculation of remaining time in ms
- const unsigned windowSizeBPS; //
- const unsigned windowMax;
+ const unsigned int windowSizeRemTime; //"window width" of statistics used for calculation of remaining time in ms
+ const unsigned int windowSizeBPS; //
+ const unsigned int windowMax;
struct Record
{
diff --git a/lib/status_handler.h b/lib/status_handler.h
index 686c1f0e..acab956a 100644
--- a/lib/status_handler.h
+++ b/lib/status_handler.h
@@ -44,7 +44,15 @@ struct ProcessCallback
//note: this one must NOT throw in order to properly allow undoing setting of statistics!
//it is in general paired with a call to requestUiRefresh() to compensate!
- virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()!!
+ virtual void updateProcessedData(int objectsDelta, zen::Int64 dataDelta) = 0; //throw()!!
+ virtual void updateTotalData (int objectsDelta, zen::Int64 dataDelta) = 0; //
+ /*the estimated total may change *during* sync:
+ 1. move file -> fallback to copy + delete
+ 2. file copy, actual size changed after comparison
+ 3. auto-resolution for failed create operations due to missing source
+ 4. directory deletion: may contain more items than scanned by FFS: excluded by filter
+ 5. delete directory to recycler or move to user-defined dir on same volume: no matter how many sub-elements exist, this is only 1 object to process!
+ 6. user-defined deletion directory on different volume: full file copy required (instead of move) */
//opportunity to abort must be implemented in a frequently executed method like requestUiRefresh()
virtual void requestUiRefresh() = 0; //throw ?
bgstack15