summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xChangelog.txt13
-rw-r--r--[-rwxr-xr-x]FreeFileSync/Build/Resources/Icons.zipbin338102 -> 391482 bytes
-rw-r--r--[-rwxr-xr-x]FreeFileSync/Build/Resources/Languages.zipbin504688 -> 506524 bytes
-rw-r--r--FreeFileSync/Source/RealTimeSync/application.cpp3
-rw-r--r--FreeFileSync/Source/RealTimeSync/application.h1
-rw-r--r--FreeFileSync/Source/RealTimeSync/gui_generated.cpp28
-rw-r--r--FreeFileSync/Source/RealTimeSync/gui_generated.h9
-rw-r--r--FreeFileSync/Source/RealTimeSync/main_dlg.cpp25
-rw-r--r--FreeFileSync/Source/afs/ftp.cpp68
-rw-r--r--FreeFileSync/Source/afs/gdrive.cpp439
-rw-r--r--FreeFileSync/Source/afs/native.cpp2
-rw-r--r--FreeFileSync/Source/afs/sftp.cpp2
-rw-r--r--FreeFileSync/Source/base/application.cpp3
-rw-r--r--FreeFileSync/Source/base/application.h2
-rw-r--r--FreeFileSync/Source/base/config.cpp103
-rw-r--r--FreeFileSync/Source/base/config.h2
-rw-r--r--FreeFileSync/Source/base/db_file.cpp6
-rw-r--r--FreeFileSync/Source/base/dir_lock.cpp32
-rw-r--r--FreeFileSync/Source/base/icon_buffer.h4
-rw-r--r--FreeFileSync/Source/base/localization.cpp155
-rw-r--r--FreeFileSync/Source/base/localization.h7
-rw-r--r--FreeFileSync/Source/base/log_file.cpp14
-rw-r--r--FreeFileSync/Source/base/path_filter.h26
-rw-r--r--FreeFileSync/Source/base/structures.cpp6
-rw-r--r--FreeFileSync/Source/base/synchronization.cpp2
-rw-r--r--FreeFileSync/Source/ui/abstract_folder_picker.cpp2
-rw-r--r--FreeFileSync/Source/ui/cfg_grid.cpp36
-rw-r--r--FreeFileSync/Source/ui/command_box.cpp2
-rw-r--r--FreeFileSync/Source/ui/file_grid.cpp79
-rw-r--r--FreeFileSync/Source/ui/file_view.cpp51
-rw-r--r--FreeFileSync/Source/ui/folder_history_box.cpp2
-rw-r--r--FreeFileSync/Source/ui/folder_pair.h25
-rw-r--r--FreeFileSync/Source/ui/gui_generated.cpp554
-rw-r--r--FreeFileSync/Source/ui/gui_generated.h69
-rw-r--r--FreeFileSync/Source/ui/log_panel.cpp10
-rw-r--r--FreeFileSync/Source/ui/main_dlg.cpp75
-rw-r--r--FreeFileSync/Source/ui/progress_indicator.cpp12
-rw-r--r--FreeFileSync/Source/ui/small_dlgs.cpp143
-rw-r--r--FreeFileSync/Source/ui/sync_cfg.cpp22
-rw-r--r--FreeFileSync/Source/ui/tree_grid.cpp20
-rw-r--r--FreeFileSync/Source/version/version.h2
-rw-r--r--wx+/bitmap_button.h12
-rw-r--r--wx+/file_drop.h2
-rw-r--r--wx+/graph.cpp8
-rw-r--r--wx+/grid.cpp55
-rw-r--r--wx+/grid.h4
-rw-r--r--wx+/image_resources.cpp127
-rw-r--r--wx+/image_resources.h2
-rw-r--r--wx+/image_tools.cpp24
-rw-r--r--wx+/image_tools.h50
-rw-r--r--wx+/popup_dlg_generated.cpp5
-rw-r--r--wx+/popup_dlg_generated.h6
-rw-r--r--wx+/rtl.h5
-rw-r--r--wx+/std_button_layout.h2
-rw-r--r--wx+/tooltip.cpp2
-rw-r--r--xBRZ/src/xbrz.cpp387
-rw-r--r--xBRZ/src/xbrz.h1
-rw-r--r--xBRZ/src/xbrz_tools.h10
-rw-r--r--zen/globals.h2
-rw-r--r--zen/legacy_compiler.h6
-rw-r--r--zen/serialize.h1
-rw-r--r--zen/stl_tools.h6
-rw-r--r--zen/string_tools.h48
-rw-r--r--zen/sys_error.h2
64 files changed, 1485 insertions, 1338 deletions
diff --git a/Changelog.txt b/Changelog.txt
index 14301dab..c4b991e7 100755
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,3 +1,16 @@
+FreeFileSync 10.19 [2019-12-27]
+-------------------------------
+Unified rendering of disabled grid layouts
+Count moved file pair as one update in view filter buttons
+Fix command button default sizes (Windows)
+Added %item_name%, %item_name2% context menu macros
+Support deleting references to shared Google Drive files
+Trash Google Drive files only when having single parent
+Fixed high DPI scaling issue on image borders
+Preserve system date format for RTL languages
+Fall back to folder path if resource archives are missing
+
+
FreeFileSync 10.18 [2019-11-19]
-------------------------------
Save/load database files in parallel
diff --git a/FreeFileSync/Build/Resources/Icons.zip b/FreeFileSync/Build/Resources/Icons.zip
index b010e86e..a02a0759 100755..100644
--- a/FreeFileSync/Build/Resources/Icons.zip
+++ b/FreeFileSync/Build/Resources/Icons.zip
Binary files differ
diff --git a/FreeFileSync/Build/Resources/Languages.zip b/FreeFileSync/Build/Resources/Languages.zip
index ba318dd8..a6c2362b 100755..100644
--- a/FreeFileSync/Build/Resources/Languages.zip
+++ b/FreeFileSync/Build/Resources/Languages.zip
Binary files differ
diff --git a/FreeFileSync/Source/RealTimeSync/application.cpp b/FreeFileSync/Source/RealTimeSync/application.cpp
index 63b8ccbe..db28c580 100644
--- a/FreeFileSync/Source/RealTimeSync/application.cpp
+++ b/FreeFileSync/Source/RealTimeSync/application.cpp
@@ -113,6 +113,9 @@ int Application::OnExit()
}
+wxLayoutDirection Application::GetLayoutDirection() const { return fff::getLayoutDirection(); }
+
+
void Application::onEnterEventLoop(wxEvent& event)
{
Disconnect(EVENT_ENTER_EVENT_LOOP, wxEventHandler(Application::onEnterEventLoop), nullptr, this);
diff --git a/FreeFileSync/Source/RealTimeSync/application.h b/FreeFileSync/Source/RealTimeSync/application.h
index 73747c6a..9c632686 100644
--- a/FreeFileSync/Source/RealTimeSync/application.h
+++ b/FreeFileSync/Source/RealTimeSync/application.h
@@ -20,6 +20,7 @@ private:
int OnExit() override;
bool OnExceptionInMainLoop() override { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun()
void OnUnhandledException () override { throw; } //just re-throw and avoid display of additional messagebox
+ wxLayoutDirection GetLayoutDirection() const override;
void onEnterEventLoop(wxEvent& event);
void onQueryEndSession(wxEvent& event);
diff --git a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
index e2cb067b..7709981d 100644
--- a/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
+++ b/FreeFileSync/Source/RealTimeSync/gui_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -32,9 +32,8 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
m_menuFile->AppendSeparator();
- wxMenuItem* m_menuItem4;
- m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
- m_menuFile->Append( m_menuItem4 );
+ m_menuItemQuit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
+ m_menuFile->Append( m_menuItemQuit );
m_menubar1->Append( m_menuFile, _("&File") );
@@ -174,12 +173,12 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
wxBoxSizer* bSizer20;
bSizer20 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonAddFolder->SetToolTip( _("Add folder") );
bSizer20->Add( m_bpButtonAddFolder, 0, wxEXPAND, 5 );
- m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonRemoveTopFolder->SetToolTip( _("Remove folder") );
bSizer20->Add( m_bpButtonRemoveTopFolder, 0, wxEXPAND, 5 );
@@ -283,6 +282,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
bSizerMain->Add( m_staticline5, 0, wxEXPAND, 5 );
m_buttonStart = new zen::BitmapTextButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonStart->SetDefault();
m_buttonStart->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -297,12 +297,12 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDlgGenerated::OnClose ) );
- this->Connect( m_menuItem6->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigNew ) );
- this->Connect( m_menuItem13->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigLoad ) );
- this->Connect( m_menuItem14->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigSave ) );
- this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuQuit ) );
- this->Connect( m_menuItemContent->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnShowHelp ) );
- this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuAbout ) );
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigNew ), this, m_menuItem6->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigLoad ), this, m_menuItem13->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnConfigSave ), this, m_menuItem14->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuQuit ), this, m_menuItemQuit->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnShowHelp ), this, m_menuItemContent->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDlgGenerated::OnMenuAbout ), this, m_menuItemAbout->GetId());
m_bpButtonAddFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnAddFolder ), NULL, this );
m_bpButtonRemoveTopFolder->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnRemoveTopFolder ), NULL, this );
m_buttonStart->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDlgGenerated::OnStart ), NULL, this );
@@ -312,14 +312,14 @@ MainDlgGenerated::~MainDlgGenerated()
{
}
-FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
wxBoxSizer* bSizer114;
bSizer114 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonRemoveFolder->SetToolTip( _("Remove folder") );
bSizer114->Add( m_bpButtonRemoveFolder, 0, wxEXPAND, 5 );
diff --git a/FreeFileSync/Source/RealTimeSync/gui_generated.h b/FreeFileSync/Source/RealTimeSync/gui_generated.h
index 323db79d..1fd190f0 100644
--- a/FreeFileSync/Source/RealTimeSync/gui_generated.h
+++ b/FreeFileSync/Source/RealTimeSync/gui_generated.h
@@ -1,12 +1,11 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
-#ifndef __GUI_GENERATED_H__
-#define __GUI_GENERATED_H__
+#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
@@ -49,6 +48,7 @@ private:
protected:
wxMenuBar* m_menubar1;
wxMenu* m_menuFile;
+ wxMenuItem* m_menuItemQuit;
wxMenu* m_menuHelp;
wxMenuItem* m_menuItemAbout;
wxBoxSizer* bSizerMain;
@@ -122,9 +122,8 @@ public:
wxBitmapButton* m_bpButtonRemoveFolder;
wxTextCtrl* m_txtCtrlDirectory;
- FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = 0 );
+ FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = 0, const wxString& name = wxEmptyString );
~FolderGenerated();
};
-#endif //__GUI_GENERATED_H__
diff --git a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
index 6ddbc215..57e188ea 100644
--- a/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
+++ b/FreeFileSync/Source/RealTimeSync/main_dlg.cpp
@@ -77,8 +77,8 @@ MainDialog::MainDialog(const Zstring& cfgFileName) :
setRelativeFontSize(*m_buttonStart, 1.5);
- m_txtCtrlDirectoryMain->SetMinSize(wxSize(fastFromDIP(300), -1));
- m_spinCtrlDelay->SetMinSize(wxSize(fastFromDIP(70), -1)); //Hack: set size (why does wxWindow::Size() not work?)
+ m_txtCtrlDirectoryMain->SetMinSize({fastFromDIP(300), -1});
+ m_spinCtrlDelay ->SetMinSize({fastFromDIP( 70), -1}); //Hack: set size (why does wxWindow::Size() not work?)
m_checkBoxHideConsole->Hide(); //only relevant on Windows
m_bpButtonRemoveTopFolder->Hide();
@@ -95,6 +95,7 @@ MainDialog::MainDialog(const Zstring& cfgFileName) :
//register key event
Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnKeyPressed), nullptr, this);
+
//prepare drag & drop
firstFolderPanel_ = std::make_unique<FolderSelector2>(this, *m_panelMainFolder, *m_buttonSelectFolderMain, *m_txtCtrlDirectoryMain, m_staticTextFinalPath);
@@ -184,21 +185,27 @@ void MainDialog::OnShowHelp(wxCommandEvent& event)
void MainDialog::OnMenuAbout(wxCommandEvent& event)
{
- std::wstring build = formatTime<std::wstring>(FORMAT_DATE, getCompileTime()) + SPACED_DASH + L"Unicode";
+ wxString build = utfTo<wxString>(fff::ffsVersion);
#ifndef wxUSE_UNICODE
#error what is going on?
#endif
- build +=
+ const wchar_t* const SPACED_BULLET = L" \u2022 ";
+ build += SPACED_BULLET;
+
+ build += LTR_MARK; //fix Arabic
#if ZEN_BUILD_ARCH == ZEN_ARCH_32BIT
- L" x86";
+ build += L"32 Bit";
#else
- L" x64";
+ build += L"64 Bit";
#endif
+ build += SPACED_BULLET;
+ build += formatTime<wxString>(FORMAT_DATE, getCompileTime());
+
showNotificationDialog(this, DialogInfoType::info, PopupDialogCfg().
setTitle(_("About")).
- setMainInstructions(L"RealTimeSync" L"\n\n" + replaceCpy(_("Build: %x"), L"%x", build)));
+ setMainInstructions(L"RealTimeSync" L"\n\n" + replaceCpy(_("Version: %x"), L"%x", build)));
}
@@ -436,7 +443,7 @@ void MainDialog::insertAddFolder(const std::vector<Zstring>& newFolders, size_t
const int folderHeight = additionalFolderPanels_.empty() ? 0 : additionalFolderPanels_[0]->GetSize().GetHeight();
const size_t visibleRows = std::min(additionalFolderPanels_.size(), MAX_ADD_FOLDERS); //up to MAX_ADD_FOLDERS additional folders shall be shown
- m_scrolledWinFolders->SetMinSize(wxSize(-1, folderHeight * static_cast<int>(visibleRows)));
+ m_scrolledWinFolders->SetMinSize({-1, folderHeight * static_cast<int>(visibleRows)});
//adapt delete top folder pair button
m_bpButtonRemoveTopFolder->Show(!additionalFolderPanels_.empty());
@@ -468,7 +475,7 @@ void MainDialog::removeAddFolder(size_t pos)
const int folderHeight = additionalFolderPanels_.empty() ? 0 : additionalFolderPanels_[0]->GetSize().GetHeight();
const size_t visibleRows = std::min(additionalFolderPanels_.size(), MAX_ADD_FOLDERS); //up to MAX_ADD_FOLDERS additional folders shall be shown
- m_scrolledWinFolders->SetMinSize(wxSize(-1, folderHeight * static_cast<int>(visibleRows)));
+ m_scrolledWinFolders->SetMinSize({-1, folderHeight * static_cast<int>(visibleRows)});
m_scrolledWinFolders->Layout(); //[!] needed when scrollbars are shown
//adapt delete top folder pair button
diff --git a/FreeFileSync/Source/afs/ftp.cpp b/FreeFileSync/Source/afs/ftp.cpp
index 9ae1c89c..0380df48 100644
--- a/FreeFileSync/Source/afs/ftp.cpp
+++ b/FreeFileSync/Source/afs/ftp.cpp
@@ -245,39 +245,39 @@ std::wstring formatFtpStatusCode(int sc)
{
switch (sc)
{
- //*INDENT-OFF*
- case 400: return L"The command was not accepted but the error condition is temporary.";
- case 421: return L"Service not available, closing control connection.";
- case 425: return L"Cannot open data connection.";
- case 426: return L"Connection closed; transfer aborted.";
- case 430: return L"Invalid username or password.";
- case 431: return L"Need some unavailable resource to process security.";
- case 434: return L"Requested host unavailable.";
- case 450: return L"Requested file action not taken.";
- case 451: return L"Local error in processing.";
- case 452: return L"Insufficient storage space in system. File unavailable, e.g. file busy.";
-
- case 500: return L"Syntax error, command unrecognized or command line too long.";
- case 501: return L"Syntax error in parameters or arguments.";
- case 502: return L"Command not implemented.";
- case 503: return L"Bad sequence of commands.";
- case 504: return L"Command not implemented for that parameter.";
- case 521: return L"Data connection cannot be opened with this PROT setting.";
- case 522: return L"Server does not support the requested network protocol.";
- case 530: return L"User not logged in.";
- case 532: return L"Need account for storing files.";
- case 533: return L"Command protection level denied for policy reasons.";
- case 534: return L"Could not connect to server; issue regarding SSL.";
- case 535: return L"Failed security check.";
- case 536: return L"Requested PROT level not supported by mechanism.";
- case 537: return L"Command protection level not supported by security mechanism.";
- case 550: return L"File unavailable, e.g. file not found, no access.";
- case 551: return L"Requested action aborted. Page type unknown.";
- case 552: return L"Requested file action aborted. Exceeded storage allocation.";
- case 553: return L"File name not allowed.";
-
- default: return L"";
- //*INDENT-ON*
+ //*INDENT-OFF*
+ case 400: return L"The command was not accepted but the error condition is temporary.";
+ case 421: return L"Service not available, closing control connection.";
+ case 425: return L"Cannot open data connection.";
+ case 426: return L"Connection closed; transfer aborted.";
+ case 430: return L"Invalid username or password.";
+ case 431: return L"Need some unavailable resource to process security.";
+ case 434: return L"Requested host unavailable.";
+ case 450: return L"Requested file action not taken.";
+ case 451: return L"Local error in processing.";
+ case 452: return L"Insufficient storage space in system. File unavailable, e.g. file busy.";
+
+ case 500: return L"Syntax error, command unrecognized or command line too long.";
+ case 501: return L"Syntax error in parameters or arguments.";
+ case 502: return L"Command not implemented.";
+ case 503: return L"Bad sequence of commands.";
+ case 504: return L"Command not implemented for that parameter.";
+ case 521: return L"Data connection cannot be opened with this PROT setting.";
+ case 522: return L"Server does not support the requested network protocol.";
+ case 530: return L"User not logged in.";
+ case 532: return L"Need account for storing files.";
+ case 533: return L"Command protection level denied for policy reasons.";
+ case 534: return L"Could not connect to server; issue regarding SSL.";
+ case 535: return L"Failed security check.";
+ case 536: return L"Requested PROT level not supported by mechanism.";
+ case 537: return L"Command protection level not supported by security mechanism.";
+ case 550: return L"File unavailable, e.g. file not found, no access.";
+ case 551: return L"Requested action aborted. Page type unknown.";
+ case 552: return L"Requested file action aborted. Exceeded storage allocation.";
+ case 553: return L"File name not allowed.";
+
+ default: return L"";
+ //*INDENT-ON*
}
}();
@@ -2262,6 +2262,6 @@ bool fff::acceptsItemPathPhraseFtp(const Zstring& itemPathPhrase) //noexcept
AbstractPath fff::createItemPathFtp(const Zstring& itemPathPhrase) //noexcept
{
- const FtpPathInfo pi = getResolvedFtpPath(itemPathPhrase); //noexcept
+ const FtpPathInfo& pi = getResolvedFtpPath(itemPathPhrase); //noexcept
return AbstractPath(makeSharedRef<FtpFileSystem>(pi.login), pi.afsPath);
}
diff --git a/FreeFileSync/Source/afs/gdrive.cpp b/FreeFileSync/Source/afs/gdrive.cpp
index fe4f932a..073e916c 100644
--- a/FreeFileSync/Source/afs/gdrive.cpp
+++ b/FreeFileSync/Source/afs/gdrive.cpp
@@ -68,7 +68,7 @@ const Zchar googleDrivePrefix[] = Zstr("gdrive:");
const char googleFolderMimeType[] = "application/vnd.google-apps.folder";
const char DB_FORMAT_DESCR[] = "FreeFileSync: Google Drive Database";
-const int DB_FORMAT_VER = 1;
+const int DB_FORMAT_VER = 2; //2019-12-05
std::string getGoogleDriveClientId () { return ""; } // => replace with live credentials
std::string getGoogleDriveClientSecret() { return ""; } //
@@ -555,25 +555,25 @@ GoogleUserInfo getUserInfo(const std::string& accessToken) //throw SysError
const char* htmlMessageTemplate = R""(<!doctype html>
<html lang="en">
<head>
- <meta charset="utf-8">
- <title>TITLE_PLACEHOLDER</title>
- <style type="text/css">
- * {
- font-family: "Helvetica Neue", "Segoe UI", Segoe, Helvetica, Arial, "Lucida Grande", sans-serif;
- text-align: center;
- background-color: #eee; }
- h1 {
- font-size: 45px;
- font-weight: 300;
- margin: 80px 0 20px 0; }
- .descr {
- font-size: 21px;
- font-weight: 200; }
- </style>
+ <meta charset="utf-8">
+ <title>TITLE_PLACEHOLDER</title>
+ <style type="text/css">
+ * {
+ font-family: "Helvetica Neue", "Segoe UI", Segoe, Helvetica, Arial, "Lucida Grande", sans-serif;
+ text-align: center;
+ background-color: #eee; }
+ h1 {
+ font-size: 45px;
+ font-weight: 300;
+ margin: 80px 0 20px 0; }
+ .descr {
+ font-size: 21px;
+ font-weight: 200; }
+ </style>
</head>
<body>
- <h1><img src="https://freefilesync.org/images/FreeFileSync.png" style="vertical-align:middle; height: 50px;" alt=""> TITLE_PLACEHOLDER</h1>
- <div class="descr">MESSAGE_PLACEHOLDER</div>
+ <h1><img src="https://freefilesync.org/images/FreeFileSync.png" style="vertical-align:middle; height: 50px;" alt=""> TITLE_PLACEHOLDER</h1>
+ <div class="descr">MESSAGE_PLACEHOLDER</div>
</body>
</html>
)"";
@@ -920,16 +920,18 @@ struct GoogleItemDetails
{
std::string itemName;
bool isFolder = false;
+ bool isShared = false;
uint64_t fileSize = 0;
- time_t modTime = 0;
+ time_t modTime = 0;
std::vector<std::string> parentIds;
};
bool operator==(const GoogleItemDetails& lhs, const GoogleItemDetails& rhs)
{
- return lhs.itemName == rhs.itemName &&
- lhs.isFolder == rhs.isFolder &&
- lhs.fileSize == rhs.fileSize &&
- lhs.modTime == rhs.modTime &&
+ return lhs.itemName == rhs.itemName &&
+ lhs.isFolder == rhs.isFolder &&
+ lhs.isShared == rhs.isShared &&
+ lhs.fileSize == rhs.fileSize &&
+ lhs.modTime == rhs.modTime &&
lhs.parentIds == rhs.parentIds;
}
@@ -951,11 +953,10 @@ std::vector<GoogleFileItem> readFolderContent(const std::string& folderId, const
std::string queryParams = xWwwFormUrlEncode(
{
{ "spaces", "drive" }, //
- { "corpora", "user" }, //"The 'user' corpus includes all files in "My Drive" and "Shared with me" https://developers.google.com/drive/api/v3/about-organization
+ { "corpora", "user" }, //"The 'user' corpus includes all files in "My Drive" and "Shared with me" https://developers.google.com/drive/api/v3/reference/files/list
{ "pageSize", "1000" }, //"[1, 1000] Default: 100"
- { "fields", "nextPageToken,incompleteSearch,files(name,id,mimeType,size,modifiedTime,parents)" }, //https://developers.google.com/drive/api/v3/reference/files
+ { "fields", "nextPageToken,incompleteSearch,files(name,id,mimeType,shared,size,modifiedTime,parents)" }, //https://developers.google.com/drive/api/v3/reference/files
{ "q", "trashed=false and '" + folderId + "' in parents" },
- //{ "q", "sharedWithMe" },
});
if (nextPageToken)
queryParams += '&' + xWwwFormUrlEncode({ { "pageToken", *nextPageToken } });
@@ -979,6 +980,7 @@ std::vector<GoogleFileItem> readFolderContent(const std::string& folderId, const
const std::optional<std::string> itemId = getPrimitiveFromJsonObject(*childVal, "id");
const std::optional<std::string> itemName = getPrimitiveFromJsonObject(*childVal, "name");
const std::optional<std::string> mimeType = getPrimitiveFromJsonObject(*childVal, "mimeType");
+ const std::optional<std::string> shared = getPrimitiveFromJsonObject(*childVal, "shared");
const std::optional<std::string> size = getPrimitiveFromJsonObject(*childVal, "size");
const std::optional<std::string> modifiedTime = getPrimitiveFromJsonObject(*childVal, "modifiedTime");
const JsonValue* parents = getChildFromJsonObject (*childVal, "parents");
@@ -987,22 +989,23 @@ std::vector<GoogleFileItem> readFolderContent(const std::string& folderId, const
throw SysError(formatGoogleErrorRaw(response));
const bool isFolder = *mimeType == googleFolderMimeType;
+ const bool isShared = shared && *shared == "true"; //"Not populated for items in shared drives"
const uint64_t fileSize = size ? stringTo<uint64_t>(*size) : 0; //not available for folders
//RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
const TimeComp tc = parseTime("%Y-%m-%dT%H:%M:%S", beforeLast(*modifiedTime, '.', IF_MISSING_RETURN_ALL));
if (tc == TimeComp() || !endsWith(*modifiedTime, 'Z')) //'Z' means "UTC" => it seems Google doesn't use the time-zone offset postfix
- throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
+ throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
time_t modTime = utcToTimeT(tc); //returns -1 on error
if (modTime == -1)
- {
+ {
if (tc.year == 1600 || //zero-initialized FILETIME equals "December 31, 1600" or "January 1, 1601"
tc.year == 1601) // => yes, possible even on Google Drive: https://freefilesync.org/forum/viewtopic.php?t=6602
modTime = 0;
else
- throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
- }
+ throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
+ }
std::vector<std::string> parentIds;
for (const auto& parentVal : parents->arrayVal)
@@ -1013,7 +1016,7 @@ std::vector<GoogleFileItem> readFolderContent(const std::string& folderId, const
}
assert(std::find(parentIds.begin(), parentIds.end(), folderId) != parentIds.end());
- childItems.push_back({ *itemId, { *itemName, isFolder, fileSize, modTime, std::move(parentIds) } });
+ childItems.push_back({ *itemId, { *itemName, isFolder, isShared, fileSize, modTime, std::move(parentIds) } });
}
}
while (nextPageToken);
@@ -1045,7 +1048,7 @@ ChangesDelta getChangesDelta(const std::string& startPageToken, const std::strin
{ "pageSize", "1000" }, //"[1, 1000] Default: 100"
{ "restrictToMyDrive", "true" }, //important! otherwise we won't get "removed: true" (because file may still be accessible from other Corpora)
{ "spaces", "drive" },
- { "fields", "kind,nextPageToken,newStartPageToken,changes(kind,removed,fileId,file(name,mimeType,size,modifiedTime,parents,trashed))" },
+ { "fields", "kind,nextPageToken,newStartPageToken,changes(kind,removed,fileId,file(name,mimeType,shared,size,modifiedTime,parents,trashed))" },
});
std::string response;
@@ -1084,6 +1087,7 @@ ChangesDelta getChangesDelta(const std::string& startPageToken, const std::strin
const std::optional<std::string> itemName = getPrimitiveFromJsonObject(*file, "name");
const std::optional<std::string> mimeType = getPrimitiveFromJsonObject(*file, "mimeType");
+ const std::optional<std::string> shared = getPrimitiveFromJsonObject(*file, "shared");
const std::optional<std::string> size = getPrimitiveFromJsonObject(*file, "size");
const std::optional<std::string> modifiedTime = getPrimitiveFromJsonObject(*file, "modifiedTime");
const std::optional<std::string> trashed = getPrimitiveFromJsonObject(*file, "trashed");
@@ -1096,22 +1100,23 @@ ChangesDelta getChangesDelta(const std::string& startPageToken, const std::strin
GoogleItemDetails itemDetails = {};
itemDetails.itemName = *itemName;
itemDetails.isFolder = *mimeType == googleFolderMimeType;
+ itemDetails.isShared = shared && *shared == "true"; //"Not populated for items in shared drives"
itemDetails.fileSize = size ? stringTo<uint64_t>(*size) : 0; //not available for folders
//RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
- const TimeComp tc = parseTime("%Y-%m-%dT%H:%M:%S", beforeLast(*modifiedTime, '.', IF_MISSING_RETURN_ALL));
- if (tc == TimeComp() || !endsWith(*modifiedTime, 'Z')) //'Z' means "UTC" => it seems Google doesn't use the time-zone offset postfix
- throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
-
- itemDetails.modTime = utcToTimeT(tc); //returns -1 on error
- if (itemDetails.modTime == -1)
- {
- if (tc.year == 1600 || //zero-initialized FILETIME equals "December 31, 1600" or "January 1, 1601"
- tc.year == 1601) // => yes, possible even on Google Drive: https://freefilesync.org/forum/viewtopic.php?t=6602
- itemDetails.modTime = 0;
- else
- throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
- }
+ const TimeComp tc = parseTime("%Y-%m-%dT%H:%M:%S", beforeLast(*modifiedTime, '.', IF_MISSING_RETURN_ALL));
+ if (tc == TimeComp() || !endsWith(*modifiedTime, 'Z')) //'Z' means "UTC" => it seems Google doesn't use the time-zone offset postfix
+ throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
+
+ itemDetails.modTime = utcToTimeT(tc); //returns -1 on error
+ if (itemDetails.modTime == -1)
+ {
+ if (tc.year == 1600 || //zero-initialized FILETIME equals "December 31, 1600" or "January 1, 1601"
+ tc.year == 1601) // => yes, possible even on Google Drive: https://freefilesync.org/forum/viewtopic.php?t=6602
+ itemDetails.modTime = 0;
+ else
+ throw SysError(L"Modification time could not be parsed. (" + utfTo<std::wstring>(*modifiedTime) + L")");
+ }
for (const auto& parentVal : parents->arrayVal)
{
@@ -1176,7 +1181,7 @@ void gdriveUnlinkParent(const std::string& itemId, const std::string& parentFold
const std::string queryParams = xWwwFormUrlEncode(
{
{ "removeParents", parentFolderId },
- { "fields", "id,parents"}, //for test if operation was successful
+ { "fields", "id,parents" }, //for test if operation was successful
});
std::string response;
googleHttpsRequest("/drive/v3/files/" + itemId + '?' + queryParams, //throw SysError
@@ -1202,7 +1207,7 @@ void gdriveUnlinkParent(const std::string& itemId, const std::string& parentFold
//- if item is a folder: trashes recursively!!!
-//- a hardlink with multiple parents will be not be accessible anymore via any of its path aliases!
+//- a hardlink with multiple parents will NOT be accessible anymore via any of its path aliases!
void gdriveMoveToTrash(const std::string& itemId, const std::string& accessToken) //throw SysError
{
//https://developers.google.com/drive/api/v3/reference/files/update
@@ -1228,11 +1233,11 @@ void gdriveMoveToTrash(const std::string& itemId, const std::string& accessToken
std::string /*folderId*/ gdriveCreateFolderPlain(const Zstring& folderName, const std::string& parentFolderId, const std::string& accessToken) //throw SysError
{
//https://developers.google.com/drive/api/v3/folder#creating_a_folder
- std::string postBuf = "{\n";
- postBuf += "\"mimeType\": \"" + std::string(googleFolderMimeType) + "\",\n";
- postBuf += "\"name\": \"" + utfTo<std::string>(folderName) + "\",\n";
- postBuf += "\"parents\": [\"" + parentFolderId + "\"]\n"; //[!] no trailing comma!
- postBuf += "}";
+ const std::string& postBuf = std::string("{\n") +
+ "\"mimeType\": \"" + std::string(googleFolderMimeType) + "\",\n" +
+ "\"name\": \"" + utfTo<std::string>(folderName) + "\",\n" +
+ "\"parents\": [\"" + parentFolderId + "\"]\n" + //[!] no trailing comma!
+ "}";
std::string response;
googleHttpsRequest("/drive/v3/files?fields=id", { "Authorization: Bearer " + accessToken, "Content-Type: application/json; charset=UTF-8" },
@@ -1267,15 +1272,14 @@ void gdriveMoveAndRenameItem(const std::string& itemId, const std::string& paren
//more Google Drive peculiarities: changing the file name changes modifiedTime!!! => workaround:
//RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
- const std::string dateTime = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(newModTime)); //returns empty string on failure
- if (dateTime.empty())
+ const std::string modTimeRfc = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(newModTime)); //returns empty string on failure
+ if (modTimeRfc.empty())
throw SysError(L"Invalid modification time (time_t: " + numberTo<std::wstring>(newModTime) + L")");
- std::string postBuf = "{\n";
- //postBuf += "\"name\": \"" + utfTo<std::string>(newName) + "\"\n";
- postBuf += "\"name\": \"" + utfTo<std::string>(newName) + "\",\n";
- postBuf += "\"modifiedTime\": \"" + dateTime + "\"\n"; //[!] no trailing comma!
- postBuf += "}";
+ const std::string& postBuf = std::string("{\n") +
+ "\"name\": \"" + utfTo<std::string>(newName) + "\",\n" +
+ "\"modifiedTime\": \"" + modTimeRfc + "\"\n" + //[!] no trailing comma!
+ "}";
std::string response;
googleHttpsRequest("/drive/v3/files/" + itemId + '?' + queryParams, //throw SysError
@@ -1304,11 +1308,11 @@ void setModTime(const std::string& itemId, time_t modTime, const std::string& ac
{
//https://developers.google.com/drive/api/v3/reference/files/update
//RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
- const std::string dateTime = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(modTime)); //returns empty string on failure
- if (dateTime.empty())
+ const std::string& modTimeRfc = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(modTime)); //returns empty string on failure
+ if (modTimeRfc.empty())
throw SysError(L"Invalid modification time (time_t: " + numberTo<std::wstring>(modTime) + L")");
- const std::string postBuf = R"({ "modifiedTime": ")" + dateTime + "\" }";
+ const std::string postBuf = R"({ "modifiedTime": ")" + modTimeRfc + "\" }";
std::string response;
googleHttpsRequest("/drive/v3/files/" + itemId + "?fields=modifiedTime", //throw SysError
@@ -1321,7 +1325,7 @@ void setModTime(const std::string& itemId, time_t modTime, const std::string& ac
catch (const JsonParsingError&) {}
const std::optional<std::string> modifiedTime = getPrimitiveFromJsonObject(jresponse, "modifiedTime");
- if (!modifiedTime || *modifiedTime != dateTime)
+ if (!modifiedTime || *modifiedTime != modTimeRfc)
throw SysError(formatGoogleErrorRaw(response));
}
#endif
@@ -1360,11 +1364,11 @@ std::string /*itemId*/ gdriveUploadSmallFile(const Zstring& fileName, const std:
std::string metaDataBuf = "{\n";
if (modTime) //convert to RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
{
- const std::string dateTime = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(*modTime)); //returns empty string on failure
- if (dateTime.empty())
+ const std::string& modTimeRfc = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(*modTime)); //returns empty string on failure
+ if (modTimeRfc.empty())
throw SysError(L"Invalid modification time (time_t: " + numberTo<std::wstring>(*modTime) + L")");
- metaDataBuf += "\"modifiedTime\": \"" + dateTime + "\",\n";
+ metaDataBuf += "\"modifiedTime\": \"" + modTimeRfc + "\",\n";
}
metaDataBuf += "\"name\": \"" + utfTo<std::string>(fileName) + "\",\n";
metaDataBuf += "\"parents\": [\"" + parentFolderId + "\"]\n"; //[!] no trailing comma!
@@ -1454,79 +1458,79 @@ std::string /*itemId*/ gdriveUploadFile(const Zstring& fileName, const std::stri
//https://developers.google.com/drive/api/v3/folder#inserting_a_file_in_a_folder
//https://developers.google.com/drive/api/v3/resumable-upload
- //step 1: initiate resumable upload session
- std::string uploadUrlRelative;
+ //step 1: initiate resumable upload session
+ std::string uploadUrlRelative;
+ {
+ std::string postBuf = "{\n";
+ if (modTime) //convert to RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
{
- std::string postBuf = "{\n";
- if (modTime) //convert to RFC 3339 date-time: e.g. "2018-09-29T08:39:12.053Z"
- {
- const std::string dateTime = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(*modTime)); //returns empty string on failure
- if (dateTime.empty())
- throw SysError(L"Invalid modification time (time_t: " + numberTo<std::wstring>(*modTime) + L")");
+ const std::string& modTimeRfc = formatTime<std::string>("%Y-%m-%dT%H:%M:%S.000Z", getUtcTime(*modTime)); //returns empty string on failure
+ if (modTimeRfc.empty())
+ throw SysError(L"Invalid modification time (time_t: " + numberTo<std::wstring>(*modTime) + L")");
- postBuf += "\"modifiedTime\": \"" + dateTime + "\",\n";
- }
- postBuf += "\"name\": \"" + utfTo<std::string>(fileName) + "\",\n";
- postBuf += "\"parents\": [\"" + parentFolderId + "\"]\n"; //[!] no trailing comma!
- postBuf += "}";
+ postBuf += "\"modifiedTime\": \"" + modTimeRfc + "\",\n";
+ }
+ postBuf += "\"name\": \"" + utfTo<std::string>(fileName) + "\",\n";
+ postBuf += "\"parents\": [\"" + parentFolderId + "\"]\n"; //[!] no trailing comma!
+ postBuf += "}";
- std::string uploadUrl;
+ std::string uploadUrl;
- auto onBytesReceived = [&](const char* buffer, size_t len)
- {
- //inside libcurl's C callstack => better not throw exceptions here!!!
- //"The callback will be called once for each header and only complete header lines are passed on to the callback" (including \r\n at the end)
- if (startsWithAsciiNoCase(std::string_view(buffer, len), "Location:"))
- {
- uploadUrl.assign(buffer, len); //not null-terminated!
- uploadUrl = afterFirst(uploadUrl, ':', IF_MISSING_RETURN_NONE);
- trim(uploadUrl);
- }
- return len;
- };
- using ReadCbType = decltype(onBytesReceived);
- using ReadCbWrapperType = size_t (*)(const char* buffer, size_t size, size_t nitems, ReadCbType* callbackData); //needed for cdecl function pointer cast
- ReadCbWrapperType onBytesReceivedWrapper = [](const char* buffer, size_t size, size_t nitems, ReadCbType* callbackData)
+ auto onBytesReceived = [&](const char* buffer, size_t len)
+ {
+ //inside libcurl's C callstack => better not throw exceptions here!!!
+ //"The callback will be called once for each header and only complete header lines are passed on to the callback" (including \r\n at the end)
+ if (startsWithAsciiNoCase(std::string_view(buffer, len), "Location:"))
{
- return (*callbackData)(buffer, size * nitems); //free this poor little C-API from its shackles and redirect to a proper lambda
- };
+ uploadUrl.assign(buffer, len); //not null-terminated!
+ uploadUrl = afterFirst(uploadUrl, ':', IF_MISSING_RETURN_NONE);
+ trim(uploadUrl);
+ }
+ return len;
+ };
+ using ReadCbType = decltype(onBytesReceived);
+ using ReadCbWrapperType = size_t (*)(const char* buffer, size_t size, size_t nitems, ReadCbType* callbackData); //needed for cdecl function pointer cast
+ ReadCbWrapperType onBytesReceivedWrapper = [](const char* buffer, size_t size, size_t nitems, ReadCbType* callbackData)
+ {
+ return (*callbackData)(buffer, size * nitems); //free this poor little C-API from its shackles and redirect to a proper lambda
+ };
- std::string response;
- const HttpSession::HttpResult httpResult = googleHttpsRequest("/upload/drive/v3/files?uploadType=resumable", //throw SysError
- { "Authorization: Bearer " + accessToken, "Content-Type: application/json; charset=UTF-8" },
- { { CURLOPT_POSTFIELDS, postBuf.c_str() }, { CURLOPT_HEADERDATA, &onBytesReceived }, { CURLOPT_HEADERFUNCTION, onBytesReceivedWrapper } },
- [&](const void* buffer, size_t bytesToWrite) { response.append(static_cast<const char*>(buffer), bytesToWrite); }, nullptr /*readRequest*/);
+ std::string response;
+ const HttpSession::HttpResult httpResult = googleHttpsRequest("/upload/drive/v3/files?uploadType=resumable", //throw SysError
+ { "Authorization: Bearer " + accessToken, "Content-Type: application/json; charset=UTF-8" },
+ { { CURLOPT_POSTFIELDS, postBuf.c_str() }, { CURLOPT_HEADERDATA, &onBytesReceived }, { CURLOPT_HEADERFUNCTION, onBytesReceivedWrapper } },
+ [&](const void* buffer, size_t bytesToWrite) { response.append(static_cast<const char*>(buffer), bytesToWrite); }, nullptr /*readRequest*/);
- if (httpResult.statusCode != 200)
- throw SysError(formatGoogleErrorRaw(response));
+ if (httpResult.statusCode != 200)
+ throw SysError(formatGoogleErrorRaw(response));
- if (!startsWith(uploadUrl, "https://www.googleapis.com/"))
- throw SysError(L"Invalid upload URL: " + utfTo<std::wstring>(uploadUrl)); //user should never see this
+ if (!startsWith(uploadUrl, "https://www.googleapis.com/"))
+ throw SysError(L"Invalid upload URL: " + utfTo<std::wstring>(uploadUrl)); //user should never see this
- uploadUrlRelative = afterFirst(uploadUrl, "googleapis.com", IF_MISSING_RETURN_NONE);
- }
- //---------------------------------------------------
- //step 2: upload file content
+ uploadUrlRelative = afterFirst(uploadUrl, "googleapis.com", IF_MISSING_RETURN_NONE);
+ }
+ //---------------------------------------------------
+ //step 2: upload file content
- //not officially documented, but Google Drive supports compressed file upload when "Content-Encoding: gzip" is set! :)))
- InputStreamAsGzip gzipStream(readBlock); //throw SysError
+ //not officially documented, but Google Drive supports compressed file upload when "Content-Encoding: gzip" is set! :)))
+ InputStreamAsGzip gzipStream(readBlock); //throw SysError
- auto readBlockAsGzip = [&](void* buffer, size_t bytesToRead) { return gzipStream.read(buffer, bytesToRead); }; //throw SysError, X
- //returns "bytesToRead" bytes unless end of stream! => fits into "0 signals EOF: Posix read() semantics"
+ auto readBlockAsGzip = [&](void* buffer, size_t bytesToRead) { return gzipStream.read(buffer, bytesToRead); }; //throw SysError, X
+ //returns "bytesToRead" bytes unless end of stream! => fits into "0 signals EOF: Posix read() semantics"
- std::string response;
- googleHttpsRequest(uploadUrlRelative, { "Content-Encoding: gzip" }, {} /*extraOptions*/, //throw SysError, X
- [&](const void* buffer, size_t bytesToWrite) { response.append(static_cast<const char*>(buffer), bytesToWrite); }, readBlockAsGzip);
+ std::string response;
+ googleHttpsRequest(uploadUrlRelative, { "Content-Encoding: gzip" }, {} /*extraOptions*/, //throw SysError, X
+ [&](const void* buffer, size_t bytesToWrite) { response.append(static_cast<const char*>(buffer), bytesToWrite); }, readBlockAsGzip);
- JsonValue jresponse;
- try { jresponse = parseJson(response); }
- catch (JsonParsingError&) {}
+ JsonValue jresponse;
+ try { jresponse = parseJson(response); }
+ catch (JsonParsingError&) {}
- const std::optional<std::string> itemId = getPrimitiveFromJsonObject(jresponse, "id");
- if (!itemId)
- throw SysError(formatGoogleErrorRaw(response));
+ const std::optional<std::string> itemId = getPrimitiveFromJsonObject(jresponse, "id");
+ if (!itemId)
+ throw SysError(formatGoogleErrorRaw(response));
- return *itemId;
+ return *itemId;
}
@@ -1612,35 +1616,42 @@ public:
rootId_ (getRootItemId (accessBuf.getAccessToken())), //throw SysError
accessBuf_(accessBuf) {} //
- GoogleFileState(MemoryStreamIn<ByteArray>& stream, GoogleAccessBuffer& accessBuf) : accessBuf_(accessBuf) //throw UnexpectedEndOfStreamError
+ GoogleFileState(MemoryStreamIn<ByteArray>& stream, GoogleAccessBuffer& accessBuf, int dbVersion) : accessBuf_(accessBuf) //throw UnexpectedEndOfStreamError
{
lastSyncToken_ = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
- rootId_ = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
+ rootId_ = readContainer<std::string>(stream); //
- for (;;)
+ //TODO: remove migration code at some time! 2019-12-05
+ if (dbVersion == 1)
+ ; //fully discard old state due to missing "isShared" attribute :(
+ else
{
- const std::string folderId = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
- if (folderId.empty())
- break;
- folderContents_[folderId].isKnownFolder = true;
- }
+ for (;;)
+ {
+ const std::string folderId = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
+ if (folderId.empty())
+ break;
+ folderContents_[folderId].isKnownFolder = true;
+ }
- size_t itemCount = readNumber<int32_t>(stream);
- while (itemCount-- != 0)
- {
- const std::string itemId = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
+ size_t itemCount = readNumber<int32_t>(stream);
+ while (itemCount-- != 0)
+ {
+ const std::string itemId = readContainer<std::string>(stream); //UnexpectedEndOfStreamError
- GoogleItemDetails details = {};
- details.itemName = readContainer<std::string>(stream); //
- details.isFolder = readNumber <int8_t>(stream) != 0; //UnexpectedEndOfStreamError
- details.fileSize = readNumber <uint64_t>(stream); //
- details.modTime = readNumber <int64_t>(stream); //
+ GoogleItemDetails details = {};
+ details.itemName = readContainer<std::string>(stream); //
+ details.isFolder = readNumber <int8_t>(stream) != 0; //
+ details.isShared = readNumber <int8_t>(stream) != 0; //UnexpectedEndOfStreamError
+ details.fileSize = readNumber <uint64_t>(stream); //
+ details.modTime = readNumber <int64_t>(stream); //
- size_t parentsCount = readNumber<int32_t>(stream); //UnexpectedEndOfStreamError
- while (parentsCount-- != 0)
- details.parentIds.push_back(readContainer<std::string>(stream)); //UnexpectedEndOfStreamError
+ size_t parentsCount = readNumber<int32_t>(stream); //UnexpectedEndOfStreamError
+ while (parentsCount-- != 0)
+ details.parentIds.push_back(readContainer<std::string>(stream)); //UnexpectedEndOfStreamError
- updateItemState(itemId, std::move(details));
+ updateItemState(itemId, std::move(details));
+ }
}
}
@@ -1662,6 +1673,7 @@ public:
writeContainer(stream, itemId);
writeContainer(stream, details.itemName);
writeNumber< int8_t>(stream, details.isFolder);
+ writeNumber< int8_t>(stream, details.isShared);
writeNumber<uint64_t>(stream, details.fileSize);
writeNumber< int64_t>(stream, details.modTime);
static_assert(sizeof(details.modTime) <= sizeof(int64_t)); //ensure cross-platform compatibility!
@@ -1755,12 +1767,12 @@ public:
GoogleItemDetails details = {};
details.itemName = utfTo<std::string>(folderName);
details.isFolder = true;
+ details.isShared = false;
details.modTime = std::time(nullptr);
details.parentIds.push_back(parentId);
//avoid needless conflicts due to different Google Drive folder modTime!
- auto it = itemDetails_.find(folderId);
- if (it != itemDetails_.end())
+ if (auto it = itemDetails_.find(folderId); it != itemDetails_.end())
details.modTime = it->second.modTime;
notifyItemUpdate(stateDelta, folderId, details);
@@ -1773,8 +1785,7 @@ public:
void notifyParentRemoved(const FileStateDelta& stateDelta, const std::string& itemId, const std::string& parentIdOld)
{
- auto it = itemDetails_.find(itemId);
- if (it != itemDetails_.end())
+ if (auto it = itemDetails_.find(itemId); it != itemDetails_.end())
{
GoogleItemDetails detailsNew = it->second;
std::erase_if(detailsNew.parentIds, [&](const std::string& id) { return id == parentIdOld; });
@@ -1786,8 +1797,7 @@ public:
void notifyMoveAndRename(const FileStateDelta& stateDelta, const std::string& itemId, const std::string& parentIdFrom, const std::string& parentIdTo, const Zstring& newName)
{
- auto it = itemDetails_.find(itemId);
- if (it != itemDetails_.end())
+ if (auto it = itemDetails_.find(itemId); it != itemDetails_.end())
{
GoogleItemDetails detailsNew = it->second;
detailsNew.itemName = utfTo<std::string>(newName);
@@ -1809,8 +1819,8 @@ private:
void notifyItemUpdate(const FileStateDelta& stateDelta, const std::string& itemId, const std::optional<GoogleItemDetails>& details)
{
- if (stateDelta.changedIds->find(itemId) == stateDelta.changedIds->end()) //=> no conflicting changes in the meantime
- updateItemState(itemId, details); //accept new state data
+ if (!contains(*stateDelta.changedIds, itemId)) //no conflicting changes in the meantime?
+ updateItemState(itemId, details); //=> accept new state data
else //conflict?
{
auto it = itemDetails_.find(itemId);
@@ -1896,7 +1906,6 @@ private:
void updateItemState(const std::string& itemId, const std::optional<GoogleItemDetails>& details)
{
auto it = itemDetails_.find(itemId);
-
if (!details == (it == itemDetails_.end()))
if (!details || *details == it->second) //notified changes match our current file state
return; //=> avoid misleading changeLog_ entries after Google Drive sync!!!
@@ -1930,11 +1939,8 @@ private:
folderContents_[parentId].childItems.push_back(it); //new insert => no need for duplicate check
for (const std::string& parentId : parentIdsRemoved)
- {
- auto itP = folderContents_.find(parentId);
- if (itP != folderContents_.end())
+ if (auto itP = folderContents_.find(parentId); itP != folderContents_.end())
std::erase_if(itP->second.childItems, [&](auto itChild) { return itChild == it; });
- }
//if all parents are removed, Google Drive will (recursively) delete the item => don't prematurely do this now: wait for change notifications!
it->second = *details;
@@ -1952,16 +1958,13 @@ private:
if (it != itemDetails_.end())
{
for (const std::string& parentId : it->second.parentIds) //1. delete from parent folders
- {
- auto itP = folderContents_.find(parentId);
- if (itP != folderContents_.end())
+ if (auto itP = folderContents_.find(parentId); itP != folderContents_.end())
std::erase_if(itP->second.childItems, [&](auto itChild) { return itChild == it; });
- }
+
itemDetails_.erase(it);
}
- auto itP = folderContents_.find(itemId);
- if (itP != folderContents_.end())
+ if (auto itP = folderContents_.find(itemId); itP != folderContents_.end())
{
for (auto itChild : itP->second.childItems) //2. delete as parent from child items (don't wait for change notifications of children)
std::erase_if(itChild->second.parentIds, [&](const std::string& id) { return id == itemId; });
@@ -2229,24 +2232,30 @@ private:
{
rawStream = decompress(zstream); //throw SysError
}
- catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(dbFilePath)), e.toString()); }
+ catch (const SysError& e) { throw FileError(_("Database file is corrupted:") + L" " + fmtPath(dbFilePath), e.toString()); }
MemoryStreamIn<ByteArray> streamIn(rawStream);
try
{
+ //-------- file format header --------
char tmp[sizeof(DB_FORMAT_DESCR)] = {};
- readArray(streamIn, &tmp, sizeof(tmp)); //file format header
- const int fileVersion = readNumber<int32_t>(streamIn); //
+ readArray(streamIn, &tmp, sizeof(tmp)); //throw UnexpectedEndOfStreamError
+
+ if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(DB_FORMAT_DESCR)))
+ throw FileError(replaceCpy(_("Database file %x is incompatible."), L"%x", fmtPath(dbFilePath)));
+
+ const int dbVersion = readNumber<int32_t>(streamIn);
- if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(DB_FORMAT_DESCR)) ||
- fileVersion != DB_FORMAT_VER)
- throw UnexpectedEndOfStreamError(); //well, not really...!?
+ //TODO: remove migration code at some time! 2019-12-05
+ if (dbVersion != 1 &&
+ dbVersion != DB_FORMAT_VER)
+ throw FileError(replaceCpy(_("Database file %x is incompatible."), L"%x", fmtPath(dbFilePath)));
- auto accessBuf = makeSharedRef<GoogleAccessBuffer>(streamIn); //throw UnexpectedEndOfStreamError
- auto fileState = makeSharedRef<GoogleFileState >(streamIn, accessBuf.ref()); //throw UnexpectedEndOfStreamError
+ auto accessBuf = makeSharedRef<GoogleAccessBuffer>(streamIn); //throw UnexpectedEndOfStreamError
+ auto fileState = makeSharedRef<GoogleFileState >(streamIn, accessBuf.ref(), dbVersion); //throw UnexpectedEndOfStreamError
return { accessBuf, fileState };
}
- catch (UnexpectedEndOfStreamError&) { throw FileError(replaceCpy(_("Cannot read file %x."), L"%x", fmtPath(dbFilePath)), L"Unexpected end of stream."); }
+ catch (UnexpectedEndOfStreamError&) { throw FileError(_("Database file is corrupted:") + L" " + fmtPath(dbFilePath), L"Unexpected end of stream."); }
}
struct UserSession
@@ -2447,10 +2456,10 @@ struct InputStreamGdrive : public AbstractFileSystem::InputStream
{
accessGlobalFileState(gdrivePath_.userEmail, [&](GoogleFileState& fileState) //throw SysError
{
- std::pair<std::string /*itemId*/, GoogleItemDetails> gdriveAttr = fileState.getFileAttributes(gdrivePath_.itemPath); //throw SysError
- attr.modTime = gdriveAttr.second.modTime;
- attr.fileSize = gdriveAttr.second.fileSize;
- attr.fileId = copyStringTo<AFS::FileId>(gdriveAttr.first);
+ const auto& [itemId, gdriveAttr] = fileState.getFileAttributes(gdrivePath_.itemPath); //throw SysError
+ attr.modTime = gdriveAttr.modTime;
+ attr.fileSize = gdriveAttr.fileSize;
+ attr.fileId = copyStringTo<AFS::FileId>(itemId);
});
}
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(getGoogleDisplayPath(gdrivePath_))), e.toString()); }
@@ -2530,6 +2539,7 @@ struct OutputStreamGdrive : public AbstractFileSystem::OutputStreamImpl
newFileItem.itemId = fileIdNew;
newFileItem.details.itemName = utfTo<std::string>(fileName);
newFileItem.details.isFolder = false;
+ newFileItem.details.isShared = false;
newFileItem.details.fileSize = asyncStreamIn->getTotalBytesRead();
if (modTime) //else: whatever modTime Google Drive selects will be notified after GOOGLE_DRIVE_SYNC_INTERVAL
newFileItem.details.modTime = *modTime;
@@ -2678,7 +2688,7 @@ private:
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(getDisplayPath(afsPath))), e.toString()); }
}
- void removeItemPlainImpl(const AfsPath& afsPath) const //throw SysError
+ void removeItemPlainImpl(const AfsPath& afsPath, bool permanent /*...or move to trash*/) const //throw SysError
{
std::string itemId;
std::optional<std::string> parentIdToUnlink;
@@ -2687,12 +2697,12 @@ private:
const std::optional<AfsPath> parentPath = getParentPath(afsPath);
if (!parentPath) throw SysError(L"Item is device root");
- std::pair<std::string /*itemId*/, GoogleItemDetails> gdriveAttr = fileState.getFileAttributes(afsPath); //throw SysError
- itemId = gdriveAttr.first;
- assert(gdriveAttr.second.parentIds.size() > 1 ||
- (gdriveAttr.second.parentIds.size() == 1 && gdriveAttr.second.parentIds[0] == fileState.getItemId(*parentPath)));
+ GoogleItemDetails gdriveAttr;
+ std::tie(itemId, gdriveAttr) = fileState.getFileAttributes(afsPath); //throw SysError
+ assert(std::find(gdriveAttr.parentIds.begin(), gdriveAttr.parentIds.end(), fileState.getItemId(*parentPath)) != gdriveAttr.parentIds.end());
- if (gdriveAttr.second.parentIds.size() != 1) //hard-link handling
+ //hard-link handling applies to shared files as well: 1. it's the right thing (TM) 2. deleting would fail anyway because we're not the owner
+ if (gdriveAttr.parentIds.size() > 1 || gdriveAttr.isShared)
parentIdToUnlink = fileState.getItemId(*parentPath); //throw SysError
});
@@ -2708,7 +2718,10 @@ private:
}
else
{
- gdriveDeleteItem(itemId, aai.accessToken); //throw SysError
+ if (permanent)
+ gdriveDeleteItem(itemId, aai.accessToken); //throw SysError
+ else
+ gdriveMoveToTrash(itemId, aai.accessToken); //throw SysError
//buffer new file state ASAP (don't wait GOOGLE_DRIVE_SYNC_INTERVAL)
accessGlobalFileState(googleUserEmail_, [&](GoogleFileState& fileState) //throw SysError
@@ -2722,7 +2735,7 @@ private:
{
try
{
- removeItemPlainImpl(afsPath); //throw SysError
+ removeItemPlainImpl(afsPath, true /*permanent*/); //throw SysError
}
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete file %x."), L"%x", fmtPath(getDisplayPath(afsPath))), e.toString()); }
}
@@ -2736,7 +2749,7 @@ private:
{
try
{
- removeItemPlainImpl(afsPath); //throw SysError
+ removeItemPlainImpl(afsPath, true /*permanent*/); //throw SysError
}
catch (const SysError& e) { throw FileError(replaceCpy(_("Cannot delete directory %x."), L"%x", fmtPath(getDisplayPath(afsPath))), e.toString()); }
}
@@ -2753,9 +2766,8 @@ private:
}
catch (const FileError&)
{
- if (!itemStillExists(afsPath)) //throw FileError
- return;
- throw;
+ if (itemStillExists(afsPath)) //throw FileError
+ throw;
}
}
@@ -2858,9 +2870,10 @@ private:
std::string parentIdTo;
const GooglePersistentSessions::AsyncAccessInfo aai = accessGlobalFileState(googleUserEmail_, [&](GoogleFileState& fileState) //throw SysError
{
- std::pair<std::string /*itemId*/, GoogleItemDetails> gdriveAttr = fileState.getFileAttributes(pathFrom); //throw SysError
- itemIdFrom = gdriveAttr.first;
- modTimeFrom = gdriveAttr.second.modTime;
+ GoogleItemDetails gdriveAttr;
+ std::tie(itemIdFrom, gdriveAttr) = fileState.getFileAttributes(pathFrom); //throw SysError
+
+ modTimeFrom = gdriveAttr.modTime;
parentIdFrom = fileState.getItemId(*parentPathFrom); //throw SysError
GoogleFileState::PathStatus psTo = fileState.getPathStatus(pathTo.afsPath); //throw SysError
@@ -2937,13 +2950,14 @@ private:
bool supportsRecycleBin(const AfsPath& afsPath) const override { return true; } //throw FileError
- struct RecycleSessionGdrive : public RecycleSession
- {
- void recycleItemIfExists(const AbstractPath& itemPath, const Zstring& logicalRelPath) override { AFS::recycleItemIfExists(itemPath); } //throw FileError
- void tryCleanup(const std::function<void (const std::wstring& displayPath)>& notifyDeletionStatus) override {}; //throw FileError
- };
std::unique_ptr<RecycleSession> createRecyclerSession(const AfsPath& afsPath) const override //throw FileError, return value must be bound!
{
+ struct RecycleSessionGdrive : public RecycleSession
+ {
+ void recycleItemIfExists(const AbstractPath& itemPath, const Zstring& logicalRelPath) override { AFS::recycleItemIfExists(itemPath); } //throw FileError
+ void tryCleanup(const std::function<void (const std::wstring& displayPath)>& notifyDeletionStatus) override {}; //throw FileError
+ };
+
return std::make_unique<RecycleSessionGdrive>();
}
@@ -2951,24 +2965,13 @@ private:
{
try
{
- GoogleFileState::PathStatus ps;
- const GooglePersistentSessions::AsyncAccessInfo aai = accessGlobalFileState(googleUserEmail_, [&](GoogleFileState& fileState) //throw SysError
- {
- ps = fileState.getPathStatus(afsPath); //throw SysError
- });
- if (ps.relPath.empty())
- {
- gdriveMoveToTrash(ps.existingItemId, aai.accessToken); //throw SysError
-
- //buffer new file state ASAP (don't wait GOOGLE_DRIVE_SYNC_INTERVAL)
- accessGlobalFileState(googleUserEmail_, [&](GoogleFileState& fileState) //throw SysError
- {
- //a hardlink with multiple parents will be not be accessible anymore via any of its path aliases!
- fileState.notifyItemDeleted(aai.stateDelta, ps.existingItemId);
- });
- }
+ removeItemPlainImpl(afsPath, false /*permanent*/); //throw SysError
+ }
+ catch (const SysError& e)
+ {
+ if (itemStillExists(afsPath)) //throw FileError
+ throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(getDisplayPath(afsPath))), e.toString());
}
- catch (const SysError& e) { throw FileError(replaceCpy(_("Unable to move %x to the recycle bin."), L"%x", fmtPath(getDisplayPath(afsPath))), e.toString()); }
}
const Zstring googleUserEmail_;
@@ -3059,10 +3062,10 @@ GdrivePath fff::getResolvedGooglePath(const Zstring& folderPathPhrase) //noexcep
if (startsWithAsciiNoCase(path, googleDrivePrefix))
path = path.c_str() + strLength(googleDrivePrefix);
- const AfsPath sanPath = sanitizeRootRelativePath(path); //Win/macOS compatibility: let's ignore slash/backslash differences
+ const AfsPath& sanPath = sanitizeRootRelativePath(path); //Win/macOS compatibility: let's ignore slash/backslash differences
- const Zstring userEmail = beforeFirst(sanPath.value, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
- const AfsPath afsPath (afterFirst(sanPath.value, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
+ const Zstring& userEmail = beforeFirst(sanPath.value, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL);
+ const AfsPath afsPath (afterFirst(sanPath.value, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE));
return { userEmail, afsPath };
}
@@ -3078,6 +3081,6 @@ bool fff::acceptsItemPathPhraseGdrive(const Zstring& itemPathPhrase) //noexcept
AbstractPath fff::createItemPathGdrive(const Zstring& itemPathPhrase) //noexcept
{
- const GdrivePath gdrivePath = getResolvedGooglePath(itemPathPhrase); //noexcept
+ const GdrivePath& gdrivePath = getResolvedGooglePath(itemPathPhrase); //noexcept
return AbstractPath(makeSharedRef<GdriveFileSystem>(gdrivePath.userEmail), gdrivePath.itemPath);
}
diff --git a/FreeFileSync/Source/afs/native.cpp b/FreeFileSync/Source/afs/native.cpp
index 937523fc..da016788 100644
--- a/FreeFileSync/Source/afs/native.cpp
+++ b/FreeFileSync/Source/afs/native.cpp
@@ -670,7 +670,7 @@ bool fff::acceptsItemPathPhraseNative(const Zstring& itemPathPhrase) //noexcept
AbstractPath fff::createItemPathNative(const Zstring& itemPathPhrase) //noexcept
{
//TODO: get volume by name hangs for idle HDD! => run createItemPathNative during getFolderStatusNonBlocking() but getResolvedFilePath currently not thread-safe!
- const Zstring itemPath = getResolvedFilePath(itemPathPhrase);
+ const Zstring& itemPath = getResolvedFilePath(itemPathPhrase);
return createItemPathNativeNoFormatting(itemPath);
}
diff --git a/FreeFileSync/Source/afs/sftp.cpp b/FreeFileSync/Source/afs/sftp.cpp
index 163df3a5..1fcedc43 100644
--- a/FreeFileSync/Source/afs/sftp.cpp
+++ b/FreeFileSync/Source/afs/sftp.cpp
@@ -2004,6 +2004,6 @@ bool fff::acceptsItemPathPhraseSftp(const Zstring& itemPathPhrase) //noexcept
AbstractPath fff::createItemPathSftp(const Zstring& itemPathPhrase) //noexcept
{
- const SftpPathInfo pi = getResolvedSftpPath(itemPathPhrase); //noexcept
+ const SftpPathInfo& pi = getResolvedSftpPath(itemPathPhrase); //noexcept
return AbstractPath(makeSharedRef<SftpFileSystem>(pi.login), pi.afsPath);
}
diff --git a/FreeFileSync/Source/base/application.cpp b/FreeFileSync/Source/base/application.cpp
index d032955b..d66b08ff 100644
--- a/FreeFileSync/Source/base/application.cpp
+++ b/FreeFileSync/Source/base/application.cpp
@@ -132,6 +132,9 @@ int Application::OnExit()
}
+wxLayoutDirection Application::GetLayoutDirection() const { return getLayoutDirection(); }
+
+
void Application::onEnterEventLoop(wxEvent& event)
{
Disconnect(EVENT_ENTER_EVENT_LOOP, wxEventHandler(Application::onEnterEventLoop), nullptr, this);
diff --git a/FreeFileSync/Source/base/application.h b/FreeFileSync/Source/base/application.h
index c08491c8..a52e6617 100644
--- a/FreeFileSync/Source/base/application.h
+++ b/FreeFileSync/Source/base/application.h
@@ -23,7 +23,7 @@ private:
int OnExit() override;
bool OnExceptionInMainLoop() override { throw; } //just re-throw and avoid display of additional messagebox: it will be caught in OnRun()
void OnUnhandledException () override { throw; } //just re-throw and avoid display of additional messagebox
-
+ wxLayoutDirection GetLayoutDirection() const override;
void onEnterEventLoop(wxEvent& event);
void onQueryEndSession(wxEvent& event);
void launch(const std::vector<Zstring>& commandArgs);
diff --git a/FreeFileSync/Source/base/config.cpp b/FreeFileSync/Source/base/config.cpp
index 3ed3f416..552b377f 100644
--- a/FreeFileSync/Source/base/config.cpp
+++ b/FreeFileSync/Source/base/config.cpp
@@ -11,18 +11,17 @@
#include <zen/time.h>
#include <wx/intl.h>
#include "ffs_paths.h"
-#include "../afs/concrete.h"
+//#include "../afs/concrete.h"
using namespace zen;
using namespace fff; //functionally needed for correct overload resolution!!!
-//using AFS = AbstractFileSystem;
namespace
{
//-------------------------------------------------------------------------------------------------------------------------------
-const int XML_FORMAT_GLOBAL_CFG = 14; //2019-11-19
+const int XML_FORMAT_GLOBAL_CFG = 15; //2019-11-30
const int XML_FORMAT_SYNC_CFG = 14; //2018-08-13
//-------------------------------------------------------------------------------------------------------------------------------
}
@@ -106,20 +105,24 @@ XmlBatchConfig fff::convertGuiToBatch(const XmlGuiConfig& guiCfg, const BatchExc
namespace
{
-std::vector<Zstring> splitFilterByLines(const Zstring& filterPhrase)
+std::vector<Zstring> splitFilterByLines(Zstring filterPhrase)
{
+ trim(filterPhrase);
if (filterPhrase.empty())
return {};
+
return split(filterPhrase, Zstr('\n'), SplitType::ALLOW_EMPTY);
}
Zstring mergeFilterLines(const std::vector<Zstring>& filterLines)
{
- if (filterLines.empty())
- return Zstring();
- Zstring out = filterLines[0];
- std::for_each(filterLines.begin() + 1, filterLines.end(), [&](const Zstring& line) { out += Zstr('\n'); out += line; });
- return out;
+ Zstring out;
+ for (const Zstring& line : filterLines)
+ {
+ out += line;
+ out += Zstr('\n');
+ }
+ return trimCpy(out);
}
}
@@ -1562,20 +1565,18 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& cfg, int formatVer)
for (const ConfigFileItemV9& item : cfgFileHistory)
cfg.gui.mainDlg.cfgFileHistory.emplace_back(item.filePath, item.lastSyncTime, getNullPath(), SyncResult::finishedSuccess, wxNullColour);
}
- //TODO: remove after migration! 2019-11-19
- else if (formatVer < 14)
+ else
{
inConfig["Configurations"].attribute("MaxSize", cfg.gui.mainDlg.cfgHistItemsMax);
inConfig["Configurations"](cfg.gui.mainDlg.cfgFileHistory);
-
- for (ConfigFileItem& item : cfg.gui.mainDlg.cfgFileHistory)
- if (equalNativePath(item.cfgFilePath, getLastRunConfigPath()))
- item.backColor = wxColor(0xdd, 0xdd, 0xdd); //light grey from onCfgGridContext()
}
- else
+ //TODO: remove after migration! 2019-11-30
+ if (formatVer < 15)
{
- inConfig["Configurations"].attribute("MaxSize", cfg.gui.mainDlg.cfgHistItemsMax);
- inConfig["Configurations"](cfg.gui.mainDlg.cfgFileHistory);
+ const Zstring lastRunConfigPath = getConfigDirPathPf() + Zstr("LastRun.ffs_gui");
+ for (ConfigFileItem& item : cfg.gui.mainDlg.cfgFileHistory)
+ if (equalNativePath(item.cfgFilePath, lastRunConfigPath))
+ item.backColor = wxColor(0xdd, 0xdd, 0xdd); //light grey from onCfgGridContext()
}
//TODO: remove parameter migration after some time! 2018-01-08
@@ -1675,18 +1676,65 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& cfg, int formatVer)
else
inWnd["Perspective"](cfg.gui.mainDlg.guiPerspectiveLast);
+ //TODO: remove after migration! 2019-11-30
+ auto splitEditMerge = [](wxString& perspective, wchar_t delim, const std::function<void(wxString& item)>& editItem)
+ {
+ std::vector<wxString> v = split(perspective, delim, SplitType::ALLOW_EMPTY);
+ assert(!v.empty());
+ perspective.clear();
+
+ std::for_each(v.begin(), v.end() - 1, [&](wxString& item)
+ {
+ editItem(item);
+ perspective += item;
+ perspective += delim;
+ });
+ editItem(v.back());
+ perspective += v.back();
+ };
+
//TODO: remove after migration! 2018-07-27
if (formatVer < 10)
+ splitEditMerge(cfg.gui.mainDlg.guiPerspectiveLast, L'|', [&](wxString& paneCfg)
+ {
+ if (contains(paneCfg, L"name=TopPanel"))
+ replace(paneCfg, L";row=2;", L";row=3;");
+ });
+
+ //TODO: remove after migration! 2019-11-30
+ if (formatVer < 15)
{
- wxString newPersp;
- for (wxString& item : split(cfg.gui.mainDlg.guiPerspectiveLast, L"|", SplitType::SKIP_EMPTY))
+ //set minimal TopPanel height => search and set actual height to 0 and let MainDialog's min-size handling kick in:
+ std::optional<int> tpDir;
+ std::optional<int> tpLayer;
+ std::optional<int> tpRow;
+ splitEditMerge(cfg.gui.mainDlg.guiPerspectiveLast, L'|', [&](wxString& paneCfg)
{
- if (contains(item, L"name=SearchPanel;"))
- replace(item, L";row=2;", L";row=3;");
+ if (contains(paneCfg, L"name=TopPanel"))
+ splitEditMerge(paneCfg, L';', [&](wxString& paneAttr)
+ {
+ if (startsWith(paneAttr, L"dir="))
+ tpDir = stringTo<int>(afterFirst(paneAttr, L'=', IF_MISSING_RETURN_NONE));
+ else if (startsWith(paneAttr, L"layer="))
+ tpLayer = stringTo<int>(afterFirst(paneAttr, L'=', IF_MISSING_RETURN_NONE));
+ else if (startsWith(paneAttr, L"row="))
+ tpRow = stringTo<int>(afterFirst(paneAttr, L'=', IF_MISSING_RETURN_NONE));
+ });
+ });
+
+ if (tpDir && tpLayer && tpRow)
+ {
+ const wxString tpSize = L"dock_size(" +
+ numberTo<wxString>(*tpDir ) + L"," +
+ numberTo<wxString>(*tpLayer) + L"," +
+ numberTo<wxString>(*tpRow ) + L")=";
- newPersp += (newPersp.empty() ? L"" : L"|") + item;
+ splitEditMerge(cfg.gui.mainDlg.guiPerspectiveLast, L'|', [&](wxString& paneCfg)
+ {
+ if (startsWith(paneCfg, tpSize))
+ paneCfg = tpSize + L"0";
+ });
}
- cfg.gui.mainDlg.guiPerspectiveLast = newPersp;
}
std::vector<Zstring> tmp = splitFilterByLines(cfg.gui.defaultExclusionFilter); //default value
@@ -1761,6 +1809,13 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& cfg, int formatVer)
//TODO: remove macro migration after some time! 2016-07-18
for (ExternalApp& item : cfg.gui.externalApps)
replace(item.cmdLine, Zstr("%item_folder%"), Zstr("%folder_path%"));
+ //TODO: remove after migration! 2019-11-30
+ if (formatVer < 15)
+ for (ExternalApp& item : cfg.gui.externalApps)
+ {
+ replace(item.cmdLine, Zstr("%folder_path%"), Zstr("%parent_path%"));
+ replace(item.cmdLine, Zstr("%folder_path2%"), Zstr("%parent_path2%"));
+ }
//last update check
inGui["LastOnlineCheck" ](cfg.gui.lastUpdateCheck);
diff --git a/FreeFileSync/Source/base/config.h b/FreeFileSync/Source/base/config.h
index 89edfeb9..14ea2565 100644
--- a/FreeFileSync/Source/base/config.h
+++ b/FreeFileSync/Source/base/config.h
@@ -250,7 +250,7 @@ struct XmlGlobalSettings
{
//default external app descriptions will be translated "on the fly"!!!
//CONTRACT: first entry will be used for [Enter] or mouse double-click!
- { L"Browse directory", Zstr("xdg-open \"%folder_path%\"") },
+ { L"Browse directory", Zstr("xdg-open \"%parent_path%\"") },
{ L"Open with default application", Zstr("xdg-open \"%local_path%\"") },
//mark for extraction: _("Browse directory") Linux doesn't use the term "folder"
};
diff --git a/FreeFileSync/Source/base/db_file.cpp b/FreeFileSync/Source/base/db_file.cpp
index c7ad54d5..aba2947f 100644
--- a/FreeFileSync/Source/base/db_file.cpp
+++ b/FreeFileSync/Source/base/db_file.cpp
@@ -106,7 +106,7 @@ DbStreams loadStreams(const AbstractPath& dbPath, const IOCallback& notifyUnbuff
//TODO: remove migration code at some time! 2017-02-01
if (version != 9 &&
- version != DB_FORMAT_CONTAINER) //read file format version number
+ version != DB_FORMAT_CONTAINER)
throw FileError(replaceCpy(_("Database file %x is incompatible."), L"%x", fmtPath(AFS::getDisplayPath(dbPath))));
DbStreams output;
@@ -154,11 +154,11 @@ DbStreams loadStreams(const AbstractPath& dbPath, const IOCallback& notifyUnbuff
}
catch (UnexpectedEndOfStreamError&)
{
- throw FileError(_("Database file is corrupted:") + L"\n" + fmtPath(AFS::getDisplayPath(dbPath)), L"Unexpected end of stream.");
+ throw FileError(_("Database file is corrupted:") + L" " + fmtPath(AFS::getDisplayPath(dbPath)), L"Unexpected end of stream.");
}
catch (const std::bad_alloc& e) //still required?
{
- throw FileError(_("Database file is corrupted:") + L"\n" + fmtPath(AFS::getDisplayPath(dbPath)),
+ throw FileError(_("Database file is corrupted:") + L" " + fmtPath(AFS::getDisplayPath(dbPath)),
_("Out of memory.") + L" " + utfTo<std::wstring>(e.what()));
}
}
diff --git a/FreeFileSync/Source/base/dir_lock.cpp b/FreeFileSync/Source/base/dir_lock.cpp
index 85d2be90..f32e5832 100644
--- a/FreeFileSync/Source/base/dir_lock.cpp
+++ b/FreeFileSync/Source/base/dir_lock.cpp
@@ -182,9 +182,11 @@ LockInformation getLockInfoFromCurrentProcess() //throw FileError
LockInformation unserialize(MemoryStreamIn<ByteArray>& stream) //throw UnexpectedEndOfStreamError
{
+ //-------- file format header --------
char tmp[sizeof(LOCK_FORMAT_DESCR)] = {};
- readArray(stream, &tmp, sizeof(tmp)); //file format header
- const int lockFileVersion = readNumber<int32_t>(stream); //
+ readArray(stream, &tmp, sizeof(tmp)); //throw UnexpectedEndOfStreamError
+
+ const int lockFileVersion = readNumber<int32_t>(stream); //throw UnexpectedEndOfStreamError
if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(LOCK_FORMAT_DESCR)) ||
lockFileVersion != LOCK_FORMAT_VER)
@@ -239,10 +241,10 @@ std::string retrieveLockId(const Zstring& lockFilePath) //throw FileError
enum class ProcessStatus
{
- NOT_RUNNING,
- RUNNING,
- ITS_US,
- CANT_TELL,
+ notRunning,
+ running,
+ itsUs,
+ noIdea,
};
ProcessStatus getProcessStatus(const LockInformation& lockInfo) //throw FileError
@@ -251,15 +253,15 @@ ProcessStatus getProcessStatus(const LockInformation& lockInfo) //throw FileErro
if (lockInfo.computerName != localInfo.computerName ||
lockInfo.userId != localInfo.userId) //another user may run a session right now!
- return ProcessStatus::CANT_TELL; //lock owned by different computer in this network
+ return ProcessStatus::noIdea; //lock owned by different computer in this network
if (lockInfo.sessionId == localInfo.sessionId &&
lockInfo.processId == localInfo.processId) //obscure, but possible: deletion failed or a lock file is "stolen" and put back while the program is running
- return ProcessStatus::ITS_US;
+ return ProcessStatus::itsUs;
if (std::optional<SessionId> sessionId = getSessionId(lockInfo.processId)) //throw FileError
- return *sessionId == lockInfo.sessionId ? ProcessStatus::RUNNING : ProcessStatus::NOT_RUNNING;
- return ProcessStatus::NOT_RUNNING;
+ return *sessionId == lockInfo.sessionId ? ProcessStatus::running : ProcessStatus::notRunning;
+ return ProcessStatus::notRunning;
}
@@ -289,17 +291,17 @@ void waitOnDirLock(const Zstring& lockFilePath, const DirLockCallback& notifySta
{
const LockInformation& lockInfo = retrieveLockInfo(lockFilePath); //throw FileError
- infoMsg += L" | " + _("Lock owner:") + L' ' + utfTo<std::wstring>(lockInfo.userId);
+ infoMsg += L" | " + _("User name:") + L' ' + utfTo<std::wstring>(lockInfo.userId);
originalLockId = lockInfo.lockId;
switch (getProcessStatus(lockInfo)) //throw FileError
{
- case ProcessStatus::ITS_US: //since we've already passed LockAdmin, the lock file seems abandoned ("stolen"?) although it's from this process
- case ProcessStatus::NOT_RUNNING:
+ case ProcessStatus::itsUs: //since we've already passed LockAdmin, the lock file seems abandoned ("stolen"?) although it's from this process
+ case ProcessStatus::notRunning:
lockOwnderDead = true;
break;
- case ProcessStatus::RUNNING:
- case ProcessStatus::CANT_TELL:
+ case ProcessStatus::running:
+ case ProcessStatus::noIdea:
break;
}
}
diff --git a/FreeFileSync/Source/base/icon_buffer.h b/FreeFileSync/Source/base/icon_buffer.h
index c088a56a..d6dd504f 100644
--- a/FreeFileSync/Source/base/icon_buffer.h
+++ b/FreeFileSync/Source/base/icon_buffer.h
@@ -32,8 +32,8 @@ public:
static int getSize(IconSize sz); //expected and *maximum* icon size in pixel
int getSize() const { return getSize(iconSizeType_); } //
- void setWorkload (const std::vector<AbstractPath>& load); //(re-)set new workload of icons to be retrieved;
- bool readyForRetrieval(const AbstractPath& filePath);
+ void setWorkload (const std::vector<AbstractPath>& load); //(re-)set new workload of icons to be retrieved;
+ bool readyForRetrieval(const AbstractPath& filePath);
std::optional<wxBitmap> retrieveFileIcon (const AbstractPath& filePath); //... and mark as hot
wxBitmap getIconByExtension(const Zstring& filePath); //...and add to buffer
//retrieveFileIcon() + getIconByExtension() are safe to call from within WM_PAINT handler! no COM calls (...on calling thread)
diff --git a/FreeFileSync/Source/base/localization.cpp b/FreeFileSync/Source/base/localization.cpp
index d6491c86..ef1ee778 100644
--- a/FreeFileSync/Source/base/localization.cpp
+++ b/FreeFileSync/Source/base/localization.cpp
@@ -100,6 +100,36 @@ FFSTranslation::FFSTranslation(const std::string& lngStream) //throw lng::Parsin
std::vector<TranslationInfo> loadTranslations()
{
+ const Zstring& zipPath = getResourceDirPf() + Zstr("Languages.zip");
+ std::vector<std::pair<Zstring /*file name*/, std::string /*byte stream*/>> streams;
+
+ try //to load from ZIP first:
+ {
+ const std::string rawStream = loadBinContainer<std::string>(zipPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership
+ wxZipInputStream zipStream(memStream, wxConvUTF8);
+
+ while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!
+ if (std::string stream(entry->GetSize(), '\0'); !stream.empty() && zipStream.ReadAll(&stream[0], stream.size()))
+ streams.emplace_back(utfTo<Zstring>(entry->GetName()), std::move(stream));
+ else
+ assert(false);
+ }
+ catch (FileError&) //fall back to folder
+ {
+ traverseFolder(beforeLast(zipPath, Zstr(".zip"), IF_MISSING_RETURN_NONE), [&](const FileInfo& fi)
+ {
+ if (endsWith(fi.fullPath, Zstr(".lng")))
+ try
+ {
+ std::string stream = loadBinContainer<std::string>(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ streams.emplace_back(fi.itemName, std::move(stream));
+ }
+ catch (FileError&) { assert(false); }
+ }, nullptr, nullptr, [](const std::wstring& errorMsg) { assert(false); }); //errors are not really critical in this context
+ }
+ //--------------------------------------------------------------------
+
std::vector<TranslationInfo> locMapping;
{
//default entry:
@@ -113,50 +143,36 @@ std::vector<TranslationInfo> loadTranslations()
locMapping.push_back(newEntry);
}
- try
- {
- const std::string rawStream = loadBinContainer<std::string>(fff::getResourceDirPf() + Zstr("Languages.zip"), nullptr /*notifyUnbufferedIO*/); //throw FileError
- wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership
- wxZipInputStream zipStream(memStream, wxConvUTF8);
-
- while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!)
+ for (/*const*/ auto& [fileName, stream] : streams)
+ try
{
- std::string stream(entry->GetSize(), '\0');
- if (!stream.empty() && zipStream.ReadAll(&stream[0], stream.size()))
- try
- {
- const lng::TransHeader lngHeader = lng::parseHeader(stream); //throw ParsingError
- assert(!lngHeader.languageName .empty());
- assert(!lngHeader.translatorName.empty());
- assert(!lngHeader.localeName .empty());
- assert(!lngHeader.flagFile .empty());
- /*
- Some ISO codes are used by multiple wxLanguage IDs which can lead to incorrect mapping by wxLocale::FindLanguageInfo()!!!
- => Identify by description, e.g. "Chinese (Traditional)". The following IDs are affected:
- wxLANGUAGE_CHINESE_TRADITIONAL
- wxLANGUAGE_ENGLISH_UK
- wxLANGUAGE_SPANISH //non-unique, but still mapped correctly (or is it incidentally???)
- wxLANGUAGE_SERBIAN //
- */
- if (const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(utfTo<wxString>(lngHeader.localeName)))
- {
- TranslationInfo newEntry;
- newEntry.languageID = static_cast<wxLanguage>(locInfo->Language);
- newEntry.languageName = utfTo<std::wstring>(lngHeader.languageName);
- newEntry.translatorName = utfTo<std::wstring>(lngHeader.translatorName);
- newEntry.languageFlag = utfTo<std::wstring>(lngHeader.flagFile);
- newEntry.lngFileName = utfTo<Zstring>(entry->GetName());
- newEntry.lngStream = std::move(stream);
- locMapping.push_back(newEntry);
- }
- else assert(false);
- }
- catch (lng::ParsingError&) { assert(false); } //better not show an error message here; scenario: batch jobs
- else
- assert(false);
+ const lng::TransHeader lngHeader = lng::parseHeader(stream); //throw ParsingError
+ assert(!lngHeader.languageName .empty());
+ assert(!lngHeader.translatorName.empty());
+ assert(!lngHeader.localeName .empty());
+ assert(!lngHeader.flagFile .empty());
+ /*
+ Some ISO codes are used by multiple wxLanguage IDs which can lead to incorrect mapping by wxLocale::FindLanguageInfo()!!!
+ => Identify by description, e.g. "Chinese (Traditional)". The following IDs are affected:
+ wxLANGUAGE_CHINESE_TRADITIONAL
+ wxLANGUAGE_ENGLISH_UK
+ wxLANGUAGE_SPANISH //non-unique, but still mapped correctly (or is it incidentally???)
+ wxLANGUAGE_SERBIAN //
+ */
+ if (const wxLanguageInfo* locInfo = wxLocale::FindLanguageInfo(utfTo<wxString>(lngHeader.localeName)))
+ {
+ TranslationInfo newEntry;
+ newEntry.languageID = static_cast<wxLanguage>(locInfo->Language);
+ newEntry.languageName = utfTo<std::wstring>(lngHeader.languageName);
+ newEntry.translatorName = utfTo<std::wstring>(lngHeader.translatorName);
+ newEntry.languageFlag = utfTo<std::wstring>(lngHeader.flagFile);
+ newEntry.lngFileName = fileName;
+ newEntry.lngStream = std::move(stream);
+ locMapping.push_back(newEntry);
+ }
+ else assert(false);
}
- }
- catch (FileError&) { assert(false); }
+ catch (lng::ParsingError&) { assert(false); } //better not show an error message here; scenario: batch jobs
std::sort(locMapping.begin(), locMapping.end(), [](const TranslationInfo& lhs, const TranslationInfo& rhs)
{
@@ -337,11 +353,11 @@ public:
writeNumber<uint32_t>(moBuf_, 0); //format version
writeNumber<uint32_t>(moBuf_, transMapping.size()); //string count
writeNumber<uint32_t>(moBuf_, headerSize); //string references offset: original
- writeNumber<uint32_t>(moBuf_, headerSize + 8 * transMapping.size()); //string references offset: translation
+ writeNumber<uint32_t>(moBuf_, headerSize + (2 * sizeof(uint32_t)) * transMapping.size()); //string references offset: translation
writeNumber<uint32_t>(moBuf_, 0); //size of hashing table
writeNumber<uint32_t>(moBuf_, 0); //offset of hashing table
- const int stringsOffset = headerSize + 2 * 8 * transMapping.size();
+ const int stringsOffset = headerSize + 2 * (2 * sizeof(uint32_t)) * transMapping.size();
std::string stringsList;
for (const auto& [original, translation] : transMapping)
@@ -351,9 +367,9 @@ public:
stringsList.append(original.c_str(), original.size() + 1); //include 0-termination
}
- for (const auto& item : transMapping)
+ for (const auto& [original, trans] : transMapping)
{
- const auto& translation = utfTo<std::string>(item.second);
+ const auto& translation = utfTo<std::string>(trans);
writeNumber<uint32_t>(moBuf_, translation.size()); //string length
writeNumber<uint32_t>(moBuf_, stringsOffset + stringsList.size()); //string offset
stringsList.append(translation.c_str(), translation.size() + 1); //include 0-termination
@@ -402,44 +418,41 @@ public:
void init(wxLanguage lng)
{
- const wxLanguageInfo* sysLngInfo = wxLocale::GetLanguageInfo(sysLng_);
- const wxLanguageInfo* selLngInfo = wxLocale::GetLanguageInfo(lng);
-
- const bool sysLangIsRTL = sysLngInfo ? sysLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
- const bool selectedLangIsRTL = selLngInfo ? selLngInfo->LayoutDirection == wxLayout_RightToLeft : false;
+ lng_ = lng;
- const wxLanguage initLng = sysLangIsRTL == selectedLangIsRTL ?
- sysLng_ : //use sys-lang to preserve sub-language specific rules (e.g. German Swiss number punctuation)
- lng; //have to use the supplied language to enable RTL layout different than user settings
+ if (const wxLanguageInfo* selLngInfo = wxLocale::GetLanguageInfo(lng))
+ layoutDir_ = selLngInfo->LayoutDirection;
+ else
+ layoutDir_ = wxLayout_LeftToRight;
- if (!locale_ || localeLng_ != initLng)
+ //use sys-lang to preserve sub-language specific rules (e.g. German Swiss number punctuation)
+ //beneficial even for Arabic locale: support user-specific date settings (instead of Hijri calendar year 1441 = Gregorian 2019)
+ if (!locale_)
{
//wxWidgets shows a modal dialog on error during wxLocale::Init() -> at least we can shut it up!
wxLog* oldLogTarget = wxLog::SetActiveTarget(new wxLogStderr); //transfer and receive ownership!
ZEN_ON_SCOPE_EXIT(delete wxLog::SetActiveTarget(oldLogTarget));
- locale_.reset(); //avoid global locale lifetime overlap! wxWidgets cannot handle this and will crash!
- locale_ = std::make_unique<wxLocale>(initLng, wxLOCALE_DONT_LOAD_DEFAULT /*we're not using wxwin.mo*/);
+ //locale_.reset(); //avoid global locale lifetime overlap! wxWidgets cannot handle this and will crash!
+ locale_ = std::make_unique<wxLocale>(sysLng_, wxLOCALE_DONT_LOAD_DEFAULT /*we're not using wxwin.mo*/);
assert(locale_->IsOk());
- localeLng_ = initLng;
}
-
- lng_ = lng;
}
- void tearDown() { locale_.reset(); lng_ = localeLng_ = wxLANGUAGE_UNKNOWN; }
+ void tearDown() { locale_.reset(); lng_ = wxLANGUAGE_UNKNOWN; layoutDir_ = wxLayout_Default; }
- wxLanguage getLanguage () const { return lng_; }
wxLanguage getSysLanguage() const { return sysLng_; }
+ wxLanguage getLanguage () const { return lng_; }
+ wxLayoutDirection getLayoutDirection() const { return layoutDir_; }
private:
wxWidgetsLocale() {}
~wxWidgetsLocale() { assert(!locale_); }
- std::unique_ptr<wxLocale> locale_;
- wxLanguage localeLng_ = wxLANGUAGE_UNKNOWN;
- wxLanguage lng_ = wxLANGUAGE_UNKNOWN;
const wxLanguage sysLng_ = static_cast<wxLanguage>(wxLocale::GetSystemLanguage());
+ wxLanguage lng_ = wxLANGUAGE_UNKNOWN;
+ wxLayoutDirection layoutDir_ = wxLayout_Default;
+ std::unique_ptr<wxLocale> locale_;
};
}
@@ -517,14 +530,20 @@ void fff::setLanguage(wxLanguage lng) //throw FileError
}
+wxLanguage fff::getSystemLanguage()
+{
+ static const wxLanguage sysLng = mapLanguageDialect(wxWidgetsLocale::getInstance().getSysLanguage());
+ return sysLng;
+}
+
+
wxLanguage fff::getLanguage()
{
return wxWidgetsLocale::getInstance().getLanguage();
}
-wxLanguage fff::getSystemLanguage()
+wxLayoutDirection fff::getLayoutDirection()
{
- static const wxLanguage sysLng = mapLanguageDialect(wxWidgetsLocale::getInstance().getSysLanguage());
- return sysLng;
+ return wxWidgetsLocale::getInstance().getLayoutDirection();
}
diff --git a/FreeFileSync/Source/base/localization.h b/FreeFileSync/Source/base/localization.h
index 51fea760..e635ac1e 100644
--- a/FreeFileSync/Source/base/localization.h
+++ b/FreeFileSync/Source/base/localization.h
@@ -9,6 +9,7 @@
#include <vector>
#include <zen/file_error.h>
+#include <wx/intl.h>
#include <wx/language.h>
@@ -25,11 +26,11 @@ struct TranslationInfo
};
const std::vector<TranslationInfo>& getExistingTranslations();
-
-void setLanguage(wxLanguage lng); //throw FileError
+wxLanguage getSystemLanguage();
wxLanguage getLanguage();
+wxLayoutDirection getLayoutDirection();
-wxLanguage getSystemLanguage();
+void setLanguage(wxLanguage lng); //throw FileError
void releaseWxLocale(); //wxLocale crashes miserably on wxGTK when destructor runs during global cleanup => call in wxApp::OnExit
//"You should delete all wxWidgets object that you created by the time OnExit finishes. In particular, do not destroy them from application class' destructor!"
diff --git a/FreeFileSync/Source/base/log_file.cpp b/FreeFileSync/Source/base/log_file.cpp
index 76a9b7a1..39e8f0a7 100644
--- a/FreeFileSync/Source/base/log_file.cpp
+++ b/FreeFileSync/Source/base/log_file.cpp
@@ -117,9 +117,6 @@ AbstractPath saveNewLogFile(const ProcessSummary& summary, //throw FileError
const AbstractPath& logFolderPath,
const std::function<void(const std::wstring& msg)>& notifyStatus /*throw X*/)
{
- //create logfile folder if required
- AFS::createFolderIfMissingRecursion(logFolderPath); //throw FileError
-
//const std::string colon = "\xcb\xb8"; //="modifier letter raised colon" => regular colon is forbidden in file names on Windows and OS X
//=> too many issues, most notably cmd.exe is not Unicode-aware: https://freefilesync.org/forum/viewtopic.php?t=1679
@@ -162,6 +159,17 @@ AbstractPath saveNewLogFile(const ProcessSummary& summary, //throw FileError
const AbstractPath logFilePath = AFS::appendRelPath(logFolderPath, logFileName);
+ //-----------------------------------------------------------------------
+ try //create logfile folder if required
+ {
+ AFS::createFolderIfMissingRecursion(logFolderPath); //throw FileError
+ }
+ catch (const FileError& e) //add context info regarding log file!
+ {
+ throw FileError(replaceCpy(_("Cannot write file %x."), L"%x", fmtPath(AFS::getDisplayPath(logFilePath))), e.toString());
+ }
+ //-----------------------------------------------------------------------
+
auto notifyUnbufferedIO = [notifyStatus,
bytesWritten_ = int64_t(0),
msg_ = replaceCpy(_("Saving file %x..."), L"%x", fmtPath(AFS::getDisplayPath(logFilePath)))]
diff --git a/FreeFileSync/Source/base/path_filter.h b/FreeFileSync/Source/base/path_filter.h
index 549bf0cc..f1087722 100644
--- a/FreeFileSync/Source/base/path_filter.h
+++ b/FreeFileSync/Source/base/path_filter.h
@@ -14,22 +14,18 @@
namespace fff
{
-//------------------------------------------------------------------
-/*
-Semantics of PathFilter:
-1. using it creates a NEW folder hierarchy! -> must be considered by <Two way> variant!
-2. it applies equally to both sides => it always matches either both sides or none! => can be used while traversing a single folder!
-
- class hierarchy:
-
- PathFilter (interface)
- /|\
- _________|_____________
- | | |
-NullFilter NameFilter CombinedFilter
-*/
+/* Semantics of PathFilter:
+ 1. using it creates a NEW folder hierarchy! -> must be considered by <Two way> variant!
+ 2. it applies equally to both sides => it always matches either both sides or none! => can be used while traversing a single folder!
+
+ PathFilter (interface)
+ /|\
+ ____________|_____________
+ | | |
+ NullFilter NameFilter CombinedFilter
+ */
class PathFilter;
-using FilterRef = zen::SharedRef<const PathFilter>; //Thread-safety: internally synchronized!
+using FilterRef = zen::SharedRef<const PathFilter>;
const Zchar FILTER_ITEM_SEPARATOR = Zstr('|');
diff --git a/FreeFileSync/Source/base/structures.cpp b/FreeFileSync/Source/base/structures.cpp
index ba8b3a83..18448ece 100644
--- a/FreeFileSync/Source/base/structures.cpp
+++ b/FreeFileSync/Source/base/structures.cpp
@@ -103,10 +103,10 @@ std::wstring fff::getVariantName(DirectionConfig::Variant var)
//const wchar_t arrowLeft [] = L"\u25C4\u2013 "; //black triangle pointer
//const wchar_t arrowRight[] = L" \u2013\u25BA"; //
const wchar_t arrowLeft [] = L"\uFF1C\u2013 "; //fullwidth less-than + en dash
- const wchar_t arrowRight[] = L" \u2013\uFF1E"; //en dash + fullwidth greater-than
- const wchar_t angleRight[] = L" \uFF1E";
+ const wchar_t arrowRight[] = L" \u2013\uFF1E"; //en dash + fullwidth greater-than
+ const wchar_t angleRight[] = L" \uFF1E";
//=> drawback: - not drawn correctly before Vista
- // - RTL: the full width less-than is not mirrored automatically (=> Windows Unicode bug!?)
+ // - RTL: the full width less-than is not mirrored automatically (=> Windows Unicode bug!)
#endif
return getVariantNameImpl(var, arrowLeft, arrowRight, angleRight);
}
diff --git a/FreeFileSync/Source/base/synchronization.cpp b/FreeFileSync/Source/base/synchronization.cpp
index fdb9e23e..3533573b 100644
--- a/FreeFileSync/Source/base/synchronization.cpp
+++ b/FreeFileSync/Source/base/synchronization.cpp
@@ -108,7 +108,7 @@ void SyncStatistics::processFile(const FilePair& file)
break;
case SO_MOVE_LEFT_FROM: //ignore; already counted
- case SO_MOVE_RIGHT_FROM: //
+ case SO_MOVE_RIGHT_FROM: //=> harmonize with FileView::applyFilterByAction()
break;
case SO_OVERWRITE_LEFT:
diff --git a/FreeFileSync/Source/ui/abstract_folder_picker.cpp b/FreeFileSync/Source/ui/abstract_folder_picker.cpp
index e9cfc6e6..4c96e6f7 100644
--- a/FreeFileSync/Source/ui/abstract_folder_picker.cpp
+++ b/FreeFileSync/Source/ui/abstract_folder_picker.cpp
@@ -88,7 +88,7 @@ AbstractFolderPickerDlg::AbstractFolderPickerDlg(wxWindow* parent, AbstractPath&
setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel));
m_staticTextStatus->SetLabel(L"");
- m_treeCtrlFileSystem->SetMinSize(wxSize(fastFromDIP(350), fastFromDIP(400)));
+ m_treeCtrlFileSystem->SetMinSize({fastFromDIP(350), fastFromDIP(400)});
const int iconSize = IconBuffer::getSize(IconBuffer::SIZE_SMALL);
auto imgList = std::make_unique<wxImageList>(iconSize, iconSize);
diff --git a/FreeFileSync/Source/ui/cfg_grid.cpp b/FreeFileSync/Source/ui/cfg_grid.cpp
index 9e8eb69a..b15a3302 100644
--- a/FreeFileSync/Source/ui/cfg_grid.cpp
+++ b/FreeFileSync/Source/ui/cfg_grid.cpp
@@ -333,6 +333,14 @@ private:
return std::wstring();
}
+ void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
+ {
+ if (selected)
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
+ else
+ clearArea(dc, rect, wxSystemSettings::GetColour(enabled ? wxSYS_COLOUR_WINDOW : wxSYS_COLOUR_BTNFACE));
+ }
+
enum class HoverAreaLog
{
LINK,
@@ -346,12 +354,7 @@ private:
if (selected)
textColor.Set(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
else
- {
- //if (enabled)
textColor.Set(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
- //else
- // textColor.Set(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
- }
if (const ConfigView::Details* item = cfgView_.getItem(row))
switch (static_cast<ColumnTypeCfg>(colType))
@@ -369,7 +372,7 @@ private:
rectTmp2.x += rectTmp2.width;
rectTmp2.width = rectTmp.width - rectTmp2.width;
- dc.GradientFillLinear(rectTmp2, item->cfgItem.backColor, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW), wxEAST);
+ dc.GradientFillLinear(rectTmp2, item->cfgItem.backColor, wxSystemSettings::GetColour(enabled ? wxSYS_COLOUR_WINDOW : wxSYS_COLOUR_BTNFACE), wxEAST);
}
else //always show a glimpse of the background color
{
@@ -467,14 +470,6 @@ private:
return 0;
}
- void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
- {
- if (selected)
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
- else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
- }
-
HoverArea getRowMouseHover(size_t row, ColumnType colType, int cellRelativePosX, int cellWidth) override
{
if (const ConfigView::Details* item = cfgView_.getItem(row))
@@ -494,7 +489,7 @@ private:
return HoverArea::NONE;
}
- void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override
+ void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted) override
{
const auto colTypeCfg = static_cast<ColumnTypeCfg>(colType);
@@ -512,24 +507,27 @@ private:
case ColumnTypeCfg::lastSync:
rectRemain.x += getColumnGapLeft();
rectRemain.width -= getColumnGapLeft();
- drawColumnLabelText(dc, rectRemain, getColumnLabel(colType));
+ drawColumnLabelText(dc, rectRemain, getColumnLabel(colType), enabled);
if (sortMarker.IsOk())
drawBitmapRtlNoMirror(dc, sortMarker, rectInner, wxALIGN_CENTER_HORIZONTAL);
break;
case ColumnTypeCfg::lastLog:
- drawBitmapRtlNoMirror(dc, getResourceImage(L"log_file_sicon"), rectInner, wxALIGN_CENTER);
+ {
+ const wxBitmap logIcon = getResourceImage(L"log_file_sicon");
+ drawBitmapRtlNoMirror(dc, enabled ? logIcon : logIcon.ConvertToDisabled(), rectInner, wxALIGN_CENTER);
if (sortMarker.IsOk())
{
- const int gapLeft = (rectInner.width + getResourceImage(L"log_file_sicon").GetWidth()) / 2;
+ const int gapLeft = (rectInner.width + logIcon.GetWidth()) / 2;
rectRemain.x += gapLeft;
rectRemain.width -= gapLeft;
drawBitmapRtlNoMirror(dc, sortMarker, rectRemain, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
}
- break;
+ }
+ break;
}
}
diff --git a/FreeFileSync/Source/ui/command_box.cpp b/FreeFileSync/Source/ui/command_box.cpp
index b862d365..7dc2607d 100644
--- a/FreeFileSync/Source/ui/command_box.cpp
+++ b/FreeFileSync/Source/ui/command_box.cpp
@@ -49,7 +49,7 @@ CommandBox::CommandBox(wxWindow* parent,
defaultCommands_(getDefaultCommands())
{
//####################################
- /*#*/ SetMinSize(wxSize(fastFromDIP(150), -1)); //# workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
+ /*#*/ SetMinSize({fastFromDIP(150), -1}); //# workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
//####################################
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (CommandBox::OnKeyEvent ), nullptr, this);
diff --git a/FreeFileSync/Source/ui/file_grid.cpp b/FreeFileSync/Source/ui/file_grid.cpp
index e369527e..bc7b7037 100644
--- a/FreeFileSync/Source/ui/file_grid.cpp
+++ b/FreeFileSync/Source/ui/file_grid.cpp
@@ -277,31 +277,25 @@ private:
protected:
void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
{
- if (enabled)
+ if (enabled && !selected)
{
- if (selected)
- dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
- //ignore focus
+ //alternate background color to improve readability (while lacking cell borders)
+ if (getRowDisplayType(row) == DisplayType::NORMAL)
+ fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0);
else
- {
- //alternate background color to improve readability (while lacking cell borders)
- if (getRowDisplayType(row) == DisplayType::NORMAL)
- fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0);
- else
- clearArea(dc, rect, getBackGroundColor(row));
+ clearArea(dc, rect, getBackGroundColor(row));
- //draw horizontal border if required
- DisplayType dispTp = getRowDisplayType(row);
- if (dispTp != DisplayType::NORMAL &&
- dispTp == getRowDisplayType(row + 1))
- {
- wxDCPenChanger dummy2(dc, getColorGridLine());
- dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight() + wxPoint(1, 0));
- }
+ //draw horizontal border if required
+ DisplayType dispTp = getRowDisplayType(row);
+ if (dispTp != DisplayType::NORMAL &&
+ dispTp == getRowDisplayType(row + 1))
+ {
+ wxDCPenChanger dummy2(dc, getColorGridLine());
+ dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight() + wxPoint(1, 0));
}
}
else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
+ GridData::renderRowBackgound(dc, rect, row, enabled, enabled && selected);
}
wxColor getBackGroundColor(size_t row) const
@@ -668,14 +662,14 @@ private:
return std::wstring();
}
- void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override
+ void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted) override
{
const wxRect rectInner = drawColumnLabelBackground(dc, rect, highlighted);
wxRect rectRemain = rectInner;
rectRemain.x += getColumnGapLeft();
rectRemain.width -= getColumnGapLeft();
- drawColumnLabelText(dc, rectRemain, getColumnLabel(colType));
+ drawColumnLabelText(dc, rectRemain, getColumnLabel(colType), enabled);
//draw sort marker
if (const FileView* view = getGridDataView())
@@ -822,7 +816,7 @@ private:
{
wxRect rectTmp = rect;
rectTmp.width /= 20;
- dc.GradientFillLinear(rectTmp, getColorSelectionGradientFrom(), GridDataRim<LEFT_SIDE>::getBackGroundColor(row), wxEAST);
+ dc.GradientFillLinear(rectTmp, getColorSelectionGradientFrom(), getBackGroundColor(row), wxEAST);
}
}
}
@@ -924,14 +918,6 @@ public:
void highlightSyncAction(bool value) { highlightSyncAction_ = value; }
private:
- enum class HoverAreaCenter //each cell can be divided into four blocks concerning mouse selections
- {
- CHECK_BOX,
- DIR_LEFT,
- DIR_NONE,
- DIR_RIGHT
- };
-
std::wstring getValue(size_t row, ColumnType colType) const override
{
if (const FileSystemObject* fsObj = getRawData(row))
@@ -949,27 +935,30 @@ private:
void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
{
- if (enabled)
+ if (enabled && !selected)
{
- if (selected)
- dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
- else
+ if (const FileSystemObject* fsObj = getRawData(row))
{
- if (const FileSystemObject* fsObj = getRawData(row))
- {
- if (fsObj->isActive())
- fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0);
- else
- clearArea(dc, rect, getColorNotActive());
- }
+ if (fsObj->isActive())
+ fillBackgroundDefaultColorAlternating(dc, rect, row % 2 == 0);
else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ clearArea(dc, rect, getColorNotActive());
}
+ else
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
}
else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
+ GridData::renderRowBackgound(dc, rect, row, enabled, enabled && selected);
}
+ enum class HoverAreaCenter //each cell can be divided into four blocks concerning mouse selections
+ {
+ CHECK_BOX,
+ DIR_LEFT,
+ DIR_NONE,
+ DIR_RIGHT
+ };
+
void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover) override
{
auto drawHighlightBackground = [&](const FileSystemObject& fsObj, const wxColor& col)
@@ -1094,7 +1083,7 @@ private:
std::wstring getToolTip(ColumnType colType) const override { return getColumnLabel(colType); }
- void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override
+ void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted) override
{
const auto colTypeCenter = static_cast<ColumnTypeCenter>(colType);
@@ -1120,7 +1109,7 @@ private:
}
if (colIcon.IsOk())
- drawBitmapRtlNoMirror(dc, colIcon, rectInner, wxALIGN_CENTER);
+ drawBitmapRtlNoMirror(dc, enabled ? colIcon : colIcon.ConvertToDisabled(), rectInner, wxALIGN_CENTER);
//draw sort marker
if (const FileView* view = getGridDataView())
diff --git a/FreeFileSync/Source/ui/file_view.cpp b/FreeFileSync/Source/ui/file_view.cpp
index 0342d800..4b878ad2 100644
--- a/FreeFileSync/Source/ui/file_view.cpp
+++ b/FreeFileSync/Source/ui/file_view.cpp
@@ -15,14 +15,6 @@ using namespace fff;
namespace
{
-struct CompileTimeReminder : public FSObjectVisitor
-{
- void visit(const FilePair& file ) override {}
- void visit(const SymlinkPair& symlink) override {}
- void visit(const FolderPair& folder ) override {}
-} checkDymanicCasts; //just a compile-time reminder to manually check dynamic casts in this file if ever needed
-
-
template <class ViewStats>
void addNumbers(const FileSystemObject& fsObj, ViewStats& stats)
{
@@ -178,6 +170,9 @@ FileView::ActionViewStats FileView::applyFilterByAction(bool showExcluded, //map
{
ActionViewStats stats;
+ int moveLeft = 0;
+ int moveRight = 0;
+
updateView([&](const FileSystemObject& fsObj)
{
auto categorize = [&](bool showCategory, int& categoryCount)
@@ -207,15 +202,17 @@ FileView::ActionViewStats FileView::applyFilterByAction(bool showExcluded, //map
case SO_DELETE_RIGHT:
return categorize(showDeleteRight, stats.deleteRight);
case SO_OVERWRITE_LEFT:
- case SO_COPY_METADATA_TO_LEFT: //no extra button on screen
- case SO_MOVE_LEFT_TO:
- case SO_MOVE_LEFT_FROM:
+ case SO_COPY_METADATA_TO_LEFT: //no extra filter button
return categorize(showUpdateLeft, stats.updateLeft);
+ case SO_MOVE_LEFT_FROM:
+ case SO_MOVE_LEFT_TO:
+ return categorize(showUpdateLeft, moveLeft);
case SO_OVERWRITE_RIGHT:
- case SO_COPY_METADATA_TO_RIGHT: //no extra button on screen
+ case SO_COPY_METADATA_TO_RIGHT: //no extra filter button
+ return categorize(showUpdateRight, stats.updateRight);
case SO_MOVE_RIGHT_FROM:
case SO_MOVE_RIGHT_TO:
- return categorize(showUpdateRight, stats.updateRight);
+ return categorize(showUpdateRight, moveRight);
case SO_DO_NOTHING:
return categorize(showDoNothing, stats.updateNone);
case SO_EQUAL:
@@ -227,6 +224,10 @@ FileView::ActionViewStats FileView::applyFilterByAction(bool showExcluded, //map
return true;
});
+ assert(moveLeft % 2 == 0 && moveRight % 2 == 0);
+ stats.updateLeft += moveLeft / 2; //count move operations as single update
+ stats.updateRight += moveRight / 2; //=> harmonize with SyncStatistics::processFile()
+
return stats;
}
@@ -274,8 +275,8 @@ private:
CmpNaturalSort: 850 ms
CmpLocalPath: 233 ms
CmpAsciiNoCase: 189 ms
- No sorting: 30 ms
- */
+ No sorting: 30 ms
+ */
template <class ItemPair>
static std::vector<ItemPair*> getItemsSorted(std::list<ItemPair>& itemList)
{
@@ -329,6 +330,14 @@ void FileView::setData(FolderComparison& folderCmp)
//------------------------------------ SORTING -----------------------------------------
namespace
{
+struct CompileTimeReminder : public FSObjectVisitor
+{
+ void visit(const FilePair& file ) override {}
+ void visit(const SymlinkPair& symlink) override {}
+ void visit(const FolderPair& folder ) override {}
+} checkDymanicCasts; //just a compile-time reminder to manually check dynamic casts in this file if ever needed
+
+
inline
bool isDirectoryPair(const FileSystemObject& fsObj)
{
@@ -537,12 +546,12 @@ struct FileView::LessRelativeFolder
//presort by folder pair
if (a.folderIndex != b.folderIndex)
- {
- if constexpr (ascending)
- return a.folderIndex < b.folderIndex;
- else
- return a.folderIndex > b.folderIndex;
- }
+ {
+ if constexpr (ascending)
+ return a.folderIndex < b.folderIndex;
+ else
+ return a.folderIndex > b.folderIndex;
+ }
return lessRelativeFolder<ascending>(*fsObjA, *fsObjB);
}
diff --git a/FreeFileSync/Source/ui/folder_history_box.cpp b/FreeFileSync/Source/ui/folder_history_box.cpp
index 70eaa9dc..8109757a 100644
--- a/FreeFileSync/Source/ui/folder_history_box.cpp
+++ b/FreeFileSync/Source/ui/folder_history_box.cpp
@@ -28,7 +28,7 @@ FolderHistoryBox::FolderHistoryBox(wxWindow* parent,
wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name)
{
//#####################################
- /*##*/ SetMinSize(wxSize(fastFromDIP(150), -1)); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
+ /*##*/ SetMinSize({fastFromDIP(150), -1}); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
//#####################################
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(FolderHistoryBox::OnKeyEvent), nullptr, this);
diff --git a/FreeFileSync/Source/ui/folder_pair.h b/FreeFileSync/Source/ui/folder_pair.h
index cb5794b6..7a90521c 100644
--- a/FreeFileSync/Source/ui/folder_pair.h
+++ b/FreeFileSync/Source/ui/folder_pair.h
@@ -38,7 +38,7 @@ public:
std::optional<CompConfig> getCompConfig () const { return localCmpCfg_; }
std::optional<SyncConfig> getSyncConfig () const { return localSyncCfg_; }
- FilterConfig getFilterConfig() const { return localFilter_; }
+ FilterConfig getFilterConfig() const { return localFilter_; }
FolderPairPanelBasic(GuiPanel& basicPanel) : //takes reference on basic panel to be enhanced
@@ -57,40 +57,36 @@ private:
{
using namespace zen;
- const wxImage imgCmp = shrinkImage(getResourceImage(L"cfg_compare").ConvertToImage(), fastFromDIP(20));
- const wxImage imgSync = shrinkImage(getResourceImage(L"cfg_sync" ).ConvertToImage(), fastFromDIP(20));
- const wxImage imgFilter = shrinkImage(getResourceImage(L"cfg_filter" ).ConvertToImage(), fastFromDIP(20));
-
if (localCmpCfg_)
{
- setImage(*basicPanel_.m_bpButtonLocalCompCfg, imgCmp);
+ setImage(*basicPanel_.m_bpButtonLocalCompCfg, imgCmp_);
basicPanel_.m_bpButtonLocalCompCfg->SetToolTip(_("Local comparison settings") + L" (" + getVariantName(localCmpCfg_->compareVar) + L")");
}
else
{
- setImage(*basicPanel_.m_bpButtonLocalCompCfg, greyScale(imgCmp));
+ setImage(*basicPanel_.m_bpButtonLocalCompCfg, greyScale(imgCmp_));
basicPanel_.m_bpButtonLocalCompCfg->SetToolTip(_("Local comparison settings"));
}
if (localSyncCfg_)
{
- setImage(*basicPanel_.m_bpButtonLocalSyncCfg, imgSync);
+ setImage(*basicPanel_.m_bpButtonLocalSyncCfg, imgSync_);
basicPanel_.m_bpButtonLocalSyncCfg->SetToolTip(_("Local synchronization settings") + L" (" + getVariantName(localSyncCfg_->directionCfg.var) + L")");
}
else
{
- setImage(*basicPanel_.m_bpButtonLocalSyncCfg, greyScale(imgSync));
+ setImage(*basicPanel_.m_bpButtonLocalSyncCfg, greyScale(imgSync_));
basicPanel_.m_bpButtonLocalSyncCfg->SetToolTip(_("Local synchronization settings"));
}
if (!isNullFilter(localFilter_))
{
- setImage(*basicPanel_.m_bpButtonLocalFilter, imgFilter);
+ setImage(*basicPanel_.m_bpButtonLocalFilter, imgFilter_);
basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Local filter") + L" (" + _("Active") + L")");
}
else
{
- setImage(*basicPanel_.m_bpButtonLocalFilter, greyScale(imgFilter));
+ setImage(*basicPanel_.m_bpButtonLocalFilter, greyScale(imgFilter_));
basicPanel_.m_bpButtonLocalFilter->SetToolTip(_("Local filter") + L" (" + _("None") + L")");
}
}
@@ -167,9 +163,12 @@ private:
//alternate configuration attached to it
std::optional<CompConfig> localCmpCfg_;
std::optional<SyncConfig> localSyncCfg_;
- FilterConfig localFilter_;
+ FilterConfig localFilter_;
+
+ const wxImage imgCmp_ = zen::shrinkImage(zen::getResourceImage(L"cfg_compare").ConvertToImage(), zen::fastFromDIP(20));
+ const wxImage imgSync_ = zen::shrinkImage(zen::getResourceImage(L"cfg_sync" ).ConvertToImage(), zen::fastFromDIP(20));
+ const wxImage imgFilter_ = zen::shrinkImage(zen::getResourceImage(L"cfg_filter" ).ConvertToImage(), zen::fastFromDIP(20));
};
}
-
#endif //FOLDER_PAIR_H_89341750847252345
diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp
index 559dfa0d..7c9dbb81 100644
--- a/FreeFileSync/Source/ui/gui_generated.cpp
+++ b/FreeFileSync/Source/ui/gui_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -34,9 +34,8 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuFile->AppendSeparator();
- wxMenuItem* m_menuItem4;
- m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
- m_menuFile->Append( m_menuItem4 );
+ m_menuItemQuit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ), wxEmptyString, wxITEM_NORMAL );
+ m_menuFile->Append( m_menuItemQuit );
m_menubar->Append( m_menuFile, _("&File") );
@@ -150,6 +149,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer261->Add( m_buttonCancel, 0, wxEXPAND, 5 );
m_buttonCompare = new zen::BitmapTextButton( m_panelTopButtons, wxID_ANY, _("Compare"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonCompare->SetDefault();
m_buttonCompare->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
m_buttonCompare->SetToolTip( _("dummy") );
@@ -159,12 +159,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer261->Add( 4, 0, 0, 0, 5 );
- m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonCmpConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonCmpConfig->SetToolTip( _("dummy") );
bSizer261->Add( m_bpButtonCmpConfig, 0, wxEXPAND, 5 );
- m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonCmpContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonCmpContext->SetToolTip( _("dummy") );
bSizer261->Add( m_bpButtonCmpContext, 0, wxEXPAND, 5 );
@@ -184,12 +184,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer199->Add( 0, 0, 1, 0, 5 );
- m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
+ m_bpButtonFilter = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0|wxFULL_REPAINT_ON_RESIZE );
m_bpButtonFilter->SetToolTip( _("dummy") );
bSizer199->Add( m_bpButtonFilter, 0, wxEXPAND, 5 );
- m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonFilterContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonFilterContext->SetToolTip( _("dummy") );
bSizer199->Add( m_bpButtonFilterContext, 0, wxEXPAND, 5 );
@@ -209,12 +209,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer262->Add( 0, 0, 1, 0, 5 );
- m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSyncConfig = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSyncConfig->SetToolTip( _("dummy") );
bSizer262->Add( m_bpButtonSyncConfig, 0, wxEXPAND, 5 );
- m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSyncContext = new wxBitmapButton( m_panelTopButtons, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSyncContext->SetToolTip( _("dummy") );
bSizer262->Add( m_bpButtonSyncContext, 0, wxEXPAND, 5 );
@@ -243,7 +243,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer1791->Fit( m_panelTopButtons );
bSizerPanelHolder->Add( m_panelTopButtons, 0, wxEXPAND, 5 );
- m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL );
+ m_panelDirectoryPairs = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC );
wxBoxSizer* bSizer1601;
bSizer1601 = new wxBoxSizer( wxVERTICAL );
@@ -269,12 +269,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer159;
bSizer159 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonAddPair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonAddPair->SetToolTip( _("Add folder pair") );
bSizer159->Add( m_bpButtonAddPair, 0, wxEXPAND, 5 );
- m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRemovePair = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") );
bSizer159->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 );
@@ -293,7 +293,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer182->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelTopLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") );
bSizer182->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
@@ -311,7 +311,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1771;
bSizer1771 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSwapSides = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSwapSides->SetToolTip( _("dummy") );
bSizer1771->Add( m_bpButtonSwapSides, 0, wxEXPAND, 5 );
@@ -319,17 +319,17 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer160;
bSizer160 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonLocalCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalCompCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalCompCfg->SetToolTip( _("dummy") );
bSizer160->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 );
- m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalFilter = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalFilter->SetToolTip( _("dummy") );
bSizer160->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 );
- m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panelTopCenter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") );
bSizer160->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 );
@@ -364,7 +364,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer179->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") );
bSizer179->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
@@ -429,7 +429,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer1781->Fit( m_splitterMain );
bSizer1711->Add( m_splitterMain, 1, wxEXPAND, 5 );
- m_panelStatusBar = new wxPanel( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL );
+ m_panelStatusBar = new wxPanel( m_panelCenter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_STATIC );
wxBoxSizer* bSizer451;
bSizer451 = new wxBoxSizer( wxHORIZONTAL );
@@ -591,7 +591,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1713;
bSizer1713 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonHideSearch = new wxBitmapButton( m_panelSearch, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonHideSearch->SetToolTip( _("Close search bar") );
bSizer1713->Add( m_bpButtonHideSearch, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
@@ -754,7 +754,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer17611;
bSizer17611 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonNew = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonNew->SetToolTip( _("dummy") );
bSizer17611->Add( m_bpButtonNew, 0, wxEXPAND, 5 );
@@ -769,7 +769,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1761;
bSizer1761 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonOpen = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonOpen->SetToolTip( _("dummy") );
bSizer1761->Add( m_bpButtonOpen, 0, wxEXPAND, 5 );
@@ -784,7 +784,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer175;
bSizer175 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSave = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSave->SetToolTip( _("dummy") );
bSizer175->Add( m_bpButtonSave, 0, wxEXPAND, 5 );
@@ -802,12 +802,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer1772;
bSizer1772 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSaveAs = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSaveAs->SetToolTip( _("dummy") );
bSizer1772->Add( m_bpButtonSaveAs, 1, 0, 5 );
- m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSaveAsBatch = new wxBitmapButton( m_panelConfig, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSaveAsBatch->SetToolTip( _("dummy") );
bSizer1772->Add( m_bpButtonSaveAsBatch, 1, 0, 5 );
@@ -838,7 +838,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_panelViewFilter = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
bSizerViewFilter = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonShowLog = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
+ m_bpButtonShowLog = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowLog, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -847,10 +847,10 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer287;
bSizer287 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonViewTypeSyncAction = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonViewTypeSyncAction = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizer287->Add( m_bpButtonViewTypeSyncAction, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonViewContext = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonViewContext = new wxBitmapButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonViewContext->SetToolTip( _("dummy") );
bSizer287->Add( m_bpButtonViewContext, 0, wxRIGHT|wxEXPAND, 5 );
@@ -858,49 +858,49 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizerViewFilter->Add( bSizer287, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonShowExcluded = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowExcluded = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowExcluded, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT, 5 );
- m_bpButtonShowDeleteLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowDeleteLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowDeleteLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowUpdateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowUpdateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowUpdateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowCreateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowCreateLeft = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowCreateLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowLeftOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowLeftOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowLeftOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowLeftNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowLeftNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowLeftNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowEqual = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowEqual = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowEqual, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDoNothing = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowDoNothing = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowDoNothing, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDifferent = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowDifferent = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowDifferent, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowRightNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowRightNewer = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowRightNewer, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowRightOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowRightOnly = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowRightOnly, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowCreateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowCreateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowCreateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowUpdateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowUpdateRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowUpdateRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowDeleteRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowDeleteRight = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowDeleteRight, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonShowConflict = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonShowConflict = new zen::ToggleButton( m_panelViewFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizerViewFilter->Add( m_bpButtonShowConflict, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -910,7 +910,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_staticText96->Wrap( -1 );
bSizerViewFilter->Add( m_staticText96, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
- m_panelStatistics = new wxPanel( m_panelViewFilter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
+ m_panelStatistics = new wxPanel( m_panelViewFilter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_SUNKEN );
m_panelStatistics->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
bSizer1801 = new wxBoxSizer( wxVERTICAL );
@@ -1117,26 +1117,26 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) );
- this->Connect( m_menuItemNew->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigNew ) );
- this->Connect( m_menuItemLoad->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigLoad ) );
- this->Connect( m_menuItemSave->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSave ) );
- this->Connect( m_menuItemSaveAs->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSaveAs ) );
- this->Connect( m_menuItemSaveAsBatch->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveAsBatchJob ) );
- this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) );
- this->Connect( m_menuItemShowLog->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnShowLog ) );
- this->Connect( m_menuItemCompare->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) );
- this->Connect( m_menuItemCompSettings->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ) );
- this->Connect( m_menuItemFilter->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigureFilter ) );
- this->Connect( m_menuItemSyncSettings->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ) );
- this->Connect( m_menuItemSynchronize->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) );
- this->Connect( m_menuItemOptions->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuOptions ) );
- this->Connect( m_menuItemFind->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuFindItem ) );
- this->Connect( m_menuItemExportList->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) );
- this->Connect( m_menuItem51->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuResetLayout ) );
- this->Connect( m_menuItemHelp->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnShowHelp ) );
- this->Connect( m_menuItemCheckVersionNow->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) );
- this->Connect( m_menuItemCheckVersionAuto->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersionAutomatically ) );
- this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) );
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigNew ), this, m_menuItemNew->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigLoad ), this, m_menuItemLoad->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSave ), this, m_menuItemSave->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigSaveAs ), this, m_menuItemSaveAs->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveAsBatchJob ), this, m_menuItemSaveAsBatch->GetId());
+ m_menuFile->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ), this, m_menuItemQuit->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnShowLog ), this, m_menuItemShowLog->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), this, m_menuItemCompare->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), this, m_menuItemCompSettings->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnConfigureFilter ), this, m_menuItemFilter->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), this, m_menuItemSyncSettings->GetId());
+ m_menu4->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), this, m_menuItemSynchronize->GetId());
+ m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuOptions ), this, m_menuItemOptions->GetId());
+ m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuFindItem ), this, m_menuItemFind->GetId());
+ m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ), this, m_menuItemExportList->GetId());
+ m_menuTools->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuResetLayout ), this, m_menuItem51->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnShowHelp ), this, m_menuItemHelp->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ), this, m_menuItemCheckVersionNow->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersionAutomatically ), this, m_menuItemCheckVersionAuto->GetId());
+ m_menuHelp->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ), this, m_menuItemAbout->GetId());
m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this );
m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this );
m_bpButtonCmpConfig->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( MainDialogGenerated::OnCompSettingsContext ), NULL, this );
@@ -1189,7 +1189,7 @@ MainDialogGenerated::~MainDialogGenerated()
{
}
-FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bSizer74;
bSizer74 = new wxBoxSizer( wxHORIZONTAL );
@@ -1200,12 +1200,12 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
wxBoxSizer* bSizer134;
bSizer134 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonFolderPairOptions = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonFolderPairOptions->SetToolTip( _("Arrange folder pair") );
bSizer134->Add( m_bpButtonFolderPairOptions, 0, wxEXPAND, 5 );
- m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRemovePair = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") );
bSizer134->Add( m_bpButtonRemovePair, 0, wxEXPAND, 5 );
@@ -1218,7 +1218,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer134->Add( m_buttonSelectFolderLeft, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderLeft = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltFolderLeft->SetToolTip( _("Access online storage") );
bSizer134->Add( m_bpButtonSelectAltFolderLeft, 0, wxEXPAND, 5 );
@@ -1233,17 +1233,17 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
wxBoxSizer* bSizer95;
bSizer95 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonLocalCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalCompCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalCompCfg->SetToolTip( _("dummy") );
bSizer95->Add( m_bpButtonLocalCompCfg, 0, wxEXPAND, 5 );
- m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalFilter = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalFilter->SetToolTip( _("dummy") );
bSizer95->Add( m_bpButtonLocalFilter, 0, wxEXPAND, 5 );
- m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLocalSyncCfg = new wxBitmapButton( m_panel20, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonLocalSyncCfg->SetToolTip( _("dummy") );
bSizer95->Add( m_bpButtonLocalSyncCfg, 0, wxEXPAND, 5 );
@@ -1268,7 +1268,7 @@ FolderPairPanelGenerated::FolderPairPanelGenerated( wxWindow* parent, wxWindowID
bSizer135->Add( m_buttonSelectFolderRight, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltFolderRight = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltFolderRight->SetToolTip( _("Access online storage") );
bSizer135->Add( m_bpButtonSelectAltFolderRight, 0, wxEXPAND, 5 );
@@ -1356,26 +1356,26 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText91->Wrap( -1 );
bSizer182->Add( m_staticText91, 0, wxALL, 5 );
- wxBoxSizer* bSizer2381;
- bSizer2381 = new wxBoxSizer( wxVERTICAL );
+ wxGridSizer* gSizer2;
+ gSizer2 = new wxGridSizer( 0, 1, 5, 0 );
m_toggleBtnByTimeSize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File time and size"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnByTimeSize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer2381->Add( m_toggleBtnByTimeSize, 0, wxEXPAND|wxBOTTOM, 5 );
+ gSizer2->Add( m_toggleBtnByTimeSize, 0, wxEXPAND, 5 );
m_toggleBtnByContent = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnByContent->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer2381->Add( m_toggleBtnByContent, 0, wxEXPAND|wxBOTTOM, 5 );
+ gSizer2->Add( m_toggleBtnByContent, 0, wxEXPAND, 5 );
m_toggleBtnBySize = new wxToggleButton( m_panelComparisonSettings, wxID_ANY, _("File size"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnBySize->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer2381->Add( m_toggleBtnBySize, 0, wxEXPAND, 5 );
+ gSizer2->Add( m_toggleBtnBySize, 0, wxEXPAND, 5 );
- bSizer182->Add( bSizer2381, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer182->Add( gSizer2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizer178->Add( bSizer182, 0, wxALL, 5 );
@@ -1866,31 +1866,31 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticText86->Wrap( -1 );
bSizer235->Add( m_staticText86, 0, wxALL, 5 );
- wxBoxSizer* bSizer236;
- bSizer236 = new wxBoxSizer( wxVERTICAL );
+ wxGridSizer* gSizer1;
+ gSizer1 = new wxGridSizer( 0, 1, 5, 0 );
m_toggleBtnTwoWay = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnTwoWay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnTwoWay, 0, wxBOTTOM|wxEXPAND, 5 );
+ gSizer1->Add( m_toggleBtnTwoWay, 0, wxEXPAND, 5 );
m_toggleBtnMirror = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnMirror->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnMirror, 0, wxEXPAND|wxBOTTOM, 5 );
+ gSizer1->Add( m_toggleBtnMirror, 0, wxEXPAND, 5 );
m_toggleBtnUpdate = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnUpdate->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnUpdate, 0, wxEXPAND|wxBOTTOM, 5 );
+ gSizer1->Add( m_toggleBtnUpdate, 0, wxEXPAND, 5 );
m_toggleBtnCustom = new wxToggleButton( m_panelSyncSettings, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
m_toggleBtnCustom->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
- bSizer236->Add( m_toggleBtnCustom, 0, wxEXPAND, 5 );
+ gSizer1->Add( m_toggleBtnCustom, 0, wxEXPAND, 5 );
- bSizer235->Add( bSizer236, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer235->Add( gSizer1, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizer237->Add( bSizer235, 0, wxALL, 5 );
@@ -1946,22 +1946,22 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
ffgSizer11->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLeftOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonLeftNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonDifferent = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonConflict = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRightNewer = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonRightOnly = new wxBitmapButton( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
ffgSizer11->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -1974,7 +1974,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerSyncDirHolder->Add( bSizerSyncDirections, 0, 0, 5 );
- bSizerDatabase = new wxWrapSizer( wxVERTICAL );
+ bSizerDatabase = new wxBoxSizer( wxVERTICAL );
m_bitmapDatabase = new wxStaticBitmap( m_panelSyncSettings, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerDatabase->Add( m_bitmapDatabase, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -2133,7 +2133,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer156->Add( m_buttonSelectVersioningFolder, 0, wxEXPAND, 5 );
- m_bpButtonSelectVersioningAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectVersioningAltFolder = new wxBitmapButton( m_panelVersioning, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectVersioningAltFolder->SetToolTip( _("Access online storage") );
bSizer156->Add( m_bpButtonSelectVersioningAltFolder, 0, wxEXPAND, 5 );
@@ -2280,7 +2280,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer279->Add( m_buttonSelectLogFolder, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltLogFolder = new wxBitmapButton( m_panelLogfile, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltLogFolder->SetToolTip( _("Access online storage") );
bSizer279->Add( m_bpButtonSelectAltLogFolder, 0, wxEXPAND, 5 );
@@ -2353,6 +2353,7 @@ ConfigDlgGenerated::ConfigDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -2889,6 +2890,7 @@ CloudSetupDlgGenerated::CloudSetupDlgGenerated( wxWindow* parent, wxWindowID id,
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -2949,7 +2951,7 @@ AbstractFolderPickerGenerated::AbstractFolderPickerGenerated( wxWindow* parent,
m_staticTextStatus->Wrap( -1 );
bSizer185->Add( m_staticTextStatus, 0, wxALL, 5 );
- m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxNO_BORDER );
+ m_treeCtrlFileSystem = new wxTreeCtrl( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxTR_FULL_ROW_HIGHLIGHT|wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_NO_LINES|wxBORDER_NONE );
bSizer185->Add( m_treeCtrlFileSystem, 1, wxEXPAND, 5 );
@@ -2964,6 +2966,7 @@ AbstractFolderPickerGenerated::AbstractFolderPickerGenerated( wxWindow* parent,
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonOkay = new wxButton( this, wxID_OK, _("Select Folder"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -3185,6 +3188,7 @@ SyncConfirmationDlgGenerated::SyncConfirmationDlgGenerated( wxWindow* parent, wx
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonStartSync = new wxButton( this, wxID_OK, _("Start"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonStartSync->SetDefault();
m_buttonStartSync->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -3216,7 +3220,7 @@ SyncConfirmationDlgGenerated::~SyncConfirmationDlgGenerated()
{
}
-CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+CompareProgressDlgGenerated::CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
@@ -3416,7 +3420,7 @@ CompareProgressDlgGenerated::~CompareProgressDlgGenerated()
{
}
-SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
bSizerRoot = new wxBoxSizer( wxVERTICAL );
@@ -3443,7 +3447,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizer247->Add( 0, 0, 1, 0, 5 );
- m_bpButtonMinimizeToTray = new wxBitmapButton( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonMinimizeToTray = new wxBitmapButton( m_panel53, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonMinimizeToTray->SetToolTip( _("Minimize to notification area") );
bSizer247->Add( m_bpButtonMinimizeToTray, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5 );
@@ -3726,6 +3730,7 @@ SyncProgressPanelGenerated::SyncProgressPanelGenerated( wxWindow* parent, wxWind
bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 );
m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonClose->SetDefault();
m_buttonClose->Enable( false );
@@ -3750,7 +3755,7 @@ SyncProgressPanelGenerated::~SyncProgressPanelGenerated()
{
}
-LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
+LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
@@ -3760,13 +3765,13 @@ LogPanelGenerated::LogPanelGenerated( wxWindow* parent, wxWindowID id, const wxP
wxBoxSizer* bSizer154;
bSizer154 = new wxBoxSizer( wxVERTICAL );
- m_bpButtonErrors = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonErrors = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizer154->Add( m_bpButtonErrors, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonWarnings = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonWarnings = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizer154->Add( m_bpButtonWarnings, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_bpButtonInfo = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonInfo = new zen::ToggleButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
bSizer154->Add( m_bpButtonInfo, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -3936,6 +3941,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonSaveAs = new wxButton( this, wxID_SAVE, _("Save &as..."), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonSaveAs->SetDefault();
m_buttonSaveAs->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -4005,7 +4011,7 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
- m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
@@ -4026,6 +4032,7 @@ DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 );
m_buttonOK = new wxButton( this, wxID_OK, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -4094,7 +4101,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 );
- m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND, 5 );
@@ -4111,7 +4118,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizer182->Add( m_buttonSelectTargetFolder, 0, wxEXPAND, 5 );
- m_bpButtonSelectAltTargetFolder = new wxBitmapButton( m_panel31, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
+ m_bpButtonSelectAltTargetFolder = new wxBitmapButton( m_panel31, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
m_bpButtonSelectAltTargetFolder->SetToolTip( _("Access online storage") );
bSizer182->Add( m_bpButtonSelectAltTargetFolder, 0, wxEXPAND, 5 );
@@ -4148,6 +4155,7 @@ CopyToDlgGenerated::CopyToDlgGenerated( wxWindow* parent, wxWindowID id, const w
bSizerStdButtons->Add( 0, 0, 1, wxEXPAND, 5 );
m_buttonOK = new wxButton( this, wxID_OK, _("Copy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOK->SetDefault();
m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -4409,7 +4417,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizer290->Add( m_buttonSelectSoundCompareDone, 0, wxEXPAND, 5 );
- m_bpButtonPlayCompareDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
+ m_bpButtonPlayCompareDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizer290->Add( m_bpButtonPlayCompareDone, 0, wxEXPAND, 5 );
@@ -4436,7 +4444,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizer2901->Add( m_buttonSelectSoundSyncDone, 0, wxEXPAND, 5 );
- m_bpButtonPlaySyncDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
+ m_bpButtonPlaySyncDone = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizer2901->Add( m_bpButtonPlaySyncDone, 0, wxEXPAND, 5 );
@@ -4454,9 +4462,93 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer181;
bSizer181 = new wxBoxSizer( wxVERTICAL );
+ wxBoxSizer* bSizer289;
+ bSizer289 = new wxBoxSizer( wxHORIZONTAL );
+
m_staticText85 = new wxStaticText( m_panel39, wxID_ANY, _("Customize context menu:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText85->Wrap( -1 );
- bSizer181->Add( m_staticText85, 0, wxBOTTOM, 5 );
+ bSizer289->Add( m_staticText85, 1, wxRIGHT, 5 );
+
+ wxFlexGridSizer* fgSizer25;
+ fgSizer25 = new wxFlexGridSizer( 0, 2, 0, 10 );
+ fgSizer25->SetFlexibleDirection( wxBOTH );
+ fgSizer25->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+ m_staticText174 = new wxStaticText( m_panel39, wxID_ANY, _("%item_path%"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText174->Wrap( -1 );
+ m_staticText174->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
+ m_staticText174->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText174, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText175 = new wxStaticText( m_panel39, wxID_ANY, _("Full file or folder path"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText175->Wrap( -1 );
+ m_staticText175->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText175, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText178 = new wxStaticText( m_panel39, wxID_ANY, _("%local_path%"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText178->Wrap( -1 );
+ m_staticText178->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
+ m_staticText178->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText178, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText179 = new wxStaticText( m_panel39, wxID_ANY, _("Temporary local copy for SFTP and MTP storage"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText179->Wrap( -1 );
+ m_staticText179->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText179, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText189 = new wxStaticText( m_panel39, wxID_ANY, _("%item_name%"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText189->Wrap( -1 );
+ m_staticText189->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
+ m_staticText189->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText189, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText190 = new wxStaticText( m_panel39, wxID_ANY, _("File or folder name"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText190->Wrap( -1 );
+ m_staticText190->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText190, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText176 = new wxStaticText( m_panel39, wxID_ANY, _("%parent_path%"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText176->Wrap( -1 );
+ m_staticText176->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
+ m_staticText176->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText176, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticText177 = new wxStaticText( m_panel39, wxID_ANY, _("Parent folder path"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText177->Wrap( -1 );
+ m_staticText177->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
+
+ fgSizer25->Add( m_staticText177, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer289->Add( fgSizer25, 0, wxLEFT, 5 );
+
+
+ bSizer181->Add( bSizer289, 0, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer193;
+ bSizer193 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
+ bSizer193->Add( m_bpButtonAddRow, 0, wxALIGN_BOTTOM, 5 );
+
+ m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW|0 );
+ bSizer193->Add( m_bpButtonRemoveRow, 0, wxALIGN_BOTTOM, 5 );
+
+
+ bSizer193->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ m_hyperlink17 = new wxHyperlinkCtrl( m_panel39, wxID_ANY, _("Show examples"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
+ bSizer193->Add( m_hyperlink17, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer181->Add( bSizer193, 0, wxEXPAND, 5 );
m_gridCustomCommand = new wxGrid( m_panel39, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
@@ -4473,12 +4565,12 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_gridCustomCommand->SetColLabelSize( -1 );
m_gridCustomCommand->SetColLabelValue( 0, _("Description") );
m_gridCustomCommand->SetColLabelValue( 1, _("Command line") );
- m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
+ m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Rows
m_gridCustomCommand->EnableDragRowSize( false );
m_gridCustomCommand->SetRowLabelSize( 1 );
- m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
+ m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
// Label Appearance
@@ -4486,24 +4578,6 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
bSizer181->Add( m_gridCustomCommand, 1, wxEXPAND, 5 );
- wxBoxSizer* bSizer193;
- bSizer193 = new wxBoxSizer( wxHORIZONTAL );
-
- m_bpButtonAddRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
- bSizer193->Add( m_bpButtonAddRow, 0, wxEXPAND, 5 );
-
- m_bpButtonRemoveRow = new wxBitmapButton( m_panel39, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), wxBU_AUTODRAW );
- bSizer193->Add( m_bpButtonRemoveRow, 0, wxEXPAND, 5 );
-
-
- bSizer193->Add( 0, 0, 1, wxEXPAND, 5 );
-
- m_hyperlink17 = new wxHyperlinkCtrl( m_panel39, wxID_ANY, _("Show examples"), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- bSizer193->Add( m_hyperlink17, 0, wxLEFT, 5 );
-
-
- bSizer181->Add( bSizer193, 0, wxTOP|wxEXPAND, 5 );
-
bSizer166->Add( bSizer181, 1, wxEXPAND|wxALL, 10 );
@@ -4525,6 +4599,7 @@ OptionsDlgGenerated::OptionsDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizerStdButtons->Add( 0, 0, 1, 0, 5 );
m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -4604,10 +4679,10 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
wxBoxSizer* bSizer98;
bSizer98 = new wxBoxSizer( wxHORIZONTAL );
- m_calendarFrom = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxNO_BORDER );
+ m_calendarFrom = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxBORDER_NONE );
bSizer98->Add( m_calendarFrom, 0, wxTOP|wxBOTTOM|wxLEFT, 10 );
- m_calendarTo = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxNO_BORDER );
+ m_calendarTo = new wxCalendarCtrl( m_panel35, wxID_ANY, wxDefaultDateTime, wxDefaultPosition, wxDefaultSize, wxCAL_SHOW_HOLIDAYS|wxBORDER_NONE );
bSizer98->Add( m_calendarTo, 0, wxALL, 10 );
@@ -4622,6 +4697,7 @@ SelectTimespanDlgGenerated::SelectTimespanDlgGenerated( wxWindow* parent, wxWind
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -4666,69 +4742,29 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bSizer174;
bSizer174 = new wxBoxSizer( wxHORIZONTAL );
+ m_bitmapLogoLeft = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer174->Add( m_bitmapLogoLeft, 0, 0, 5 );
+
+ m_staticline81 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+ bSizer174->Add( m_staticline81, 0, wxEXPAND, 5 );
+
bSizerMainSection = new wxBoxSizer( wxVERTICAL );
+ m_staticline82 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizerMainSection->Add( m_staticline82, 0, wxEXPAND, 5 );
+
m_bitmapLogo = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
bSizerMainSection->Add( m_bitmapLogo, 0, 0, 5 );
m_staticline341 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerMainSection->Add( m_staticline341, 0, wxEXPAND, 5 );
- wxBoxSizer* bSizer186;
- bSizer186 = new wxBoxSizer( wxVERTICAL );
-
- m_staticText94 = new wxStaticText( m_panel41, wxID_ANY, _("Feedback and suggestions are welcome:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText94->Wrap( -1 );
- bSizer186->Add( m_staticText94, 0, wxALL, 5 );
-
- ffgSizer11 = new wxFlexGridSizer( 2, 0, 5, 10 );
- ffgSizer11->SetFlexibleDirection( wxBOTH );
- ffgSizer11->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
-
- m_bitmapHomepage = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
- m_bitmapHomepage->SetToolTip( _("Home page") );
-
- ffgSizer11->Add( m_bitmapHomepage, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapForum = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
- m_bitmapForum->SetToolTip( _("FreeFileSync Forum") );
-
- ffgSizer11->Add( m_bitmapForum, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapEmail = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
- m_bitmapEmail->SetToolTip( _("Email") );
-
- ffgSizer11->Add( m_bitmapEmail, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_hyperlink1 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("FreeFileSync.org"), wxT("https://freefilesync.org/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, true, wxEmptyString ) );
- m_hyperlink1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink1->SetToolTip( _("https://freefilesync.org") );
-
- ffgSizer11->Add( m_hyperlink1, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_hyperlink21 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("FreeFileSync Forum"), wxT("https://freefilesync.org/forum/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink21->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, true, wxEmptyString ) );
- m_hyperlink21->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink21->SetToolTip( _("https://freefilesync.org/forum/") );
-
- ffgSizer11->Add( m_hyperlink21, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_hyperlink2 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("zenju@freefilesync.org"), wxT("mailto:zenju@freefilesync.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, true, wxEmptyString ) );
- m_hyperlink2->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink2->SetToolTip( _("mailto:zenju@freefilesync.org") );
-
- ffgSizer11->Add( m_hyperlink2, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ m_staticTextVersion = new wxStaticText( m_panel41, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextVersion->Wrap( -1 );
+ bSizerMainSection->Add( m_staticTextVersion, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
-
- bSizer186->Add( ffgSizer11, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
-
-
- bSizerMainSection->Add( bSizer186, 0, wxALL|wxEXPAND, 5 );
-
- m_staticline3412 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizerMainSection->Add( m_staticline3412, 0, wxEXPAND, 5 );
+ m_staticline3411 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizerMainSection->Add( m_staticline3411, 0, wxEXPAND, 5 );
m_panelDonate = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_panelDonate->SetBackgroundColour( wxColour( 153, 170, 187 ) );
@@ -4780,7 +4816,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_panelDonate->SetSizer( bSizer183 );
m_panelDonate->Layout();
bSizer183->Fit( m_panelDonate );
- bSizerMainSection->Add( m_panelDonate, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
+ bSizerMainSection->Add( m_panelDonate, 0, wxEXPAND|wxALL, 10 );
m_panelThankYou = new wxPanel( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_panelThankYou->SetBackgroundColour( wxColour( 153, 170, 187 ) );
@@ -4831,121 +4867,68 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_panelThankYou->SetSizer( bSizer1831 );
m_panelThankYou->Layout();
bSizer1831->Fit( m_panelThankYou );
- bSizerMainSection->Add( m_panelThankYou, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 10 );
-
- wxBoxSizer* bSizer187;
- bSizer187 = new wxBoxSizer( wxVERTICAL );
-
- m_staticText96 = new wxStaticText( m_panel41, wxID_ANY, _("Source code written in C++ using:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText96->Wrap( -1 );
- bSizer187->Add( m_staticText96, 0, wxALL, 5 );
-
- wxBoxSizer* bSizer171;
- bSizer171 = new wxBoxSizer( wxHORIZONTAL );
-
- m_hyperlink11 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("MS Visual Studio"), wxT("https://www.visualstudio.com"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink11->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink11->SetToolTip( _("https://www.visualstudio.com") );
-
- bSizer171->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
-
- m_hyperlink7 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("wxWidgets"), wxT("https://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink7->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink7->SetToolTip( _("https://www.wxwidgets.org") );
-
- bSizer171->Add( m_hyperlink7, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
-
- m_hyperlink14 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("wxFormBuilder"), wxT("https://github.com/wxFormBuilder/wxFormBuilder"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink14->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink14->SetToolTip( _("https://github.com/wxFormBuilder/wxFormBuilder") );
+ bSizerMainSection->Add( m_panelThankYou, 0, wxEXPAND|wxALL, 10 );
- bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
-
- m_hyperlink16 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink16->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink16->SetToolTip( _("http://astyle.sourceforge.net") );
-
- bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
-
- bSizer187->Add( bSizer171, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
-
- wxBoxSizer* bSizer172;
- bSizer172 = new wxBoxSizer( wxHORIZONTAL );
+ m_staticline3412 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizerMainSection->Add( m_staticline3412, 0, wxEXPAND, 5 );
- m_hyperlink15 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("zen::Xml"), wxT("http://zenxml.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink15->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink15->SetToolTip( _("http://zenxml.sourceforge.net") );
+ wxBoxSizer* bSizer186;
+ bSizer186 = new wxBoxSizer( wxVERTICAL );
- bSizer172->Add( m_hyperlink15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ m_staticText94 = new wxStaticText( m_panel41, wxID_ANY, _("Feedback and suggestions are welcome:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText94->Wrap( -1 );
+ bSizer186->Add( m_staticText94, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 );
- m_hyperlink12 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Google Test"), wxT("https://github.com/google/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink12->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink12->SetToolTip( _("https://github.com/google/googletest") );
+ wxBoxSizer* bSizer289;
+ bSizer289 = new wxBoxSizer( wxHORIZONTAL );
- bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ m_bpButtonForum = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+ m_bpButtonForum->SetToolTip( _("https://freefilesync.org/forum/") );
- m_hyperlink10 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("libssh2"), wxT("https://www.libssh2.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink10->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink10->SetToolTip( _("https://www.libssh2.org") );
+ bSizer289->Add( m_bpButtonForum, 0, wxALL|wxEXPAND, 5 );
- bSizer172->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ wxBoxSizer* bSizer290;
+ bSizer290 = new wxBoxSizer( wxVERTICAL );
- m_hyperlink101 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("libcurl"), wxT("https://curl.haxx.se/libcurl"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink101->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink101->SetToolTip( _("https://curl.haxx.se/libcurl") );
+ m_bpButtonHomepage = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+ m_bpButtonHomepage->SetToolTip( _("https://freefilesync.org") );
- bSizer172->Add( m_hyperlink101, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer290->Add( m_bpButtonHomepage, 1, wxTOP|wxRIGHT|wxEXPAND, 5 );
- m_hyperlink18 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("NSIS"), wxT("https://nsis.sourceforge.io"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink18->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink18->SetToolTip( _("https://nsis.sourceforge.io") );
- bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ bSizer290->Add( 0, 5, 0, 0, 5 );
- m_hyperlink9 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Inno Setup"), wxT("http://www.jrsoftware.org/isinfo.php"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink9->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
- m_hyperlink9->SetToolTip( _("http://www.jrsoftware.org/isinfo.php") );
+ m_bpButtonEmail = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+ m_bpButtonEmail->SetToolTip( _("mailto:zenju@freefilesync.org") );
- bSizer172->Add( m_hyperlink9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ bSizer290->Add( m_bpButtonEmail, 1, wxEXPAND|wxBOTTOM|wxRIGHT, 5 );
- m_hyperlink25 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("xBRZ"), wxT("https://sourceforge.net/projects/xbrz/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink25->SetToolTip( _("https://sourceforge.net/projects/xbrz/") );
- bSizer172->Add( m_hyperlink25, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer289->Add( bSizer290, 0, wxEXPAND, 5 );
- bSizer187->Add( bSizer172, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizer186->Add( bSizer289, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- bSizerMainSection->Add( bSizer187, 0, wxALL|wxEXPAND, 5 );
+ bSizerMainSection->Add( bSizer186, 0, wxALL|wxEXPAND, 5 );
m_staticline34 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerMainSection->Add( m_staticline34, 0, wxEXPAND, 5 );
wxBoxSizer* bSizer185;
- bSizer185 = new wxBoxSizer( wxVERTICAL );
-
- m_staticText93 = new wxStaticText( m_panel41, wxID_ANY, _("Published under the GNU General Public License:"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText93->Wrap( -1 );
- bSizer185->Add( m_staticText93, 0, wxALL, 5 );
-
- wxBoxSizer* bSizer1671;
- bSizer1671 = new wxBoxSizer( wxHORIZONTAL );
-
- m_bitmapGpl = new wxStaticBitmap( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1, -1 ), 0 );
- bSizer1671->Add( m_bitmapGpl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
-
- m_hyperlink5 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("https://www.gnu.org/licenses/gpl-3.0"), wxT("https://www.gnu.org/licenses/gpl-3.0"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
- m_hyperlink5->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+ bSizer185 = new wxBoxSizer( wxHORIZONTAL );
- bSizer1671->Add( m_hyperlink5, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+ m_staticTextGpl = new wxStaticText( m_panel41, wxID_ANY, _("Published under the GNU General Public License:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextGpl->Wrap( -1 );
+ bSizer185->Add( m_staticTextGpl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+ m_bpButtonGpl = new wxBitmapButton( m_panel41, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+ m_bpButtonGpl->SetToolTip( _("https://www.gnu.org/licenses/gpl-3.0") );
- bSizer185->Add( bSizer1671, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ bSizer185->Add( m_bpButtonGpl, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
- bSizerMainSection->Add( bSizer185, 0, wxALL|wxEXPAND, 5 );
+ bSizerMainSection->Add( bSizer185, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
bSizer174->Add( bSizerMainSection, 0, 0, 5 );
@@ -4956,17 +4939,9 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bSizer177;
bSizer177 = new wxBoxSizer( wxVERTICAL );
- m_staticline74 = new wxStaticLine( m_panel41, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer177->Add( m_staticline74, 0, wxEXPAND, 5 );
-
- m_staticTextThanksForLoc = new wxStaticText( m_panel41, wxID_ANY, _("Many thanks for localization:"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+ m_staticTextThanksForLoc = new wxStaticText( m_panel41, wxID_ANY, _("Many thanks for localization:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextThanksForLoc->Wrap( -1 );
- m_staticTextThanksForLoc->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
-
- bSizer177->Add( m_staticTextThanksForLoc, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 10 );
-
-
- bSizer177->Add( 0, 5, 0, 0, 5 );
+ bSizer177->Add( m_staticTextThanksForLoc, 0, wxALL, 5 );
m_scrolledWindowTranslators = new wxScrolledWindow( m_panel41, wxID_ANY, wxDefaultPosition, wxSize( -1, -1 ), wxVSCROLL );
m_scrolledWindowTranslators->SetScrollRate( 10, 10 );
@@ -4980,10 +4955,10 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
m_scrolledWindowTranslators->SetSizer( fgSizerTranslators );
m_scrolledWindowTranslators->Layout();
fgSizerTranslators->Fit( m_scrolledWindowTranslators );
- bSizer177->Add( m_scrolledWindowTranslators, 1, wxLEFT|wxEXPAND, 10 );
+ bSizer177->Add( m_scrolledWindowTranslators, 1, wxEXPAND|wxLEFT, 5 );
- bSizer174->Add( bSizer177, 0, wxEXPAND, 5 );
+ bSizer174->Add( bSizer177, 0, wxEXPAND|wxLEFT, 5 );
m_panel41->SetSizer( bSizer174 );
@@ -4997,6 +4972,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonClose->SetDefault();
bSizerStdButtons->Add( m_buttonClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
@@ -5014,6 +4990,10 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) );
m_buttonDonate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnDonate ), NULL, this );
m_buttonShowDonationDetails->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnShowDonationDetails ), NULL, this );
+ m_bpButtonForum->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOpenForum ), NULL, this );
+ m_bpButtonHomepage->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOpenHomepage ), NULL, this );
+ m_bpButtonEmail->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnSendEmail ), NULL, this );
+ m_bpButtonGpl->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnShowGpl ), NULL, this );
m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this );
}
@@ -5064,6 +5044,7 @@ DownloadProgressDlgGenerated::DownloadProgressDlgGenerated( wxWindow* parent, wx
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonCancel->SetDefault();
bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
@@ -5112,7 +5093,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
bSizer16->Add( 0, 10, 0, 0, 5 );
- m_textCtrlLastError = new wxTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlLastError = new wxTextCtrl( m_panel35, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
bSizer16->Add( m_textCtrlLastError, 1, wxEXPAND, 5 );
@@ -5158,6 +5139,7 @@ ActivationDlgGenerated::ActivationDlgGenerated( wxWindow* parent, wxWindowID id,
bSizer234->Add( m_staticText136, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_buttonActivateOnline = new wxButton( m_panel3511, wxID_ANY, _("Activate online"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonActivateOnline->SetDefault();
m_buttonActivateOnline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -5306,6 +5288,7 @@ CfgHighlightDlgGenerated::CfgHighlightDlgGenerated( wxWindow* parent, wxWindowID
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonOkay->SetDefault();
m_buttonOkay->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
@@ -5416,6 +5399,7 @@ WarnAccessRightsMissingDlgGenerated::WarnAccessRightsMissingDlgGenerated( wxWind
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonClose = new wxButton( this, wxID_OK, _("Close"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonClose->SetDefault();
bSizerStdButtons->Add( m_buttonClose, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h
index 15653910..2a966144 100644
--- a/FreeFileSync/Source/ui/gui_generated.h
+++ b/FreeFileSync/Source/ui/gui_generated.h
@@ -1,12 +1,11 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
-#ifndef __GUI_GENERATED_H__
-#define __GUI_GENERATED_H__
+#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
@@ -45,7 +44,6 @@
#include <wx/hyperlink.h>
#include <wx/spinctrl.h>
#include <wx/choice.h>
-#include <wx/wrapsizer.h>
#include <wx/notebook.h>
#include <wx/dialog.h>
#include <wx/treectrl.h>
@@ -73,6 +71,7 @@ protected:
wxMenuItem* m_menuItemSave;
wxMenuItem* m_menuItemSaveAs;
wxMenuItem* m_menuItemSaveAsBatch;
+ wxMenuItem* m_menuItemQuit;
wxMenu* m_menu4;
wxMenuItem* m_menuItemShowLog;
wxMenuItem* m_menuItemCompare;
@@ -308,7 +307,7 @@ public:
fff::FolderHistoryBox* m_folderPathRight;
wxBitmapButton* m_bpButtonSelectAltFolderRight;
- FolderPairPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0 );
+ FolderPairPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxEmptyString );
~FolderPairPanelGenerated();
};
@@ -428,7 +427,7 @@ protected:
wxBitmapButton* m_bpButtonRightNewer;
wxBitmapButton* m_bpButtonRightOnly;
wxStaticText* m_staticText120;
- wxWrapSizer* bSizerDatabase;
+ wxBoxSizer* bSizerDatabase;
wxStaticBitmap* m_bitmapDatabase;
wxStaticText* m_staticText145;
wxStaticText* m_staticTextSyncVarDescription;
@@ -772,7 +771,7 @@ public:
wxBoxSizer* bSizerErrorsIgnore;
wxStaticBitmap* m_bitmapIgnoreErrors;
- CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxRAISED_BORDER );
+ CompareProgressDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxBORDER_RAISED, const wxString& name = wxEmptyString );
~CompareProgressDlgGenerated();
};
@@ -834,7 +833,7 @@ public:
wxButton* m_buttonPause;
wxButton* m_buttonStop;
- SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL );
+ SyncProgressPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~SyncProgressPanelGenerated();
};
@@ -861,7 +860,7 @@ protected:
public:
zen::Grid* m_gridMessages;
- LogPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL );
+ LogPanelGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~LogPanelGenerated();
};
@@ -1039,10 +1038,18 @@ protected:
wxBitmapButton* m_bpButtonPlaySyncDone;
wxStaticLine* m_staticline3611;
wxStaticText* m_staticText85;
- wxGrid* m_gridCustomCommand;
+ wxStaticText* m_staticText174;
+ wxStaticText* m_staticText175;
+ wxStaticText* m_staticText178;
+ wxStaticText* m_staticText179;
+ wxStaticText* m_staticText189;
+ wxStaticText* m_staticText190;
+ wxStaticText* m_staticText176;
+ wxStaticText* m_staticText177;
wxBitmapButton* m_bpButtonAddRow;
wxBitmapButton* m_bpButtonRemoveRow;
wxHyperlinkCtrl* m_hyperlink17;
+ wxGrid* m_gridCustomCommand;
wxStaticLine* m_staticline36;
wxBoxSizer* bSizerStdButtons;
wxButton* m_buttonDefault;
@@ -1132,18 +1139,14 @@ private:
protected:
wxPanel* m_panel41;
+ wxStaticBitmap* m_bitmapLogoLeft;
+ wxStaticLine* m_staticline81;
wxBoxSizer* bSizerMainSection;
+ wxStaticLine* m_staticline82;
wxStaticBitmap* m_bitmapLogo;
wxStaticLine* m_staticline341;
- wxStaticText* m_staticText94;
- wxFlexGridSizer* ffgSizer11;
- wxStaticBitmap* m_bitmapHomepage;
- wxStaticBitmap* m_bitmapForum;
- wxStaticBitmap* m_bitmapEmail;
- wxHyperlinkCtrl* m_hyperlink1;
- wxHyperlinkCtrl* m_hyperlink21;
- wxHyperlinkCtrl* m_hyperlink2;
- wxStaticLine* m_staticline3412;
+ wxStaticText* m_staticTextVersion;
+ wxStaticLine* m_staticline3411;
wxPanel* m_panelDonate;
wxPanel* m_panel39;
wxStaticBitmap* m_bitmapDonate;
@@ -1155,24 +1158,15 @@ protected:
wxStaticText* m_staticTextThanks;
wxStaticText* m_staticTextNoAutoUpdate;
wxButton* m_buttonShowDonationDetails;
- wxStaticText* m_staticText96;
- wxHyperlinkCtrl* m_hyperlink11;
- wxHyperlinkCtrl* m_hyperlink7;
- wxHyperlinkCtrl* m_hyperlink14;
- wxHyperlinkCtrl* m_hyperlink16;
- wxHyperlinkCtrl* m_hyperlink15;
- wxHyperlinkCtrl* m_hyperlink12;
- wxHyperlinkCtrl* m_hyperlink10;
- wxHyperlinkCtrl* m_hyperlink101;
- wxHyperlinkCtrl* m_hyperlink18;
- wxHyperlinkCtrl* m_hyperlink9;
- wxHyperlinkCtrl* m_hyperlink25;
+ wxStaticLine* m_staticline3412;
+ wxStaticText* m_staticText94;
+ wxBitmapButton* m_bpButtonForum;
+ wxBitmapButton* m_bpButtonHomepage;
+ wxBitmapButton* m_bpButtonEmail;
wxStaticLine* m_staticline34;
- wxStaticText* m_staticText93;
- wxStaticBitmap* m_bitmapGpl;
- wxHyperlinkCtrl* m_hyperlink5;
+ wxStaticText* m_staticTextGpl;
+ wxBitmapButton* m_bpButtonGpl;
wxStaticLine* m_staticline37;
- wxStaticLine* m_staticline74;
wxStaticText* m_staticTextThanksForLoc;
wxScrolledWindow* m_scrolledWindowTranslators;
wxFlexGridSizer* fgSizerTranslators;
@@ -1184,6 +1178,10 @@ protected:
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnDonate( wxCommandEvent& event ) { event.Skip(); }
virtual void OnShowDonationDetails( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnOpenForum( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnOpenHomepage( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnSendEmail( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnShowGpl( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOK( wxCommandEvent& event ) { event.Skip(); }
@@ -1339,4 +1337,3 @@ public:
};
-#endif //__GUI_GENERATED_H__
diff --git a/FreeFileSync/Source/ui/log_panel.cpp b/FreeFileSync/Source/ui/log_panel.cpp
index 8e770d43..51cfa703 100644
--- a/FreeFileSync/Source/ui/log_panel.cpp
+++ b/FreeFileSync/Source/ui/log_panel.cpp
@@ -190,6 +190,11 @@ public:
return std::wstring();
}
+ void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
+ {
+ GridData::renderRowBackgound(dc, rect, row, true /*enabled*/, enabled && selected);
+ }
+
void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover) override
{
wxRect rectTmp = rect;
@@ -249,11 +254,6 @@ public:
}
}
- void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
- {
- GridData::renderRowBackgound(dc, rect, row, true /*enabled*/, enabled && selected);
- }
-
int getBestSize(wxDC& dc, size_t row, ColumnType colType) override
{
// -> synchronize renderCell() <-> getBestSize()
diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp
index b77a2a7e..5fbaea53 100644
--- a/FreeFileSync/Source/ui/main_dlg.cpp
+++ b/FreeFileSync/Source/ui/main_dlg.cpp
@@ -57,7 +57,7 @@ using namespace fff;
namespace
{
const size_t EXT_APP_MASS_INVOKE_THRESHOLD = 10; //more is likely a user mistake (Explorer uses limit of 15)
-const int TOP_BUTTON_OPTIMAL_WIDTH_DIP = 180;
+const int TOP_BUTTON_OPTIMAL_WIDTH_DIP = 170;
const std::chrono::milliseconds LAST_USED_CFG_EXISTENCE_CHECK_TIME_MAX(500);
const std::chrono::milliseconds FILE_GRID_POST_UPDATE_DELAY(400);
@@ -243,14 +243,14 @@ void updateTopButton(wxBitmapButton& btn, const wxBitmap& bmp, const wxString& v
wxImage variantImage = createImageFromText(variantName,
wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD),
wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
- wxImage descrImage = stackImages(labelImage, variantImage, ImageStackLayout::VERTICAL, ImageStackAlignment::CENTER);
+ wxImage descrImage = stackImages(labelImage, variantImage, ImageStackLayout::vertical, ImageStackAlignment::center);
const wxImage& iconImage = makeGrey ? greyScale(bmp.ConvertToImage()) : bmp.ConvertToImage();
wxImage dynImage = btn.GetLayoutDirection() != wxLayout_RightToLeft ?
- stackImages(iconImage, descrImage, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, fastFromDIP(5)) :
- stackImages(descrImage, iconImage, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, fastFromDIP(5));
+ stackImages(iconImage, descrImage, ImageStackLayout::horizontal, ImageStackAlignment::center, fastFromDIP(5)) :
+ stackImages(descrImage, iconImage, ImageStackLayout::horizontal, ImageStackAlignment::center, fastFromDIP(5));
- wxSize btnSize = dynImage.GetSize() + wxSize(fastFromDIP(16), fastFromDIP(16)); //add border space
+ wxSize btnSize = dynImage.GetSize() + wxSize(fastFromDIP(10), fastFromDIP(10)); //add border space
btnSize.x = std::max(btnSize.x, fastFromDIP(TOP_BUTTON_OPTIMAL_WIDTH_DIP));
dynImage.Resize(btnSize, wxPoint() + (btnSize - dynImage.GetSize()) / 2);
@@ -424,8 +424,8 @@ MainDialog::MainDialog(const Zstring& globalConfigFilePath,
m_bpButtonHideSearch ->SetBitmapLabel(getResourceImage(L"close_panel"));
m_bpButtonShowLog ->SetBitmapLabel(getResourceImage(L"log_file"));
- m_bpButtonFilter ->SetMinSize(wxSize(getResourceImage(L"cfg_filter").GetWidth() + fastFromDIP(27), -1)); //make the filter button wider
- m_textCtrlSearchTxt->SetMinSize(wxSize(fastFromDIP(220), -1));
+ m_bpButtonFilter ->SetMinSize({getResourceImage(L"cfg_filter").GetWidth() + fastFromDIP(27), -1}); //make the filter button wider
+ m_textCtrlSearchTxt->SetMinSize({fastFromDIP(220), -1});
//----------------------------------------------------------------------------------------
wxImage labelImage = createImageFromText(_("Select view:"), m_bpButtonViewTypeSyncAction->GetFont(), wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
@@ -435,7 +435,7 @@ MainDialog::MainDialog(const Zstring& globalConfigFilePath,
auto generateViewTypeImage = [&](const wxString& imgName)
{
- return stackImages(labelImage, mirrorIfRtl(getResourceImage(imgName).ConvertToImage()), ImageStackLayout::VERTICAL, ImageStackAlignment::CENTER);
+ return stackImages(labelImage, mirrorIfRtl(getResourceImage(imgName).ConvertToImage()), ImageStackLayout::vertical, ImageStackAlignment::center);
};
m_bpButtonViewTypeSyncAction->init(generateViewTypeImage(L"viewtype_sync_action"),
generateViewTypeImage(L"viewtype_cmp_result"));
@@ -465,8 +465,11 @@ MainDialog::MainDialog(const Zstring& globalConfigFilePath,
//init log panel
setRelativeFontSize(*m_staticTextLogStatus, 1.5);
+ const wxBitmap& bmpTime = getResourceImage(L"cmp_file_time_sicon");
m_bitmapItemStat->SetBitmap(bmpFile);
- m_bitmapTimeStat->SetBitmap(getResourceImage(L"cmp_file_time_sicon"));
+ m_bitmapTimeStat->SetBitmap(bmpTime);
+ m_bitmapItemStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
+ m_bitmapTimeStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
logPanel_ = new LogPanel(m_panelLog); //pass ownership
bSizerLog->Add(logPanel_, 1, wxEXPAND);
@@ -511,8 +514,8 @@ MainDialog::MainDialog(const Zstring& globalConfigFilePath,
m_panelTopButtons->GetSizer()->SetSizeHints(m_panelTopButtons); //~=Fit() + SetMinSize()
m_buttonCancel->SetBitmap(getTransparentPixel()); //set dummy image (can't be empty!): text-only buttons are rendered smaller on OS X!
- m_buttonCancel->SetMinSize(wxSize(std::max(m_buttonCancel->GetSize().x, fastFromDIP(TOP_BUTTON_OPTIMAL_WIDTH_DIP)),
- std::max(m_buttonCancel->GetSize().y, m_buttonCompare->GetSize().y)));
+ m_buttonCancel->SetMinSize({std::max(m_buttonCancel->GetSize().x, fastFromDIP(TOP_BUTTON_OPTIMAL_WIDTH_DIP)),
+ std::max(m_buttonCancel->GetSize().y, m_buttonCompare->GetSize().y)});
auiMgr_.AddPane(m_panelTopButtons,
wxAuiPaneInfo().Name(L"TopPanel").Layer(2).Top().Row(1).Caption(_("Main Bar")).CaptionVisible(false).
@@ -608,6 +611,7 @@ MainDialog::MainDialog(const Zstring& globalConfigFilePath,
m_panelSearch->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnSearchPanelKeyPressed), nullptr, this);
+
//set tool tips with (non-translated!) short cut hint
m_bpButtonNew ->SetToolTip(replaceCpy(_("&New"), L"&", L"") + L" (Ctrl+N)"); //
m_bpButtonOpen ->SetToolTip(replaceCpy(_("&Open..."), L"&", L"") + L" (Ctrl+O)"); //
@@ -1014,19 +1018,28 @@ void MainDialog::setGlobalCfgOnInit(const XmlGlobalSettings& globalSettings)
paneCaptions.emplace_back(&paneArray[i], paneArray[i].caption);
//compare progress dialog minimum sizes are layout-dependent + can't be changed by user => don't load stale values from config
+ std::vector<std::tuple<wxAuiPaneInfo*, wxSize /*min size*/, wxSize /*best size*/>> paneConstraints;
+ auto preserveConstraint = [&paneConstraints](wxAuiPaneInfo& pane) { paneConstraints.emplace_back(&pane, pane.min_size, pane.best_size); };
+
wxAuiPaneInfo& progPane = auiMgr_.GetPane(compareStatus_->getAsWindow());
- wxAuiPaneInfo& viewPane = auiMgr_.GetPane(m_panelViewFilter); //same goes for view filter
- const std::pair<wxSize, wxSize> progPaneSizeOrig(progPane.min_size, progPane.best_size);
- const std::pair<wxSize, wxSize> viewPaneSizeOrig(viewPane.min_size, viewPane.best_size);
+ preserveConstraint(auiMgr_.GetPane(m_panelTopButtons));
+ preserveConstraint(progPane);
+ preserveConstraint(auiMgr_.GetPane(m_panelSearch));
+ preserveConstraint(auiMgr_.GetPane(m_panelViewFilter));
+ preserveConstraint(auiMgr_.GetPane(m_panelConfig));
- auiMgr_.LoadPerspective(globalSettings.gui.mainDlg.guiPerspectiveLast);
+ auiMgr_.LoadPerspective(globalSettings.gui.mainDlg.guiPerspectiveLast, false /*don't call wxAuiManager::Update() yet*/);
//restore original captions
for (const auto& [paneInfo, caption] : paneCaptions)
paneInfo->Caption(caption);
- std::tie(progPane.min_size, progPane.best_size) = progPaneSizeOrig;
- std::tie(viewPane.min_size, viewPane.best_size) = viewPaneSizeOrig;
+ //restore pane layout constraints
+ for (auto& [pane, minSize, bestSize] : paneConstraints)
+ {
+ pane->min_size = minSize;
+ pane->best_size = bestSize;
+ }
//--------------------------------------------------------------------------------
//if MainDialog::onQueryEndSession() is called while comparison is active, this panel is saved and restored as "visible"
@@ -1464,9 +1477,11 @@ void invokeCommandLine(const Zstring& commandLinePhrase, //throw FileError
const AbstractPath basePath = fsObj->base().getAbstractPath<side >();
const AbstractPath basePath2 = fsObj->base().getAbstractPath<side2>();
- //full path, even if item is not (yet) existing:
- const Zstring itemPath = AFS::isNullPath(basePath ) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj-> getAbstractPath<side >()));
- const Zstring itemPath2 = AFS::isNullPath(basePath2) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj-> getAbstractPath<side2>()));
+ //return paths, even if item is not (yet) existing:
+ const Zstring itemPath = AFS::isNullPath(basePath ) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj-> getAbstractPath<side >()));
+ const Zstring itemPath2 = AFS::isNullPath(basePath2) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj-> getAbstractPath<side2>()));
+ const Zstring itemName = AFS::isNullPath(basePath ) ? Zstr("") : AFS::getItemName (fsObj-> getAbstractPath<side >());
+ const Zstring itemName2 = AFS::isNullPath(basePath2) ? Zstr("") : AFS::getItemName (fsObj-> getAbstractPath<side2>());
const Zstring folderPath = AFS::isNullPath(basePath ) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj->parent().getAbstractPath<side >()));
const Zstring folderPath2 = AFS::isNullPath(basePath2) ? Zstr("") : utfTo<Zstring>(AFS::getDisplayPath(fsObj->parent().getAbstractPath<side2>()));
@@ -1489,10 +1504,12 @@ void invokeCommandLine(const Zstring& commandLinePhrase, //throw FileError
Zstring command = commandLinePhrase;
replace(command, Zstr("%item_path%"), itemPath);
replace(command, Zstr("%item_path2%"), itemPath2);
- replace(command, Zstr("%folder_path%"), folderPath);
- replace(command, Zstr("%folder_path2%"), folderPath2);
replace(command, Zstr("%local_path%"), localPath);
replace(command, Zstr("%local_path2%"), localPath2);
+ replace(command, Zstr("%item_name%"), itemName);
+ replace(command, Zstr("%item_name2%"), itemName2);
+ replace(command, Zstr("%parent_path%"), folderPath);
+ replace(command, Zstr("%parent_path2%"), folderPath2);
shellExecute(command, selection.size() > EXT_APP_MASS_INVOKE_THRESHOLD ? ExecutionType::SYNC : ExecutionType::ASYNC, false/*hideConsole*/); //throw FileError
}
@@ -1813,7 +1830,7 @@ void MainDialog::OnResizeLeftFolderWidth(wxEvent& event)
//adapt left-shift display distortion caused by scrollbars for multiple folder pairs
const int width = m_panelTopLeft->GetSize().GetWidth();
for (FolderPairPanel* panel : additionalFolderPairs_)
- panel->m_panelLeft->SetMinSize(wxSize(width, -1));
+ panel->m_panelLeft->SetMinSize({width, -1});
event.Skip();
}
@@ -2665,7 +2682,7 @@ void MainDialog::resetLayout()
{
m_splitterMain->setSashOffset(0);
- auiMgr_.LoadPerspective(defaultPerspective_);
+ auiMgr_.LoadPerspective(defaultPerspective_, false /*don't call wxAuiManager::Update() => already done in updateGuiForFolderPair() */);
updateGuiForFolderPair();
}
@@ -2725,8 +2742,8 @@ void MainDialog::OnCompSettingsContext(wxEvent& event)
menu.addItem(getVariantName(cmpVar), [&setVariant, cmpVar] { setVariant(cmpVar); }, activeCmpVar == cmpVar ? &iconNormal : &iconGrey);
};
addVariantItem(CompareVariant::timeSize, L"cmp_file_time_sicon");
- addVariantItem(CompareVariant::content, L"cmp_file_content_sicon");
- addVariantItem(CompareVariant::size, L"cmp_file_size_sicon");
+ addVariantItem(CompareVariant::content, L"cmp_file_content_sicon");
+ addVariantItem(CompareVariant::size, L"cmp_file_size_sicon");
//menu.addRadio(getVariantName(CompareVariant::timeSize), [&] { setVariant(CompareVariant::timeSize); }, activeCmpVar == CompareVariant::timeSize);
//menu.addRadio(getVariantName(CompareVariant::content ), [&] { setVariant(CompareVariant::content); }, activeCmpVar == CompareVariant::content);
@@ -4614,8 +4631,8 @@ void MainDialog::updateGridViewData()
wxImage imgIconReleased = imgCategory.ConvertToGreyscale(1.0/3, 1.0/3, 1.0/3); //treat all channels equally!
brighten(imgIconReleased, 80);
- wxImage imgButtonPressed = stackImages(imgCategory, imgCountPressed, ImageStackLayout::HORIZONTAL, ImageStackAlignment::BOTTOM);
- wxImage imgButtonReleased = stackImages(imgIconReleased, imgCountReleased, ImageStackLayout::HORIZONTAL, ImageStackAlignment::BOTTOM);
+ wxImage imgButtonPressed = stackImages(imgCategory, imgCountPressed, ImageStackLayout::horizontal, ImageStackAlignment::bottom);
+ wxImage imgButtonReleased = stackImages(imgIconReleased, imgCountReleased, ImageStackLayout::horizontal, ImageStackAlignment::bottom);
wxBitmap bmpBorderRect(imgButtonPressed.GetWidth(), imgButtonPressed.GetHeight()); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
{
@@ -5214,7 +5231,7 @@ void MainDialog::insertAddFolderPair(const std::vector<LocalPairConfig>& newPair
//set width of left folder panel
const int width = m_panelTopLeft->GetSize().GetWidth();
- newPair->m_panelLeft->SetMinSize(wxSize(width, -1));
+ newPair->m_panelLeft->SetMinSize({width, -1});
//register events
newPair->m_bpButtonFolderPairOptions->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxEventHandler(MainDialog::OnShowFolderPairOptions), nullptr, this);
diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp
index 7a3e48a9..7f2ac3df 100644
--- a/FreeFileSync/Source/ui/progress_indicator.cpp
+++ b/FreeFileSync/Source/ui/progress_indicator.cpp
@@ -181,8 +181,11 @@ CompareProgressPanel::Impl::Impl(wxFrame& parentWindow) :
CompareProgressDlgGenerated(&parentWindow),
parentWindow_(parentWindow)
{
+ const wxBitmap& bmpTime = getResourceImage(L"cmp_file_time_sicon");
m_bitmapItemStat->SetBitmap(IconBuffer::genericFileIcon(IconBuffer::SIZE_SMALL));
- m_bitmapTimeStat->SetBitmap(getResourceImage(L"cmp_file_time_sicon"));
+ m_bitmapTimeStat->SetBitmap(bmpTime);
+ m_bitmapItemStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
+ m_bitmapTimeStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
m_bitmapIgnoreErrors->SetBitmap(getResourceImage(L"error_ignore_active"));
m_bitmapRetryErrors ->SetBitmap(getResourceImage(L"error_retry"));
@@ -767,7 +770,7 @@ SyncProgressDialogImpl<TopLevelDialog>::SyncProgressDialogImpl(long style, //wxF
assert((std::is_same_v<TopLevelDialog, wxFrame> == !parentFrame));
//finish construction of this dialog:
- this->pnl_.m_panelProgress->SetMinSize(wxSize(fastFromDIP(550), fastFromDIP(340)));
+ this->pnl_.m_panelProgress->SetMinSize({fastFromDIP(550), fastFromDIP(340)});
wxBoxSizer* bSizer170 = new wxBoxSizer(wxVERTICAL);
bSizer170->Add(&pnl_, 1, wxEXPAND);
@@ -815,8 +818,11 @@ SyncProgressDialogImpl<TopLevelDialog>::SyncProgressDialogImpl(long style, //wxF
pnl_.m_bpButtonMinimizeToTray->SetBitmapLabel(getResourceImage(L"minimize_to_tray"));
+ const wxBitmap& bmpTime = getResourceImage(L"cmp_file_time_sicon");
pnl_.m_bitmapItemStat->SetBitmap(IconBuffer::genericFileIcon(IconBuffer::SIZE_SMALL));
- pnl_.m_bitmapTimeStat->SetBitmap(getResourceImage(L"cmp_file_time_sicon"));
+ pnl_.m_bitmapTimeStat->SetBitmap(bmpTime);
+ pnl_.m_bitmapItemStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
+ pnl_.m_bitmapTimeStat->SetMinSize({-1, std::max(IconBuffer::getSize(IconBuffer::SIZE_SMALL), bmpTime.GetHeight())});
pnl_.m_bitmapIgnoreErrors->SetBitmap(getResourceImage(L"error_ignore_active"));
pnl_.m_bitmapRetryErrors ->SetBitmap(getResourceImage(L"error_retry"));
diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp
index 256100fd..867711ae 100644
--- a/FreeFileSync/Source/ui/small_dlgs.cpp
+++ b/FreeFileSync/Source/ui/small_dlgs.cpp
@@ -60,6 +60,11 @@ private:
void OnOK (wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_OKAY); }
void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); }
void OnDonate(wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"https://freefilesync.org/donate.php"); }
+ void OnOpenHomepage(wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"https://freefilesync.org/"); }
+ void OnOpenForum (wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"https://freefilesync.org/forum/"); }
+ void OnSendEmail (wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"mailto:zenju@freefilesync.org"); }
+ void OnShowGpl (wxCommandEvent& event) override { wxLaunchDefaultBrowser(L"https://www.gnu.org/licenses/gpl-3.0"); }
+
void onLocalKeyEvent(wxKeyEvent& event);
};
@@ -70,11 +75,32 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent)
assert(m_buttonClose->GetId() == wxID_OK); //we cannot use wxID_CLOSE else Esc key won't work: yet another wxWidgets bug??
- m_bitmapHomepage->SetBitmap(getResourceImage(L"website"));
- m_bitmapForum ->SetBitmap(getResourceImage(L"forum"));
- m_bitmapEmail ->SetBitmap(getResourceImage(L"email"));
- m_bitmapGpl ->SetBitmap(getResourceImage(L"gpl"));
+ m_bitmapLogo ->SetBitmap(getResourceImage(L"logo"));
+ m_bitmapLogoLeft->SetBitmap(getResourceImage(L"logo-left"));
+
+
+ //------------------------------------
+ wxString build = utfTo<wxString>(ffsVersion);
+#ifndef wxUSE_UNICODE
+#error what is going on?
+#endif
+
+ const wchar_t* const SPACED_BULLET = L" \u2022 ";
+ build += SPACED_BULLET;
+
+ build += LTR_MARK; //fix Arabic
+#if ZEN_BUILD_ARCH == ZEN_ARCH_32BIT
+ build += L"32 Bit";
+#else
+ build += L"64 Bit";
+#endif
+
+ build += SPACED_BULLET;
+ build += formatTime<wxString>(FORMAT_DATE, getCompileTime());
+ m_staticTextVersion->SetLabel(replaceCpy(_("Version: %x"), L"%x", build));
+
+ //------------------------------------
{
m_panelThankYou->Hide();
m_bitmapDonate->SetBitmap(getResourceImage(L"ffs_heart"));
@@ -82,16 +108,31 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent)
setRelativeFontSize(*m_buttonDonate, 1.25);
}
- //m_animCtrlWink->SetAnimation(getResourceAnimation(L"wink"));
- //m_animCtrlWink->Play();
+ //------------------------------------
+ wxImage forumImage = stackImages(getResourceImage(L"forum").ConvertToImage(),
+ createImageFromText(L"FreeFileSync Forum", *wxNORMAL_FONT, m_bpButtonForum->GetForegroundColour()),
+ ImageStackLayout::vertical, ImageStackAlignment::center, fastFromDIP(5));
+ m_bpButtonForum->SetBitmapLabel(wxBitmap(forumImage));
+
+ setBitmapTextLabel(*m_bpButtonHomepage, getResourceImage(L"homepage").ConvertToImage(), L"FreeFileSync.org");
+ setBitmapTextLabel(*m_bpButtonEmail, getResourceImage(L"email" ).ConvertToImage(), L"zenju@freefilesync.org");
- m_staticTextThanksForLoc->SetMinSize(wxSize(fastFromDIP(200), -1));
+ //------------------------------------
+ m_bpButtonGpl->SetBitmapLabel(getResourceImage(L"gpl"));
+
+ //have the GPL text wrap to two lines:
+ wxMemoryDC dc;
+ dc.SetFont(m_staticTextGpl->GetFont());
+ const wxSize gplExt = dc.GetTextExtent(m_staticTextGpl->GetLabelText());
+ m_staticTextGpl->Wrap(gplExt.GetWidth() * 6 / 10);
+
+ //------------------------------------
+ m_staticTextThanksForLoc->SetMinSize({fastFromDIP(200), -1});
m_staticTextThanksForLoc->Wrap(fastFromDIP(200));
- //create language credits
for (const TranslationInfo& ti : getExistingTranslations())
{
- //flag
+ //country flag
wxStaticBitmap* staticBitmapFlag = new wxStaticBitmap(m_scrolledWindowTranslators, wxID_ANY, getResourceImage(ti.languageFlag));
fgSizerTranslators->Add(staticBitmapFlag, 0, wxALIGN_CENTER);
@@ -104,54 +145,7 @@ AboutDlg::AboutDlg(wxWindow* parent) : AboutDlgGenerated(parent)
}
fgSizerTranslators->Fit(m_scrolledWindowTranslators);
-
- std::wstring build = formatTime<std::wstring>(FORMAT_DATE, getCompileTime()) + SPACED_DASH + L"Unicode";
-#ifndef wxUSE_UNICODE
-#error what is going on?
-#endif
-
- build +=
-#if ZEN_BUILD_ARCH == ZEN_ARCH_32BIT
- L" x86";
-#else
- L" x64";
-#endif
-
-
- GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize()
-
- //generate logo: put *after* first Fit()
- Layout(); //make sure m_panelLogo has final width (required by wxGTK)
-
- wxImage appnameImg = createImageFromText(wxString(L"FreeFileSync ") + ffsVersion,
- wxFont(wxNORMAL_FONT->GetPointSize() * 1.8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, L"Tahoma"),
- *wxBLACK); //accessibility: align foreground/background colors!
- wxImage buildImg = createImageFromText(replaceCpy(_("Build: %x"), L"%x", build),
- *wxNORMAL_FONT,
- *wxBLACK,
- ImageStackAlignment::CENTER);
- wxImage versionImage = stackImages(appnameImg, buildImg, ImageStackLayout::VERTICAL, ImageStackAlignment::CENTER, 0);
-
- const int borderSize = fastFromDIP(5);
- wxBitmap headerBmp(bSizerMainSection->GetSize().x, versionImage.GetHeight() + 2 * borderSize, 24);
- //attention: *must* pass 24 bits, auto-determination fails on Windows high-contrast colors schemes!!!
- //problem only shows when calling wxDC::DrawBitmap
- {
- wxMemoryDC dc(headerBmp);
- dc.SetBackground(*wxWHITE_BRUSH);
- dc.Clear();
-
- const wxBitmap& bmpGradient = getResourceImage(L"logo_gradient");
- dc.DrawBitmap(bmpGradient, wxPoint(0, (headerBmp.GetHeight() - bmpGradient.GetHeight()) / 2));
-
- const int logoSize = versionImage.GetHeight();
- const wxBitmap logoBmp = getResourceImage(L"FreeFileSync").ConvertToImage().Scale(logoSize, logoSize, wxIMAGE_QUALITY_HIGH); //looks smooth unlike wxIMAGE_QUALITY_BILINEAR!
- dc.DrawBitmap(logoBmp, wxPoint(2 * borderSize, (headerBmp.GetHeight() - logoBmp.GetHeight()) / 2));
-
- dc.DrawBitmap(versionImage, wxPoint((headerBmp.GetWidth () - versionImage.GetWidth ()) / 2,
- (headerBmp.GetHeight() - versionImage.GetHeight()) / 2));
- }
- m_bitmapLogo->SetBitmap(headerBmp);
+ //------------------------------------
//enable dialog-specific key events
Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(AboutDlg::onLocalKeyEvent), nullptr, this);
@@ -263,12 +257,12 @@ CloudSetupDlg::CloudSetupDlg(wxWindow* parent, Zstring& folderPathPhrase, size_t
m_checkBoxShowPassword->SetValue(false);
m_textCtrlServer->SetHint(_("Example:") + L" website.com 66.198.240.22");
- m_textCtrlServer->SetMinSize(wxSize(fastFromDIP(260), -1));
+ m_textCtrlServer->SetMinSize({fastFromDIP(260), -1});
- m_textCtrlPort ->SetMinSize(wxSize(fastFromDIP(60), -1)); //
- m_spinCtrlConnectionCount ->SetMinSize(wxSize(fastFromDIP(70), -1)); //Hack: set size (why does wxWindow::Size() not work?)
- m_spinCtrlChannelCountSftp->SetMinSize(wxSize(fastFromDIP(70), -1)); //
- m_spinCtrlTimeout ->SetMinSize(wxSize(fastFromDIP(70), -1)); //
+ m_textCtrlPort ->SetMinSize({fastFromDIP(60), -1}); //
+ m_spinCtrlConnectionCount ->SetMinSize({fastFromDIP(70), -1}); //Hack: set size (why does wxWindow::Size() not work?)
+ m_spinCtrlChannelCountSftp->SetMinSize({fastFromDIP(70), -1}); //
+ m_spinCtrlTimeout ->SetMinSize({fastFromDIP(70), -1}); //
setupFileDrop(*m_panelAuth);
m_panelAuth->Connect(EVENT_DROP_FILE, FileDropEventHandler(CloudSetupDlg::onKeyFileDropped), nullptr, this);
@@ -395,6 +389,7 @@ void CloudSetupDlg::OnGdriveUserAdd(wxCommandEvent& event)
else
{
const wxString googleUser = utfTo<wxString>(std::get<Zstring>(result));
+
int selIdx = m_listBoxGdriveUsers->FindString(googleUser, false /*caseSensitive*/);
if (selIdx == wxNOT_FOUND)
selIdx = m_listBoxGdriveUsers->Append(googleUser);
@@ -735,7 +730,7 @@ CopyToDialog::CopyToDialog(wxWindow* parent,
m_targetFolderPath->init(folderHistory_);
- m_textCtrlFileList->SetMinSize(wxSize(fastFromDIP(500), fastFromDIP(200)));
+ m_textCtrlFileList->SetMinSize({fastFromDIP(500), fastFromDIP(200)});
/*
There is a nasty bug on wxGTK under Ubuntu: If a multi-line wxTextCtrl contains so many lines that scrollbars are shown,
@@ -862,7 +857,7 @@ DeleteDialog::DeleteDialog(wxWindow* parent,
setMainInstructionFont(*m_staticTextHeader);
- m_textCtrlFileList->SetMinSize(wxSize(fastFromDIP(500), fastFromDIP(200)));
+ m_textCtrlFileList->SetMinSize({fastFromDIP(500), fastFromDIP(200)});
m_checkBoxUseRecycler->SetValue(useRecycleBin);
@@ -1113,7 +1108,7 @@ OptionsDlg::OptionsDlg(wxWindow* parent, XmlGlobalSettings& globalSettings) :
//setMainInstructionFont(*m_staticTextHeader);
m_gridCustomCommand->SetTabBehaviour(wxGrid::Tab_Leave);
- m_spinCtrlLogFilesMaxAge->SetMinSize(wxSize(fastFromDIP(70), -1)); //Hack: set size (why does wxWindow::Size() not work?)
+ m_spinCtrlLogFilesMaxAge->SetMinSize({fastFromDIP(70), -1}); //Hack: set size (why does wxWindow::Size() not work?)
m_hyperlinkLogFolder->SetLabel(utfTo<wxString>(getDefaultLogFolderPath()));
setRelativeFontSize(*m_hyperlinkLogFolder, 1.2);
@@ -1146,16 +1141,6 @@ OptionsDlg::OptionsDlg(wxWindow* parent, XmlGlobalSettings& globalSettings) :
updateGui();
bSizerLockedFiles->Show(false);
-
- const wxString toolTip = wxString(_("Integrate external applications into context menu. The following macros are available:")) + L"\n\n" +
- L"%item_path% \t" + _("Full file or folder path") + L"\n" +
- L"%folder_path% \t" + _("Parent folder path") + L"\n" +
- L"%local_path% \t" + _("Temporary local copy for SFTP and MTP storage") + L"\n" +
- L"\n" +
- L"%item_path2%, %folder_path2%, %local_path2% \t" + _("Parameters for opposite side");
-
- m_gridCustomCommand->GetGridWindow() ->SetToolTip(toolTip);
- m_gridCustomCommand->GetGridColLabelWindow()->SetToolTip(toolTip);
m_gridCustomCommand->SetMargins(0, 0);
//temporarily set dummy value for window height calculations:
@@ -1499,7 +1484,7 @@ CfgHighlightDlg::CfgHighlightDlg(wxWindow* parent, int& cfgHistSyncOverdueDays)
m_staticTextHighlight->Wrap(fastFromDIP(300));
- m_spinCtrlOverdueDays->SetMinSize(wxSize(fastFromDIP(70), -1)); //Hack: set size (why does wxWindow::Size() not work?)
+ m_spinCtrlOverdueDays->SetMinSize({fastFromDIP(70), -1}); //Hack: set size (why does wxWindow::Size() not work?)
setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel));
@@ -1560,7 +1545,7 @@ ActivationDlg::ActivationDlg(wxWindow* parent,
//setMainInstructionFont(*m_staticTextMain);
- m_bitmapActivation->SetBitmap(getResourceImage(L"website"));
+ m_bitmapActivation->SetBitmap(getResourceImage(L"internet"));
m_textCtrlOfflineActivationKey->ForceUpper();
m_textCtrlLastError ->ChangeValue(lastErrorMsg);
@@ -1662,9 +1647,9 @@ DownloadProgressWindow::Impl::Impl(wxWindow* parent, int64_t fileSizeTotal) :
setMainInstructionFont(*m_staticTextHeader);
m_staticTextHeader->Wrap(fastFromDIP(460)); //*after* font change!
- m_staticTextDetails->SetMinSize(wxSize(fastFromDIP(550), -1));
+ m_staticTextDetails->SetMinSize({fastFromDIP(550), -1});
- m_bitmapDownloading->SetBitmap(getResourceImage(L"website"));
+ m_bitmapDownloading->SetBitmap(getResourceImage(L"internet"));
m_gaugeProgress->SetRange(GAUGE_FULL_RANGE);
diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp
index 1711f382..a4ce9809 100644
--- a/FreeFileSync/Source/ui/sync_cfg.cpp
+++ b/FreeFileSync/Source/ui/sync_cfg.cpp
@@ -304,14 +304,14 @@ commandHistItemsMax_(commandHistItemsMax)
m_toggleBtnByContent ->SetToolTip(getCompVariantDescription(CompareVariant::content));
m_toggleBtnBySize ->SetToolTip(getCompVariantDescription(CompareVariant::size));
- m_staticTextCompVarDescription->SetMinSize(wxSize(fastFromDIP(CFG_DESCRIPTION_WIDTH_DIP), -1));
+ m_staticTextCompVarDescription->SetMinSize({fastFromDIP(CFG_DESCRIPTION_WIDTH_DIP), -1});
- m_scrolledWindowPerf->SetMinSize(wxSize(fastFromDIP(220), -1));
+ m_scrolledWindowPerf->SetMinSize({fastFromDIP(220), -1});
m_bitmapPerf->SetBitmap(perfPanelActive_ ? getResourceImage(L"speed") : greyScale(getResourceImage(L"speed")));
m_panelPerfHeader ->Enable(perfPanelActive_);
- m_spinCtrlAutoRetryCount->SetMinSize(wxSize(fastFromDIP(60), -1)); //Hack: set size (why does wxWindow::Size() not work?)
- m_spinCtrlAutoRetryDelay->SetMinSize(wxSize(fastFromDIP(60), -1)); //
+ m_spinCtrlAutoRetryCount->SetMinSize({fastFromDIP(60), -1}); //Hack: set size (why does wxWindow::Size() not work?)
+ m_spinCtrlAutoRetryDelay->SetMinSize({fastFromDIP(60), -1}); //
//ignore invalid input for time shift control:
wxTextValidator inputValidator(wxFILTER_DIGITS | wxFILTER_INCLUDE_CHAR_LIST);
@@ -319,7 +319,7 @@ commandHistItemsMax_(commandHistItemsMax)
m_textCtrlTimeShift->SetValidator(inputValidator);
//------------- filter panel --------------------------
- m_textCtrlInclude->SetMinSize(wxSize(fastFromDIP(280), -1));
+ m_textCtrlInclude->SetMinSize({fastFromDIP(280), -1});
assert(!contains(m_buttonClear->GetLabel(), L"&C") && !contains(m_buttonClear->GetLabel(), L"&c")); //gazillionth wxWidgets bug on OS X: Command + C mistakenly hits "&C" access key!
@@ -365,7 +365,7 @@ commandHistItemsMax_(commandHistItemsMax)
setRelativeFontSize(*m_toggleBtnUpdate, 1.25);
setRelativeFontSize(*m_toggleBtnCustom, 1.25);
- m_staticTextSyncVarDescription->SetMinSize(wxSize(fastFromDIP(CFG_DESCRIPTION_WIDTH_DIP), -1));
+ m_staticTextSyncVarDescription->SetMinSize({fastFromDIP(CFG_DESCRIPTION_WIDTH_DIP), -1});
m_toggleBtnRecycler ->SetToolTip(_("Retain deleted and overwritten files in the recycle bin"));
m_toggleBtnPermanent ->SetToolTip(_("Delete and overwrite files permanently"));
@@ -376,11 +376,11 @@ commandHistItemsMax_(commandHistItemsMax)
add(VersioningStyle::timestampFolder, _("Time stamp") + L" [" + _("Folder") + L"]", _("Move files into a time-stamped subfolder")).
add(VersioningStyle::timestampFile, _("Time stamp") + L" [" + _("File") + L"]", _("Append a time stamp to each file name"));
- m_spinCtrlVersionMaxDays ->SetMinSize(wxSize(fastFromDIP(60), -1)); //
- m_spinCtrlVersionCountMin->SetMinSize(wxSize(fastFromDIP(60), -1)); //Hack: set size (why does wxWindow::Size() not work?)
- m_spinCtrlVersionCountMax->SetMinSize(wxSize(fastFromDIP(60), -1)); //
+ m_spinCtrlVersionMaxDays ->SetMinSize({fastFromDIP(60), -1}); //
+ m_spinCtrlVersionCountMin->SetMinSize({fastFromDIP(60), -1}); //Hack: set size (why does wxWindow::Size() not work?)
+ m_spinCtrlVersionCountMax->SetMinSize({fastFromDIP(60), -1}); //
- m_staticTextPostSync->SetMinSize(wxSize(fastFromDIP(180), -1));
+ m_staticTextPostSync->SetMinSize({fastFromDIP(180), -1});
enumPostSyncCondition_.
add(PostSyncCondition::COMPLETION, _("On completion:")).
@@ -1205,7 +1205,7 @@ void ConfigDialog::setMiscSyncOptions(const MiscSyncConfig& miscCfg)
for (int i = 0; i < rowsToCreate; ++i)
{
wxSpinCtrl* spinCtrlParallelOps = new wxSpinCtrl(m_scrolledWindowPerf, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 2000000000, 1);
- spinCtrlParallelOps->SetMinSize(wxSize(fastFromDIP(60), -1)); //Hack: set size (why does wxWindow::Size() not work?)
+ spinCtrlParallelOps->SetMinSize({fastFromDIP(60), -1}); //Hack: set size (why does wxWindow::Size() not work?)
spinCtrlParallelOps->Enable(perfPanelActive_);
fgSizerPerf->Add(spinCtrlParallelOps, 0, wxALIGN_CENTER_VERTICAL);
diff --git a/FreeFileSync/Source/ui/tree_grid.cpp b/FreeFileSync/Source/ui/tree_grid.cpp
index f6ebc8f5..963ebdd0 100644
--- a/FreeFileSync/Source/ui/tree_grid.cpp
+++ b/FreeFileSync/Source/ui/tree_grid.cpp
@@ -771,7 +771,7 @@ private:
return std::wstring();
}
- void renderColumnLabel(Grid& tree, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted) override
+ void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted) override
{
const auto colTypeTree = static_cast<ColumnTypeTree>(colType);
@@ -780,7 +780,7 @@ private:
rectRemain.x += getColumnGapLeft();
rectRemain.width -= getColumnGapLeft();
- drawColumnLabelText(dc, rectRemain, getColumnLabel(colType));
+ drawColumnLabelText(dc, rectRemain, getColumnLabel(colType), enabled);
const auto [sortCol, ascending] = treeDataView_.getSortDirection();
if (colTypeTree == sortCol)
@@ -790,25 +790,13 @@ private:
}
}
+ //void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override => GridData default is fine
+
enum class HoverAreaTree
{
NODE,
};
- void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected) override
- {
- if (enabled)
- {
- if (selected)
- dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
- //ignore focus
- else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
- }
- else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
- }
-
void renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover) override
{
//wxRect rectTmp= drawCellBorder(dc, rect);
diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h
index a13ee197..af47b93d 100644
--- a/FreeFileSync/Source/version/version.h
+++ b/FreeFileSync/Source/version/version.h
@@ -3,7 +3,7 @@
namespace fff
{
-const char ffsVersion[] = "10.18"; //internal linkage!
+const char ffsVersion[] = "10.19"; //internal linkage!
const char FFS_VERSION_SEPARATOR = '.';
}
diff --git a/wx+/bitmap_button.h b/wx+/bitmap_button.h
index bcbc7328..b40d8dd3 100644
--- a/wx+/bitmap_button.h
+++ b/wx+/bitmap_button.h
@@ -56,13 +56,13 @@ void setBitmapTextLabel(wxBitmapButton& btn, const wxImage& img, const wxString&
wxImage dynImage = createImageFromText(text, btn.GetFont(), btn.GetForegroundColour());
if (img.IsOk())
dynImage = btn.GetLayoutDirection() != wxLayout_RightToLeft ?
- stackImages(img, dynImage, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, gap) :
- stackImages(dynImage, img, ImageStackLayout::HORIZONTAL, ImageStackAlignment::CENTER, gap);
+ stackImages(img, dynImage, ImageStackLayout::horizontal, ImageStackAlignment::center, gap) :
+ stackImages(dynImage, img, ImageStackLayout::horizontal, ImageStackAlignment::center, gap);
- //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly
+ //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work correctly
const int defaultHeight = wxButton::GetDefaultSize().GetHeight();
- btn.SetMinSize(wxSize(dynImage.GetWidth () + 2 * border,
- std::max(dynImage.GetHeight() + 2 * border, defaultHeight)));
+ btn.SetMinSize({dynImage.GetWidth () + 2 * border,
+ std::max(dynImage.GetHeight() + 2 * border, defaultHeight)});
btn.SetBitmapLabel(wxBitmap(dynImage));
//SetLabel() calls confuse wxBitmapButton in the disabled state and it won't show the image! workaround:
@@ -73,7 +73,7 @@ void setBitmapTextLabel(wxBitmapButton& btn, const wxImage& img, const wxString&
inline
void setImage(wxBitmapButton& button, const wxBitmap& bmp)
{
- if (!isEqual(button.GetBitmapLabel(), bmp))
+ if (!button.GetBitmapLabel().IsSameAs(bmp))
{
button.SetBitmapLabel(bmp);
diff --git a/wx+/file_drop.h b/wx+/file_drop.h
index ee5393b7..9826bf27 100644
--- a/wx+/file_drop.h
+++ b/wx+/file_drop.h
@@ -60,8 +60,6 @@ using FileDropEventFunction = void (wxEvtHandler::*)(FileDropEvent&);
void setupFileDrop(wxWindow& wnd);
-
-
}
#endif //FILE_DROP_H_09457802957842560325626
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index a6d0f19d..ec338e99 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -226,11 +226,11 @@ void drawCornerText(wxDC& dc, const wxRect& graphArea, const wxString& txt, Grap
break;
}
- //add text shadow to improve readability:
- wxDCTextColourChanger textColor(dc, colorBack);
- dc.DrawText(txt, drawPos + border + wxSize(fastFromDIP(1), fastFromDIP(1)));
+ //add text shadow to improve readability:
+ wxDCTextColourChanger textColor(dc, colorBack);
+ dc.DrawText(txt, drawPos + border + wxSize(fastFromDIP(1), fastFromDIP(1)));
- textColor.Set(colorText);
+ textColor.Set(colorText);
dc.DrawText(txt, drawPos + border);
}
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 0613e14f..fe168df6 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -35,7 +35,7 @@ int GridData::getColumnGapLeft() { return fastFromDIP(4); }
namespace
{
//------------------------------ Grid Parameters --------------------------------
-inline wxColor getColorLabelText() { return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); }
+inline wxColor getColorLabelText(bool enabled) { return wxSystemSettings::GetColour(enabled ? wxSYS_COLOUR_WINDOWTEXT : wxSYS_COLOUR_GRAYTEXT); }
inline wxColor getColorGridLine() { return { 192, 192, 192 }; } //light grey
inline wxColor getColorLabelGradientFrom() { return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); }
@@ -213,13 +213,13 @@ wxSize GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring&
}
-void GridData::renderColumnLabel(Grid& grid, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted)
+void GridData::renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted)
{
wxRect rectRemain = drawColumnLabelBackground(dc, rect, highlighted);
rectRemain.x += getColumnGapLeft();
rectRemain.width -= getColumnGapLeft();
- drawColumnLabelText(dc, rectRemain, getColumnLabel(colType));
+ drawColumnLabelText(dc, rectRemain, getColumnLabel(colType), enabled);
}
@@ -247,9 +247,9 @@ wxRect GridData::drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool hi
}
-void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const std::wstring& text)
+void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const std::wstring& text, bool enabled)
{
- wxDCTextColourChanger textColor(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors!
+ wxDCTextColourChanger textColor(dc, getColorLabelText(enabled)); //accessibility: always set both foreground AND background colors!
drawCellText(dc, rect, text, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
}
@@ -500,7 +500,8 @@ private:
void render(wxDC& dc, const wxRect& rect) override
{
- clearArea(dc, rect, wxSystemSettings::GetColour(/*!renderAsEnabled(*this) ? wxSYS_COLOUR_BTNFACE :*/wxSYS_COLOUR_WINDOW));
+ const bool enabled = renderAsEnabled(*this);
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
dc.SetFont(GetFont()); //harmonize with RowLabelWin::getBestWidth()!
@@ -511,16 +512,16 @@ private:
if (singleLabelArea.height > 0)
{
singleLabelArea.y = refParent().CalcScrolledPosition(singleLabelArea.GetTopLeft()).y;
- drawRowLabel(dc, singleLabelArea, row);
+ drawRowLabel(dc, singleLabelArea, row, enabled);
}
}
}
- void drawRowLabel(wxDC& dc, const wxRect& rect, size_t row)
+ void drawRowLabel(wxDC& dc, const wxRect& rect, size_t row, bool enabled)
{
//clearArea(dc, rect, getColorRowLabel());
dc.GradientFillLinear(rect, getColorLabelGradientFrom(), getColorLabelGradientTo(), wxEAST); //clear overlapping cells
- wxDCTextColourChanger textColor(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors!
+ wxDCTextColourChanger textColor(dc, getColorLabelText(enabled)); //accessibility: always set both foreground AND background colors!
//label text
wxRect textRect = rect;
@@ -615,7 +616,8 @@ private:
void render(wxDC& dc, const wxRect& rect) override
{
- clearArea(dc, rect, wxSystemSettings::GetColour(/*!renderAsEnabled(*this) ? wxSYS_COLOUR_BTNFACE :*/wxSYS_COLOUR_WINDOW));
+ const bool enabled = renderAsEnabled(*this);
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
//coordinate with "colLabelHeight" in Grid constructor:
wxFont labelFont = GetFont();
@@ -637,7 +639,7 @@ private:
if (labelAreaTL.x > rect.GetRight())
return; //done, rect is fully covered
if (labelAreaTL.x + width > rect.x)
- drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(width, colLabelHeight)), col, it->type);
+ drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(width, colLabelHeight)), col, it->type, enabled);
labelAreaTL.x += width;
}
if (labelAreaTL.x > rect.GetRight())
@@ -652,11 +654,11 @@ private:
const int clientWidth = GetClientSize().GetWidth(); //need reliable, stable width in contrast to rect.width
if (totalWidth < clientWidth)
- drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(clientWidth - totalWidth, colLabelHeight)), absWidths.size(), ColumnType::NONE);
+ drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(clientWidth - totalWidth, colLabelHeight)), absWidths.size(), ColumnType::NONE, enabled);
}
}
- void drawColumnLabel(wxDC& dc, const wxRect& rect, size_t col, ColumnType colType)
+ void drawColumnLabel(wxDC& dc, const wxRect& rect, size_t col, ColumnType colType, bool enabled)
{
if (auto dataView = refParent().getDataProvider())
{
@@ -666,7 +668,7 @@ private:
false;
RecursiveDcClipper clip(dc, rect);
- dataView->renderColumnLabel(refParent(), dc, rect, colType, isHighlighted);
+ dataView->renderColumnLabel(dc, rect, colType, enabled, isHighlighted);
//draw move target location
if (refParent().allowColumnMove_)
@@ -885,7 +887,8 @@ public:
private:
void render(wxDC& dc, const wxRect& rect) override
{
- clearArea(dc, rect, wxSystemSettings::GetColour(/*!renderAsEnabled(*this) ? wxSYS_COLOUR_BTNFACE :*/wxSYS_COLOUR_WINDOW));
+ const bool enabled = renderAsEnabled(*this);
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
dc.SetFont(GetFont()); //harmonize with Grid::getBestColumnSize()
@@ -914,7 +917,7 @@ private:
{
const wxRect rowRect(cellAreaTL + wxPoint(0, row * rowHeight), wxSize(totalRowWidth, rowHeight));
RecursiveDcClipper dummy3(dc, rowRect);
- prov->renderRowBackgound(dc, rowRect, row, renderAsEnabled(*this), drawAsSelected(row));
+ prov->renderRowBackgound(dc, rowRect, row, enabled, drawAsSelected(row));
}
//draw single cells, column by column
@@ -928,7 +931,7 @@ private:
{
const wxRect cellRect(cellAreaTL.x, cellAreaTL.y + row * rowHeight, cw.width, rowHeight);
RecursiveDcClipper dummy3(dc, cellRect);
- prov->renderCell(dc, cellRect, row, cw.type, renderAsEnabled(*this), drawAsSelected(row), getRowHoverToDraw(row));
+ prov->renderCell(dc, cellRect, row, cw.type, enabled, drawAsSelected(row), getRowHoverToDraw(row));
}
cellAreaTL.x += cw.width;
}
@@ -1488,10 +1491,10 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size)
//2. try(!) to determine scrollbar sizes:
#if GTK_MAJOR_VERSION == 2
- /* Ubuntu 19.10: "scrollbar-spacing" has a default value of 3: https://developer.gnome.org/gtk2/stable/GtkScrolledWindow.html#GtkScrolledWindow--s-scrollbar-spacing
- => the default Ubuntu theme (but also our Gtk2Styles.rc) set it to 0, but still the first call to gtk_widget_style_get() returns 3: why?
- => maybe styles are applied asynchronously? GetClientSize() is affected by this, so can't use!
- => always ignore spacing to get consistent scrollbar dimensions! */
+ /* Ubuntu 19.10: "scrollbar-spacing" has a default value of 3: https://developer.gnome.org/gtk2/stable/GtkScrolledWindow.html#GtkScrolledWindow--s-scrollbar-spacing
+ => the default Ubuntu theme (but also our Gtk2Styles.rc) set it to 0, but still the first call to gtk_widget_style_get() returns 3: why?
+ => maybe styles are applied asynchronously? GetClientSize() is affected by this, so can't use!
+ => always ignore spacing to get consistent scrollbar dimensions! */
GtkScrolledWindow* scrollWin = GTK_SCROLLED_WINDOW(wxWindow::m_widget);
assert(scrollWin);
GtkWidget* rangeH = ::gtk_scrolled_window_get_hscrollbar(scrollWin);
@@ -1509,9 +1512,9 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size)
assert(scrollBarWidthV_ == 0 || scrollBarWidthV_ == scrollBarSizeTmp.x);
#elif GTK_MAJOR_VERSION == 3
- //scrollbar size increases dynamically on mouse-hover!
- //see "overlay scrolling": https://developer.gnome.org/gtk3/stable/GtkScrolledWindow.html#gtk-scrolled-window-set-overlay-scrolling
- //luckily "scrollbar-spacing" is stable on GTK3
+ //scrollbar size increases dynamically on mouse-hover!
+ //see "overlay scrolling": https://developer.gnome.org/gtk3/stable/GtkScrolledWindow.html#gtk-scrolled-window-set-overlay-scrolling
+ //luckily "scrollbar-spacing" is stable on GTK3
const wxSize scrollBarSizeTmp = GetSize() - GetClientSize();
assert(scrollBarSizeTmp.x == 0 || scrollBarSizeTmp.x == 6 || scrollBarSizeTmp.x == 13); //lame hard-coded numbers (from Ubuntu 19.10)
@@ -1522,7 +1525,7 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size)
scrollBarHeightH_ = std::max(scrollBarHeightH_, scrollBarSizeTmp.y);
scrollBarWidthV_ = std::max(scrollBarWidthV_, scrollBarSizeTmp.x);
//this function is called again by wxScrollHelper::AdjustScrollbars() if SB_SHOW_ALWAYS-scrollbars are not yet shown => scrollbar size > 0 eventually!
-
+
//-----------------------------------------------------------------------------
//harmonize with Grid::updateWindowSizes()!
wxSize sizeAvail = size - wxSize(rowLabelWidth, colLabelHeight_);
@@ -1904,7 +1907,7 @@ void Grid::showScrollBars(Grid::ScrollBarStatus horizontal, Grid::ScrollBarStatu
assert(false);
return GTK_POLICY_AUTOMATIC;
};
-
+
GtkScrolledWindow* scrollWin = GTK_SCROLLED_WINDOW(wxWindow::m_widget);
assert(scrollWin);
::gtk_scrolled_window_set_policy(scrollWin,
diff --git a/wx+/grid.h b/wx+/grid.h
index 74dc25b2..662c4fc1 100644
--- a/wx+/grid.h
+++ b/wx+/grid.h
@@ -115,7 +115,7 @@ public:
//label area:
virtual std::wstring getColumnLabel(ColumnType colType) const = 0;
- virtual void renderColumnLabel(Grid& grid, wxDC& dc, const wxRect& rect, ColumnType colType, bool highlighted); //default implementation
+ virtual void renderColumnLabel(wxDC& dc, const wxRect& rect, ColumnType colType, bool enabled, bool highlighted); //default implementation
virtual std::wstring getToolTip(ColumnType colType) const { return std::wstring(); }
static int getColumnGapLeft(); //for left-aligned text
@@ -128,7 +128,7 @@ public:
static void drawCellBackground(wxDC& dc, const wxRect& rect, bool enabled, bool selected, const wxColor& backgroundColor);
static wxRect drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool highlighted); //returns inner rectangle
- static void drawColumnLabelText (wxDC& dc, const wxRect& rect, const std::wstring& text);
+ static void drawColumnLabelText (wxDC& dc, const wxRect& rect, const std::wstring& text, bool enabled);
};
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index 91189ba6..2a3b7039 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -12,6 +12,7 @@
#include <zen/perf.h>
#include <zen/thread.h>
#include <zen/file_io.h>
+#include <zen/file_traverser.h>
#include <wx/zipstrm.h>
#include <wx/mstream.h>
#include <wx/image.h>
@@ -182,63 +183,81 @@ private:
};
-void GlobalBitmaps::init(const Zstring& filePath)
+void GlobalBitmaps::init(const Zstring& zipPath)
{
assert(bitmaps_.empty() && anims_.empty());
- //wxFFileInputStream/wxZipInputStream loads in junks of 512 bytes => WTF!!! => implement sane file loading:
- try
+ std::vector<std::pair<Zstring /*file name*/, std::string /*byte stream*/>> streams;
+
+ try //to load from ZIP first:
+ {
+ //wxFFileInputStream/wxZipInputStream loads in junks of 512 bytes => WTF!!! => implement sane file loading:
+ const std::string rawStream = loadBinContainer<std::string>(zipPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership
+ wxZipInputStream zipStream(memStream, wxConvUTF8);
+ //do NOT rely on wxConvLocal! On failure shows unhelpful popup "Cannot convert from the charset 'Unknown encoding (-1)'!"
+
+ while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!
+ if (std::string stream(entry->GetSize(), '\0'); !stream.empty() && zipStream.ReadAll(&stream[0], stream.size()))
+ streams.emplace_back(utfTo<Zstring>(entry->GetName()), std::move(stream));
+ else
+ assert(false);
+ }
+ catch (FileError&) //fall back to folder
+ {
+ traverseFolder(beforeLast(zipPath, Zstr(".zip"), IF_MISSING_RETURN_NONE), [&](const FileInfo& fi)
+ {
+ if (endsWith(fi.fullPath, Zstr(".png")))
+ try
+ {
+ std::string stream = loadBinContainer<std::string>(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ streams.emplace_back(fi.itemName, std::move(stream));
+ }
+ catch (FileError&) { assert(false); }
+ }, nullptr, nullptr, [](const std::wstring& errorMsg) { assert(false); }); //errors are not really critical in this context
+ }
+ //--------------------------------------------------------------------
+
+ //activate support for .png files
+ wxImage::AddHandler(new wxPNGHandler); //ownership passed
+
+ //do we need xBRZ scaling for high quality DPI images?
+ const int hqScale = std::clamp<int>(std::ceil(fastFromDIP(1000) / 1000.0), 1, xbrz::SCALE_FACTOR_MAX);
+ //even for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"!
+ if (hqScale > 1)
+ dpiScaler_ = std::make_unique<DpiParallelScaler>(hqScale);
+
+ for (const auto& [fileName, stream] : streams)
{
- const std::string rawStream = loadBinContainer<std::string>(filePath, nullptr /*notifyUnbufferedIO*/); //throw FileError
- wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership
- wxZipInputStream zipStream(memStream, wxConvUTF8);
- //do NOT rely on wxConvLocal! On failure shows unhelpful popup "Cannot convert from the charset 'Unknown encoding (-1)'!"
-
- //activate support for .png files
- wxImage::AddHandler(new wxPNGHandler); //ownership passed
-
- //do we need xBRZ scaling for high quality DPI images?
- const int hqScale = std::clamp<int>(std::ceil(fastFromDIP(1000) / 1000.0), 1, xbrz::SCALE_FACTOR_MAX);
- //even for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"!
- if (hqScale > 1)
- dpiScaler_ = std::make_unique<DpiParallelScaler>(hqScale);
-
- while (const auto& entry = std::unique_ptr<wxZipEntry>(zipStream.GetNextEntry())) //take ownership!)
- {
- const wxString name = entry->GetName();
-
- if (endsWith(name, L".png"))
- {
- wxImage img(zipStream, wxBITMAP_TYPE_PNG);
- assert(img.IsOk());
-
- //end this alpha/no-alpha/mask/wxDC::DrawBitmap/RTL/high-contrast-scheme interoperability nightmare here and now!!!!
- //=> there's only one type of wxImage: with alpha channel, no mask!!!
- convertToVanillaImage(img);
-
- if (dpiScaler_)
- dpiScaler_->add(name, img); //scale in parallel!
- else
- bitmaps_.emplace(name, img);
- }
- else if (endsWith(name, L".gif"))
- {
- //work around wxWidgets bug: wxAnimation::Load() requires seekable input stream (zip-input stream is not seekable)
- std::string stream(entry->GetSize(), '\0');
- if (!stream.empty() && zipStream.ReadAll(&stream[0], stream.size()))
- {
- wxMemoryInputStream seekAbleStream(stream.c_str(), stream.size()); //stream does not take ownership of data
- [[maybe_unused]] const bool loadSuccess = anims_[name].Load(seekAbleStream, wxANIMATION_TYPE_GIF);
- assert(loadSuccess);
- }
- else
- assert(false);
- }
- else
- assert(false);
- }
+ const wxString& name = utfTo<wxString>(afterLast(fileName, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL));
+
+ wxMemoryInputStream wxstream(stream.c_str(), stream.size()); //stream does not take ownership of data
+ //bonus: work around wxWidgets bug: wxAnimation::Load() requires seekable input stream (zip-input stream is not seekable)
+
+ if (endsWith(name, L".png"))
+ {
+ wxImage img(wxstream, wxBITMAP_TYPE_PNG);
+ assert(img.IsOk());
+
+ //end this alpha/no-alpha/mask/wxDC::DrawBitmap/RTL/high-contrast-scheme interoperability nightmare here and now!!!!
+ //=> there's only one type of wxImage: with alpha channel, no mask!!!
+ convertToVanillaImage(img);
+
+ if (dpiScaler_)
+ dpiScaler_->add(name, img); //scale in parallel!
+ else
+ bitmaps_.emplace(name, img);
+ }
+#if 0
+ else if (endsWith(name, L".gif"))
+ {
+ [[maybe_unused]] const bool loadSuccess = anims_[name].Load(wxstream, wxANIMATION_TYPE_GIF);
+ assert(loadSuccess);
+ }
+#endif
+ else
+ assert(false);
}
- catch (FileError&) { assert(false); }
}
@@ -272,10 +291,10 @@ const wxAnimation& GlobalBitmaps::getAnimation(const wxString& name) const
}
-void zen::initResourceImages(const Zstring& filepath)
+void zen::initResourceImages(const Zstring& zipPath)
{
if (std::shared_ptr<GlobalBitmaps> inst = GlobalBitmaps::instance())
- inst->init(filepath);
+ inst->init(zipPath);
else
assert(false);
}
diff --git a/wx+/image_resources.h b/wx+/image_resources.h
index 5ea56679..ff1d5648 100644
--- a/wx+/image_resources.h
+++ b/wx+/image_resources.h
@@ -14,7 +14,7 @@
namespace zen
{
-void initResourceImages(const Zstring& filePath); //pass resources .zip file at application startup
+void initResourceImages(const Zstring& zipPath); //pass resources .zip file at application startup
void cleanupResourceImages();
const wxBitmap& getResourceImage (const wxString& name);
diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp
index 0f248057..8f94d1bc 100644
--- a/wx+/image_tools.cpp
+++ b/wx+/image_tools.cpp
@@ -72,7 +72,7 @@ wxImage zen::stackImages(const wxImage& img1, const wxImage& img2, ImageStackLay
int width = std::max(img1Width, img2Width);
int height = std::max(img1Height, img2Height);
- if (dir == ImageStackLayout::HORIZONTAL)
+ if (dir == ImageStackLayout::horizontal)
width = img1Width + gap + img2Width;
else
height = img1Height + gap + img2Height;
@@ -85,11 +85,11 @@ wxImage zen::stackImages(const wxImage& img1, const wxImage& img2, ImageStackLay
{
switch (align)
{
- case ImageStackAlignment::CENTER:
+ case ImageStackAlignment::center:
return static_cast<int>(std::floor((totalExtent - imageExtent) / 2.0)); //consistency: round down negative values, too!
- case ImageStackAlignment::LEFT:
+ case ImageStackAlignment::left:
return 0;
- case ImageStackAlignment::RIGHT:
+ case ImageStackAlignment::right:
return totalExtent - imageExtent;
}
assert(false);
@@ -98,12 +98,12 @@ wxImage zen::stackImages(const wxImage& img1, const wxImage& img2, ImageStackLay
switch (dir)
{
- case ImageStackLayout::HORIZONTAL:
+ case ImageStackLayout::horizontal:
writeToImage(output, img1, wxPoint(0, calcPos(img1Height, height)));
writeToImage(output, img2, wxPoint(img1Width + gap, calcPos(img2Height, height)));
break;
- case ImageStackLayout::VERTICAL:
+ case ImageStackLayout::vertical:
writeToImage(output, img1, wxPoint(calcPos(img1Width, width), 0));
writeToImage(output, img2, wxPoint(calcPos(img2Width, width), img1Height + gap));
break;
@@ -165,13 +165,13 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const
if (!lineText.empty())
switch (textAlign)
{
- case ImageStackAlignment::LEFT:
+ case ImageStackAlignment::left:
dc.DrawText(lineText, wxPoint(0, posY));
break;
- case ImageStackAlignment::RIGHT:
+ case ImageStackAlignment::right:
dc.DrawText(lineText, wxPoint(maxWidth - lineSize.GetWidth(), posY));
break;
- case ImageStackAlignment::CENTER:
+ case ImageStackAlignment::center:
dc.DrawText(lineText, wxPoint((maxWidth - lineSize.GetWidth()) / 2, posY));
break;
}
@@ -191,7 +191,7 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const
for (int i = 0; i < pixelCount; ++i)
{
//black(0,0,0) becomes wxIMAGE_ALPHA_OPAQUE(255), while white(255,255,255) becomes wxIMAGE_ALPHA_TRANSPARENT(0)
- *alpha++ = static_cast<unsigned char>((255 - rgb[0] + 255 - rgb[1] + 255 - rgb[2]) / 3); //mixed mode arithmetics!
+ *alpha++ = static_cast<unsigned char>((255 - rgb[0] + 255 - rgb[1] + 255 - rgb[2]) / 3); //mixed-mode arithmetics!
rgb[0] = col.Red (); //
rgb[1] = col.Green(); //apply actual text color
@@ -211,7 +211,7 @@ wxImage zen::layOver(const wxImage& back, const wxImage& front, int alignment)
const int width = std::max(back.GetWidth(), front.GetWidth());
const int height = std::max(back.GetHeight(), front.GetHeight());
- const int offsetX = [&]
+ const int offsetX = [&]
{
if (alignment & wxALIGN_RIGHT)
return back.GetWidth() - front.GetWidth();
@@ -239,7 +239,7 @@ wxImage zen::layOver(const wxImage& back, const wxImage& front, int alignment)
::memset(output.GetAlpha(), wxIMAGE_ALPHA_TRANSPARENT, width * height);
const wxPoint posBack(std::max(-offsetX, 0), std::max(-offsetY, 0));
- writeToImage(output, back , posBack);
+ writeToImage(output, back, posBack);
writeToImage(output, front, posBack + wxPoint(offsetX, offsetY));
return output;
}
diff --git a/wx+/image_tools.h b/wx+/image_tools.h
index d72597ef..e2d42fb0 100644
--- a/wx+/image_tools.h
+++ b/wx+/image_tools.h
@@ -18,25 +18,25 @@ namespace zen
{
enum class ImageStackLayout
{
- HORIZONTAL,
- VERTICAL
+ horizontal,
+ vertical
};
enum class ImageStackAlignment //one-dimensional unlike wxAlignment
{
- CENTER,
- LEFT,
- RIGHT,
- TOP = LEFT,
- BOTTOM = RIGHT,
+ center,
+ left,
+ right,
+ top = left,
+ bottom = right,
};
wxImage stackImages(const wxImage& img1, const wxImage& img2, ImageStackLayout dir, ImageStackAlignment align, int gap = 0);
-wxImage createImageFromText(const wxString& text, const wxFont& font, const wxColor& col, ImageStackAlignment textAlign = ImageStackAlignment::LEFT); //CENTER/LEFT/RIGHT
+wxImage createImageFromText(const wxString& text, const wxFont& font, const wxColor& col, ImageStackAlignment textAlign = ImageStackAlignment::left); //center/left/right
wxImage layOver(const wxImage& back, const wxImage& front, int alignment = wxALIGN_CENTER);
-wxImage greyScale(const wxImage& img); //greyscale + brightness adaption
+wxImage greyScale(const wxImage& img); //greyscale + brightness adaption
wxBitmap greyScale(const wxBitmap& bmp); //
//void moveImage(wxImage& img, int right, int up);
@@ -44,8 +44,6 @@ void adjustBrightness(wxImage& img, int targetLevel);
double getAvgBrightness(const wxImage& img); //in [0, 255]
void brighten(wxImage& img, int level); //level: delta per channel in points
-bool isEqual(const wxBitmap& lhs, const wxBitmap& rhs); //pixel-wise equality (respecting alpha channel)
-
void convertToVanillaImage(wxImage& img); //add alpha channel if missing + remove mask if existing
//wxColor gradient(const wxColor& from, const wxColor& to, double fraction); //maps fraction within [0, 1] to an intermediate color
@@ -153,36 +151,6 @@ void adjustBrightness(wxImage& img, int targetLevel)
inline
-bool isEqual(const wxBitmap& lhs, const wxBitmap& rhs)
-{
- if (lhs.IsOk() != rhs.IsOk())
- return false;
- if (!lhs.IsOk())
- return true;
-
- if (lhs.GetSize() != rhs.GetSize())
- return false;
-
- wxImage imLhs = lhs.ConvertToImage();
- wxImage imRhs = rhs.ConvertToImage();
-
- if (imLhs.HasAlpha() != imRhs.HasAlpha())
- return false;
-
- const int pixelCount = lhs.GetWidth() * lhs.GetHeight();
-
- if (!std::equal(imLhs.GetData(), imLhs.GetData() + pixelCount * 3, imRhs.GetData()))
- return false;
-
- if (imLhs.HasAlpha())
- if (!std::equal(imLhs.GetAlpha(), imLhs.GetAlpha() + pixelCount, imRhs.GetAlpha()))
- return false;
-
- return true;
-}
-
-
-inline
wxImage shrinkImage(const wxImage& img, int requestedSize)
{
const int maxExtent = std::max(img.GetWidth(), img.GetHeight());
diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp
index 3e490757..af43c85b 100644
--- a/wx+/popup_dlg_generated.cpp
+++ b/wx+/popup_dlg_generated.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -39,7 +39,7 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
bSizer16->Add( 0, 5, 0, 0, 5 );
- m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 );
@@ -63,6 +63,7 @@ PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, con
bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
m_buttonAccept = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+
m_buttonAccept->SetDefault();
bSizerStdButtons->Add( m_buttonAccept, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h
index 9d9bc3f8..2b09289b 100644
--- a/wx+/popup_dlg_generated.h
+++ b/wx+/popup_dlg_generated.h
@@ -1,12 +1,11 @@
///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version May 29 2018)
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
-#ifndef __POPUP_DLG_GENERATED_H__
-#define __POPUP_DLG_GENERATED_H__
+#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
@@ -70,4 +69,3 @@ public:
};
-#endif //__POPUP_DLG_GENERATED_H__
diff --git a/wx+/rtl.h b/wx+/rtl.h
index 0adb6037..3ab701a7 100644
--- a/wx+/rtl.h
+++ b/wx+/rtl.h
@@ -94,13 +94,14 @@ void drawBitmapRtlNoMirror(wxDC& dc, const wxBitmap& bmp, const wxRect& rect, in
}
-inline
+inline
wxImage mirrorIfRtl(const wxImage& bmp)
{
if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft)
return bmp.Mirror();
else
- return bmp;}
+ return bmp;
+}
inline
diff --git a/wx+/std_button_layout.h b/wx+/std_button_layout.h
index cf0152de..d2c5fc32 100644
--- a/wx+/std_button_layout.h
+++ b/wx+/std_button_layout.h
@@ -83,7 +83,7 @@ void setStandardButtonLayout(wxBoxSizer& sizer, const StdButtons& buttons)
{
assert(btn->GetMinSize().GetHeight() == -1); //let OS or this routine do the sizing! note: OS X does not allow changing the (visible!) button height!
const int defaultHeight = wxButton::GetDefaultSize().GetHeight(); //buffered by wxWidgets
- btn->SetMinSize(wxSize(-1, std::max(defaultHeight, fastFromDIP(30)))); //default button height is much too small => increase!
+ btn->SetMinSize({-1, std::max(defaultHeight, fastFromDIP(31))}); //default button height is much too small => increase!
if (settingFirstButton)
settingFirstButton = false;
diff --git a/wx+/tooltip.cpp b/wx+/tooltip.cpp
index 42fb058a..0beef0bf 100644
--- a/wx+/tooltip.cpp
+++ b/wx+/tooltip.cpp
@@ -61,7 +61,7 @@ void Tooltip::show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp)
const wxBitmap& newBmp = bmp ? *bmp : wxNullBitmap;
- if (!isEqual(tipWindow_->bitmapLeft_->GetBitmap(), newBmp))
+ if (!tipWindow_->bitmapLeft_->GetBitmap().IsSameAs(newBmp))
{
tipWindow_->bitmapLeft_->SetBitmap(newBmp);
tipWindow_->Refresh(); //needed if bitmap size changed!
diff --git a/xBRZ/src/xbrz.cpp b/xBRZ/src/xbrz.cpp
index 0bf9db17..5228073f 100644
--- a/xBRZ/src/xbrz.cpp
+++ b/xBRZ/src/xbrz.cpp
@@ -246,24 +246,32 @@ struct BlendResult
};
+struct Kernel_3x3
+{
+ uint32_t
+ a, b, c,
+ d, e, f,
+ g, h, i;
+};
+
struct Kernel_4x4 //kernel for preprocessing step
{
uint32_t
- /**/a, b, c, d,
- /**/e, f, g, h,
- /**/i, j, k, l,
- /**/m, n, o, p;
+ a, b, c, //
+ e, f, g, // support reinterpret_cast from Kernel_4x4 => Kernel_3x3
+ i, j, k, //
+ m, n, o,
+ d, h, l, p;
};
-/*
-input kernel area naming convention:
+/* input kernel area naming convention:
-----------------
| A | B | C | D |
-----|---|---|---|
-| E | F | G | H | //evaluate the four corners between F, G, J, K
-----|---|---|---| //input pixel is at position F
+|---|---|---|---|
+| E | F | G | H | evaluate the four corners between F, G, J, K
+|---|---|---|---| input pixel is at position F
| I | J | K | L |
-----|---|---|---|
+|---|---|---|---|
| M | N | O | P |
-----------------
*/
@@ -306,14 +314,6 @@ BlendResult preProcessCorners(const Kernel_4x4& ker, const xbrz::ScalerCfg& cfg)
return result;
}
-struct Kernel_3x3
-{
- uint32_t
- /**/a, b, c,
- /**/d, e, f,
- /**/g, h, i;
-};
-
#define DEF_GETTER(x) template <RotationDegree rotDeg> uint32_t inline get_##x(const Kernel_3x3& ker) { return ker.x; }
//we cannot and NEED NOT write "ker.##x" since ## concatenates preprocessor tokens but "." is not a token
DEF_GETTER(a) DEF_GETTER(b) DEF_GETTER(c)
@@ -346,12 +346,16 @@ inline BlendType getTopR (unsigned char b) { return static_cast<BlendType>(0x3
inline BlendType getBottomR(unsigned char b) { return static_cast<BlendType>(0x3 & (b >> 4)); }
inline BlendType getBottomL(unsigned char b) { return static_cast<BlendType>(0x3 & (b >> 6)); }
-inline void setTopL (unsigned char& b, BlendType bt) { b |= bt; } //buffer is assumed to be initialized before preprocessing!
-inline void setTopR (unsigned char& b, BlendType bt) { b |= (bt << 2); }
-inline void setBottomR(unsigned char& b, BlendType bt) { b |= (bt << 4); }
-inline void setBottomL(unsigned char& b, BlendType bt) { b |= (bt << 6); }
+inline void clearAddTopL(unsigned char& b, BlendType bt) { b = static_cast<unsigned char>(bt); }
+inline void addTopR (unsigned char& b, BlendType bt) { b |= (bt << 2); } //buffer is assumed to be initialized before preprocessing!
+inline void addBottomR (unsigned char& b, BlendType bt) { b |= (bt << 4); } //e.g. via clearAddTopL()
+inline void addBottomL (unsigned char& b, BlendType bt) { b |= (bt << 6); } //
-inline bool blendingNeeded(unsigned char b) { return b != 0; }
+inline bool blendingNeeded(unsigned char b)
+{
+ static_assert(BLEND_NONE == 0);
+ return b != 0;
+}
template <RotationDegree rotDeg> inline
unsigned char rotateBlendInfo(unsigned char b) { return b; }
@@ -360,13 +364,12 @@ template <> inline unsigned char rotateBlendInfo<ROT_180>(unsigned char b) { ret
template <> inline unsigned char rotateBlendInfo<ROT_270>(unsigned char b) { return ((b << 6) | (b >> 2)) & 0xff; }
-/*
-input kernel area naming convention:
+/* input kernel area naming convention:
-------------
| A | B | C |
-----|---|---|
-| D | E | F | //input pixel is at position E
-----|---|---|
+|---|---|---|
+| D | E | F | input pixel is at position E
+|---|---|---|
| G | H | I |
-------------
*/
@@ -456,7 +459,72 @@ void blendPixel(const Kernel_3x3& ker,
}
-template <class Scaler, class ColorDistance> //scaler policy: see "Scaler2x" reference implementation
+class OobReaderTransparent
+{
+public:
+ OobReaderTransparent(const uint32_t* src, int srcWidth, int srcHeight, int y) :
+ s_m1(0 <= y - 1 && y - 1 < srcHeight ? src + srcWidth * (y - 1) : nullptr),
+ s_0 (0 <= y && y < srcHeight ? src + srcWidth * y : nullptr),
+ s_p1(0 <= y + 1 && y + 1 < srcHeight ? src + srcWidth * (y + 1) : nullptr),
+ s_p2(0 <= y + 2 && y + 2 < srcHeight ? src + srcWidth * (y + 2) : nullptr),
+ srcWidth_(srcWidth) {}
+
+ void readDhlp(Kernel_4x4& ker, int x) const //(x, y) is at kernel position F
+ {
+ [[likely]] if (const int x_p2 = x + 2; 0 <= x_p2 && x_p2 < srcWidth_)
+ {
+ ker.d = s_m1 ? s_m1[x_p2] : 0;
+ ker.h = s_0 ? s_0 [x_p2] : 0;
+ ker.l = s_p1 ? s_p1[x_p2] : 0;
+ ker.p = s_p2 ? s_p2[x_p2] : 0;
+ }
+ else
+ {
+ ker.d = 0;
+ ker.h = 0;
+ ker.l = 0;
+ ker.p = 0;
+ }
+ }
+
+private:
+ const uint32_t* const s_m1;
+ const uint32_t* const s_0;
+ const uint32_t* const s_p1;
+ const uint32_t* const s_p2;
+ const int srcWidth_;
+};
+
+
+class OobReaderDuplicate
+{
+public:
+ OobReaderDuplicate(const uint32_t* src, int srcWidth, int srcHeight, int y) :
+ s_m1(src + srcWidth * std::clamp(y - 1, 0, srcHeight - 1)),
+ s_0 (src + srcWidth * std::clamp(y, 0, srcHeight - 1)),
+ s_p1(src + srcWidth * std::clamp(y + 1, 0, srcHeight - 1)),
+ s_p2(src + srcWidth * std::clamp(y + 2, 0, srcHeight - 1)),
+ srcWidth_(srcWidth) {}
+
+ void readDhlp(Kernel_4x4& ker, int x) const //(x, y) is at kernel position F
+ {
+ const int x_p2 = std::clamp(x + 2, 0, srcWidth_ - 1);
+ ker.d = s_m1[x_p2];
+ ker.h = s_0 [x_p2];
+ ker.l = s_p1[x_p2];
+ ker.p = s_p2[x_p2];
+ }
+
+private:
+ const uint32_t* const s_m1;
+ const uint32_t* const s_0;
+ const uint32_t* const s_p1;
+ const uint32_t* const s_p2;
+ const int srcWidth_;
+};
+
+
+template <class Scaler, class ColorDistance, class OobReader> //scaler policy: see "Scaler2x" reference implementation
void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast)
{
yFirst = std::max(yFirst, 0);
@@ -466,64 +534,72 @@ void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
const int trgWidth = srcWidth * Scaler::scale;
- //"use" space at the end of the image as temporary buffer for "on the fly preprocessing": we even could use larger area of
- //"sizeof(uint32_t) * srcWidth * (yLast - yFirst)" bytes without risk of accidental overwriting before accessing
- const int bufferSize = srcWidth;
- unsigned char* preProcBuffer = reinterpret_cast<unsigned char*>(trg + yLast * Scaler::scale * trgWidth) - bufferSize;
- std::fill(preProcBuffer, preProcBuffer + bufferSize, '\0');
- static_assert(BLEND_NONE == 0);
+ //(ab)use space of "sizeof(uint32_t) * srcWidth * Scaler::scale" at the end of the image as temporary
+ //buffer for "on the fly preprocessing" without risk of accidental overwriting before accessing
+ unsigned char* const preProcBuf = reinterpret_cast<unsigned char*>(trg + yLast * Scaler::scale * trgWidth) - srcWidth;
//initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending
//this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition!
- if (yFirst > 0)
{
- const int y = yFirst - 1;
+ const OobReader oobReader(src, srcWidth, srcHeight, yFirst - 1);
+
+ //initialize at position x = -1
+ Kernel_4x4 ker4 = {};
+ oobReader.readDhlp(ker4, -4); //hack: read a, e, i, m at x = -1
+ ker4.a = ker4.d;
+ ker4.e = ker4.h;
+ ker4.i = ker4.l;
+ ker4.m = ker4.p;
+
+ oobReader.readDhlp(ker4, -3);
+ ker4.b = ker4.d;
+ ker4.f = ker4.h;
+ ker4.j = ker4.l;
+ ker4.n = ker4.p;
+
+ oobReader.readDhlp(ker4, -2);
+ ker4.c = ker4.d;
+ ker4.g = ker4.h;
+ ker4.k = ker4.l;
+ ker4.o = ker4.p;
+
+ oobReader.readDhlp(ker4, -1);
- const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);
- const uint32_t* s_0 = src + srcWidth * y; //center line
- const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);
- const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);
+ {
+ const BlendResult res = preProcessCorners<ColorDistance>(ker4, cfg);
+ clearAddTopL(preProcBuf[0], res.blend_k); //set 1st known corner for (0, yFirst)
+ }
for (int x = 0; x < srcWidth; ++x)
{
- const int x_m1 = std::max(x - 1, 0);
- const int x_p1 = std::min(x + 1, srcWidth - 1);
- const int x_p2 = std::min(x + 2, srcWidth - 1);
-
- Kernel_4x4 ker = {}; //perf: initialization is negligible
- ker.a = s_m1[x_m1]; //read sequentially from memory as far as possible
- ker.b = s_m1[x];
- ker.c = s_m1[x_p1];
- ker.d = s_m1[x_p2];
-
- ker.e = s_0[x_m1];
- ker.f = s_0[x];
- ker.g = s_0[x_p1];
- ker.h = s_0[x_p2];
-
- ker.i = s_p1[x_m1];
- ker.j = s_p1[x];
- ker.k = s_p1[x_p1];
- ker.l = s_p1[x_p2];
-
- ker.m = s_p2[x_m1];
- ker.n = s_p2[x];
- ker.o = s_p2[x_p1];
- ker.p = s_p2[x_p2];
-
- const BlendResult res = preProcessCorners<ColorDistance>(ker, cfg);
- /*
- preprocessing blend result:
- ---------
- | F | G | //evalute corner between F, G, J, K
- ----|---| //input pixel is at position F
- | J | K |
- ---------
- */
- setTopR(preProcBuffer[x], res.blend_j);
+ ker4.a = ker4.b; //shift previous kernel to the left
+ ker4.e = ker4.f; // -----------------
+ ker4.i = ker4.j; // | A | B | C | D |
+ ker4.m = ker4.n; // |---|---|---|---|
+ /**/ // | E | F | G | H | (x, yFirst - 1) is at position F
+ ker4.b = ker4.c; // |---|---|---|---|
+ ker4.f = ker4.g; // | I | J | K | L |
+ ker4.j = ker4.k; // |---|---|---|---|
+ ker4.n = ker4.o; // | M | N | O | P |
+ /**/ // -----------------
+ ker4.c = ker4.d;
+ ker4.g = ker4.h;
+ ker4.k = ker4.l;
+ ker4.o = ker4.p;
+
+ oobReader.readDhlp(ker4, x);
+
+ /* preprocessing blend result:
+ ---------
+ | F | G | evaluate corner between F, G, J, K
+ |---+---| current input pixel is at position F
+ | J | K |
+ --------- */
+ const BlendResult res = preProcessCorners<ColorDistance>(ker4, cfg);
+ addTopR(preProcBuf[x], res.blend_j); //set 2nd known corner for (x, yFirst)
- if (x + 1 < bufferSize)
- setTopL(preProcBuffer[x + 1], res.blend_k);
+ if (x + 1 < srcWidth)
+ clearAddTopL(preProcBuf[x + 1], res.blend_k); //set 1st known corner for (x + 1, yFirst)
}
}
//------------------------------------------------------------------------------------
@@ -532,88 +608,89 @@ void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
{
uint32_t* out = trg + Scaler::scale * y * trgWidth; //consider MT "striped" access
- const uint32_t* s_m1 = src + srcWidth * std::max(y - 1, 0);
- const uint32_t* s_0 = src + srcWidth * y; //center line
- const uint32_t* s_p1 = src + srcWidth * std::min(y + 1, srcHeight - 1);
- const uint32_t* s_p2 = src + srcWidth * std::min(y + 2, srcHeight - 1);
+ const OobReader oobReader(src, srcWidth, srcHeight, y);
- unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position
+ //initialize at position x = -1
+ Kernel_4x4 ker4 = {};
+ oobReader.readDhlp(ker4, -4); //hack: read a, e, i, m at x = -1
+ ker4.a = ker4.d;
+ ker4.e = ker4.h;
+ ker4.i = ker4.l;
+ ker4.m = ker4.p;
- for (int x = 0; x < srcWidth; ++x, out += Scaler::scale)
- {
- //all those bounds checks have only insignificant impact on performance!
- const int x_m1 = std::max(x - 1, 0); //perf: prefer array indexing to additional pointers!
- const int x_p1 = std::min(x + 1, srcWidth - 1);
- const int x_p2 = std::min(x + 2, srcWidth - 1);
+ oobReader.readDhlp(ker4, -3);
+ ker4.b = ker4.d;
+ ker4.f = ker4.h;
+ ker4.j = ker4.l;
+ ker4.n = ker4.p;
- Kernel_4x4 ker4 = {}; //perf: initialization is negligible
+ oobReader.readDhlp(ker4, -2);
+ ker4.c = ker4.d;
+ ker4.g = ker4.h;
+ ker4.k = ker4.l;
+ ker4.o = ker4.p;
- ker4.a = s_m1[x_m1]; //read sequentially from memory as far as possible
- ker4.b = s_m1[x];
- ker4.c = s_m1[x_p1];
- ker4.d = s_m1[x_p2];
+ oobReader.readDhlp(ker4, -1);
- ker4.e = s_0[x_m1];
- ker4.f = s_0[x];
- ker4.g = s_0[x_p1];
- ker4.h = s_0[x_p2];
+ unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position
+ {
+ const BlendResult res = preProcessCorners<ColorDistance>(ker4, cfg);
+ clearAddTopL(blend_xy1, res.blend_k); //set 1st known corner for (0, y + 1) and buffer for use on next column
- ker4.i = s_p1[x_m1];
- ker4.j = s_p1[x];
- ker4.k = s_p1[x_p1];
- ker4.l = s_p1[x_p2];
+ addBottomL(preProcBuf[0], res.blend_g); //set 3rd known corner for (0, y)
+ }
- ker4.m = s_p2[x_m1];
- ker4.n = s_p2[x];
- ker4.o = s_p2[x_p1];
- ker4.p = s_p2[x_p2];
+ for (int x = 0; x < srcWidth; ++x, out += Scaler::scale)
+ {
+ ker4.a = ker4.b; //shift previous kernel to the left
+ ker4.e = ker4.f; // -----------------
+ ker4.i = ker4.j; // | A | B | C | D |
+ ker4.m = ker4.n; // |---|---|---|---|
+ /**/ // | E | F | G | H | (x, y) is at position F
+ ker4.b = ker4.c; // |---|---|---|---|
+ ker4.f = ker4.g; // | I | J | K | L |
+ ker4.j = ker4.k; // |---|---|---|---|
+ ker4.n = ker4.o; // | M | N | O | P |
+ /**/ // -----------------
+ ker4.c = ker4.d;
+ ker4.g = ker4.h;
+ ker4.k = ker4.l;
+ ker4.o = ker4.p;
+
+ oobReader.readDhlp(ker4, x);
//evaluate the four corners on bottom-right of current pixel
- unsigned char blend_xy = 0; //for current (x, y) position
+ unsigned char blend_xy = preProcBuf[x]; //for current (x, y) position
{
+ /* preprocessing blend result:
+ ---------
+ | F | G | evaluate corner between F, G, J, K
+ |---+---| current input pixel is at position F
+ | J | K |
+ --------- */
const BlendResult res = preProcessCorners<ColorDistance>(ker4, cfg);
- /*
- preprocessing blend result:
- ---------
- | F | G | //evalute corner between F, G, J, K
- ----|---| //current input pixel is at position F
- | J | K |
- ---------
- */
- blend_xy = preProcBuffer[x];
- setBottomR(blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence!
+ addBottomR(blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence!
- setTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1)
- preProcBuffer[x] = blend_xy1; //store on current buffer position for use on next row
+ addTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1)
+ preProcBuf[x] = blend_xy1; //store on current buffer position for use on next row
- blend_xy1 = 0;
- setTopL(blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column
+ [[likely]] if (x + 1 < srcWidth)
+ {
+ //blend_xy1 -> blend_x1y1
+ clearAddTopL(blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column
- if (x + 1 < bufferSize) //set 3rd known corner for (x + 1, y)
- setBottomL(preProcBuffer[x + 1], res.blend_g);
+ addBottomL(preProcBuf[x + 1], res.blend_g); //set 3rd known corner for (x + 1, y)
+ }
}
//fill block of size scale * scale with the given color
fillBlock(out, trgWidth * sizeof(uint32_t), ker4.f, Scaler::scale, Scaler::scale);
- //place *after* preprocessing step, to not overwrite the results while processing the the last pixel!
+ //place *after* preprocessing step, to not overwrite the results while processing the last pixel!
- //blend four corners of current pixel
- if (blendingNeeded(blend_xy)) //good 5% perf-improvement
+ //blend all four corners of current pixel
+ if (blendingNeeded(blend_xy))
{
- Kernel_3x3 ker3 = {}; //perf: initialization is negligible
-
- ker3.a = ker4.a;
- ker3.b = ker4.b;
- ker3.c = ker4.c;
-
- ker3.d = ker4.e;
- ker3.e = ker4.f;
- ker3.f = ker4.g;
-
- ker3.g = ker4.i;
- ker3.h = ker4.j;
- ker3.i = ker4.k;
-
+ const auto& ker3 = reinterpret_cast<const Kernel_3x3&>(ker4); //"The Things We Do for Perf"
blendPixel<Scaler, ColorDistance, ROT_0 >(ker3, out, trgWidth, blend_xy, cfg);
blendPixel<Scaler, ColorDistance, ROT_90 >(ker3, out, trgWidth, blend_xy, cfg);
blendPixel<Scaler, ColorDistance, ROT_180>(ker3, out, trgWidth, blend_xy, cfg);
@@ -1076,15 +1153,15 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth
switch (factor)
{
case 2:
- return scaleImage<Scaler2x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler2x<ColorGradientRGB>, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 3:
- return scaleImage<Scaler3x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler3x<ColorGradientRGB>, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 4:
- return scaleImage<Scaler4x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler4x<ColorGradientRGB>, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 5:
- return scaleImage<Scaler5x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler5x<ColorGradientRGB>, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 6:
- return scaleImage<Scaler6x<ColorGradientRGB>, ColorDistanceRGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler6x<ColorGradientRGB>, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
}
break;
@@ -1092,15 +1169,15 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth
switch (factor)
{
case 2:
- return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 3:
- return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 4:
- return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 5:
- return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 6:
- return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
}
break;
@@ -1108,15 +1185,15 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth
switch (factor)
{
case 2:
- return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceUnbufferedARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 3:
- return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceUnbufferedARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 4:
- return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceUnbufferedARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 5:
- return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceUnbufferedARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
case 6:
- return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceUnbufferedARGB>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+ return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
}
break;
}
diff --git a/xBRZ/src/xbrz.h b/xBRZ/src/xbrz.h
index f7f7169a..492fb43a 100644
--- a/xBRZ/src/xbrz.h
+++ b/xBRZ/src/xbrz.h
@@ -51,7 +51,6 @@ const int SCALE_FACTOR_MAX = 6;
/*
-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only
--> support for source/target pitch in bytes!
-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image:
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
CAVEAT: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
diff --git a/xBRZ/src/xbrz_tools.h b/xBRZ/src/xbrz_tools.h
index 15bea025..b8bb8aa0 100644
--- a/xBRZ/src/xbrz_tools.h
+++ b/xBRZ/src/xbrz_tools.h
@@ -56,7 +56,7 @@ Pix* byteAdvance(Pix* ptr, int bytes)
//fill block with the given color
template <class Pix> inline
-void fillBlock(Pix* trg, int pitch, Pix col, int blockWidth, int blockHeight)
+void fillBlock(Pix* trg, int pitch /*[bytes]*/, Pix col, int blockWidth, int blockHeight)
{
//for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch))
// std::fill(trg, trg + blockWidth, col);
@@ -69,8 +69,8 @@ void fillBlock(Pix* trg, int pitch, Pix col, int blockWidth, int blockHeight)
//nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!)
template <class PixSrc, class PixTrg, class PixConverter>
-void nearestNeighborScale(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch,
- /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch,
+void nearestNeighborScale(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch /*[bytes]*/,
+ /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch /*[bytes]*/,
int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/)
{
static_assert(std::is_integral<PixSrc>::value, "PixSrc* is expected to be cast-able to char*");
@@ -106,8 +106,8 @@ void nearestNeighborScale(const PixSrc* src, int srcWidth, int srcHeight, int sr
//nearest-neighbor (going over source image - fast for upscaling, since source is read only once
template <class PixSrc, class PixTrg, class PixConverter>
-void nearestNeighborScaleOverSource(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch,
- /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch,
+void nearestNeighborScaleOverSource(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch /*[bytes]*/,
+ /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch /*[bytes]*/,
int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/)
{
static_assert(std::is_integral<PixSrc>::value, "PixSrc* is expected to be cast-able to char*");
diff --git a/zen/globals.h b/zen/globals.h
index e59d64c1..4c1453a2 100644
--- a/zen/globals.h
+++ b/zen/globals.h
@@ -206,7 +206,7 @@ void registerGlobalForDestruction(CleanUpEntry& entry)
//------------------------------------------------------------------------------------------
#if __cpp_lib_atomic_wait
-#error implement + rewiew improvements
+ #error implement + rewiew improvements
#endif
diff --git a/zen/legacy_compiler.h b/zen/legacy_compiler.h
index 6ce1d765..54dd7f59 100644
--- a/zen/legacy_compiler.h
+++ b/zen/legacy_compiler.h
@@ -9,9 +9,9 @@
#if !__cpp_lib_erase_if
-#include <vector>
-#include <set>
-#include <map>
+ #include <vector>
+ #include <set>
+ #include <map>
#endif
diff --git a/zen/serialize.h b/zen/serialize.h
index 5a38303c..bdeec858 100644
--- a/zen/serialize.h
+++ b/zen/serialize.h
@@ -9,6 +9,7 @@
#include <functional>
#include <cstdint>
+#include <stdexcept>
#include "string_base.h"
//keep header clean from specific stream implementations! (e.g.file_io.h)! used by abstract.h!
diff --git a/zen/stl_tools.h b/zen/stl_tools.h
index d09010ad..8856ce84 100644
--- a/zen/stl_tools.h
+++ b/zen/stl_tools.h
@@ -96,7 +96,7 @@ public:
/**/ T& ref() { return *ref_; };
const T& ref() const { return *ref_; };
- std::shared_ptr< T> ptr() { return ref_; };
+ std::shared_ptr< T> ptr() { return ref_; };
std::shared_ptr<const T> ptr() const { return ref_; };
private:
@@ -207,9 +207,9 @@ BidirectionalIterator1 searchLast(const BidirectionalIterator1 first1, Bid
//http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0458r2.html
template <class Container, class ValueType, typename = std::enable_if_t<!IsStringLikeV<Container>>> inline
-bool contains(const Container& c, const ValueType& val, int dummy = 0 /*overload string_tools.h contains()*/)
+ bool contains(const Container& c, const ValueType& val, int dummy = 0 /*overload string_tools.h contains()*/)
{
- return c.find(val) != c.end();
+ return c.find(val) != c.end();
}
//---------------------------------------------------------------------------------------
diff --git a/zen/string_tools.h b/zen/string_tools.h
index 7f9a07ff..47271bc7 100644
--- a/zen/string_tools.h
+++ b/zen/string_tools.h
@@ -34,19 +34,19 @@ template <class Char> Char asciiToUpper(Char c);
//both S and T can be strings or char/wchar_t arrays or single char/wchar_t
template <class S, class T, typename = std::enable_if_t<IsStringLikeV<S>>> bool contains(const S& str, const T& term);
-template <class S, class T> bool startsWith (const S& str, const T& prefix);
-template <class S, class T> bool startsWithAsciiNoCase(const S& str, const T& prefix);
+ template <class S, class T> bool startsWith (const S& str, const T& prefix);
+ template <class S, class T> bool startsWithAsciiNoCase(const S& str, const T& prefix);
-template <class S, class T> bool endsWith (const S& str, const T& postfix);
-template <class S, class T> bool endsWithAsciiNoCase(const S& str, const T& postfix);
+ template <class S, class T> bool endsWith (const S& str, const T& postfix);
+ template <class S, class T> bool endsWithAsciiNoCase(const S& str, const T& postfix);
-template <class S, class T> bool equalString (const S& lhs, const T& rhs);
-template <class S, class T> bool equalAsciiNoCase(const S& lhs, const T& rhs);
+ template <class S, class T> bool equalString (const S& lhs, const T& rhs);
+ template <class S, class T> bool equalAsciiNoCase(const S& lhs, const T& rhs);
-template <class S, class T> int compareString (const S& lhs, const T& rhs);
-template <class S, class T> int compareAsciiNoCase(const S& lhs, const T& rhs); //basic case-insensitive comparison (considering A-Z only!)
+ template <class S, class T> int compareString (const S& lhs, const T& rhs);
+ template <class S, class T> int compareAsciiNoCase(const S& lhs, const T& rhs); //basic case-insensitive comparison (considering A-Z only!)
-struct LessAsciiNoCase //STL container predicate
+ struct LessAsciiNoCase //STL container predicate
{
template <class S> bool operator()(const S& lhs, const S& rhs) const { return compareAsciiNoCase(lhs, rhs) < 0; }
};
@@ -165,21 +165,21 @@ template <class Char> inline
Char asciiToLower(Char c)
{
if (static_cast<Char>('A') <= c && c <= static_cast<Char>('Z'))
- return static_cast<Char>(c - static_cast<Char>('A') + static_cast<Char>('a'));
- return c;
+ return static_cast<Char>(c - static_cast<Char>('A') + static_cast<Char>('a'));
+ return c;
}
-template <class Char> inline
-Char asciiToUpper(Char c)
+ template <class Char> inline
+ Char asciiToUpper(Char c)
{
if (static_cast<Char>('a') <= c && c <= static_cast<Char>('z'))
- return static_cast<Char>(c - static_cast<Char>('a') + static_cast<Char>('A'));
- return c;
+ return static_cast<Char>(c - static_cast<Char>('a') + static_cast<Char>('A'));
+ return c;
}
-namespace impl
+ namespace impl
{
inline int strcmpWithNulls(const char* ptr1, const char* ptr2, size_t num) { return std:: memcmp(ptr1, ptr2, num); } //support embedded 0, unlike strncmp/wcsncmp!
inline int strcmpWithNulls(const wchar_t* ptr1, const wchar_t* ptr2, size_t num) { return std::wmemcmp(ptr1, ptr2, num); } //
@@ -793,10 +793,10 @@ template <class S, class Num> inline
S numberTo(const Num& number)
{
using TypeTag = std::integral_constant<impl::NumberType,
- IsSignedInt <Num>::value ? impl::NumberType::SIGNED_INT :
- IsUnsignedInt<Num>::value ? impl::NumberType::UNSIGNED_INT :
- IsFloat <Num>::value ? impl::NumberType::FLOATING_POINT :
- impl::NumberType::OTHER>;
+ IsSignedInt <Num>::value ? impl::NumberType::SIGNED_INT :
+ IsUnsignedInt<Num>::value ? impl::NumberType::UNSIGNED_INT :
+ IsFloat <Num>::value ? impl::NumberType::FLOATING_POINT :
+ impl::NumberType::OTHER>;
return impl::numberTo<S>(number, TypeTag());
}
@@ -806,10 +806,10 @@ template <class Num, class S> inline
Num stringTo(const S& str)
{
using TypeTag = std::integral_constant<impl::NumberType,
- IsSignedInt <Num>::value ? impl::NumberType::SIGNED_INT :
- IsUnsignedInt<Num>::value ? impl::NumberType::UNSIGNED_INT :
- IsFloat <Num>::value ? impl::NumberType::FLOATING_POINT :
- impl::NumberType::OTHER>;
+ IsSignedInt <Num>::value ? impl::NumberType::SIGNED_INT :
+ IsUnsignedInt<Num>::value ? impl::NumberType::UNSIGNED_INT :
+ IsFloat <Num>::value ? impl::NumberType::FLOATING_POINT :
+ impl::NumberType::OTHER>;
return impl::stringTo<Num>(str, TypeTag());
}
diff --git a/zen/sys_error.h b/zen/sys_error.h
index f3b38250..57503732 100644
--- a/zen/sys_error.h
+++ b/zen/sys_error.h
@@ -85,7 +85,7 @@ std::wstring formatSystemError(const std::wstring& functionName, long long lastE
inline
std::wstring formatSystemError(const std::wstring& functionName, ErrorCode ec)
{
- const std::wstring errorDescr = formatSystemErrorRaw(ec);
+ const std::wstring errorDescr = formatSystemErrorRaw(ec);
const std::wstring errorCode = numberTo<std::wstring>(ec);
//const std::wstring errorCode = printNumber<std::wstring>(L"0x%08x", static_cast<int>(ec));
bgstack15