summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Application.cpp65
-rw-r--r--Application.h2
-rw-r--r--BUILD/Changelog.txt (renamed from Changelog.txt)26
-rw-r--r--BUILD/Compress with UPX.cmd2
-rw-r--r--BUILD/Languages/chinese_simple.lng (renamed from Languages/chinese_simple.lng)38
-rw-r--r--BUILD/Languages/dutch.lng (renamed from Languages/dutch.lng)42
-rw-r--r--BUILD/Languages/french.lng (renamed from Languages/french.lng)190
-rw-r--r--BUILD/Languages/german.lng (renamed from Languages/german.lng)38
-rw-r--r--BUILD/Languages/hungarian.lng (renamed from Languages/hungarian.lng)252
-rw-r--r--BUILD/Languages/italian.lng (renamed from Languages/italian.lng)36
-rw-r--r--BUILD/Languages/japanese.lng (renamed from Languages/japanese.lng)36
-rw-r--r--BUILD/Languages/polish.lng (renamed from Languages/polish.lng)36
-rw-r--r--BUILD/Languages/portuguese.lng (renamed from Languages/portuguese.lng)36
-rw-r--r--BUILD/Languages/portuguese_br.lng (renamed from Languages/portuguese_br.lng)122
-rw-r--r--BUILD/Languages/russian.lng726
-rw-r--r--BUILD/Languages/slovenian.lng (renamed from Languages/slovenian.lng)38
-rw-r--r--BUILD/Languages/spanish.lng (renamed from Languages/spanish.lng)38
-rw-r--r--BUILD/License.txt (renamed from License.txt)0
-rw-r--r--BUILD/Readme.txt (renamed from Readme.txt)15
-rw-r--r--BUILD/Resources.dat (renamed from Resources.dat)bin231192 -> 237836 bytes
-rw-r--r--BUILD/Shadow.zipbin0 -> 12676 bytes
-rw-r--r--BUILD/mingwm10.dllbin0 -> 11362 bytes
-rw-r--r--Cleanup.cmd28
-rw-r--r--FreeFileSync.cbp131
-rw-r--r--FreeFileSync.vcproj483
-rw-r--r--Makefile75
-rw-r--r--Makefile_Win.cmd45
-rw-r--r--algorithm.cpp79
-rw-r--r--algorithm.h6
-rw-r--r--comparison.cpp116
-rw-r--r--comparison.h12
-rw-r--r--library/CustomGrid.cpp949
-rw-r--r--library/CustomGrid.h150
-rw-r--r--library/ShadowCopy/ShadowDll.vcproj219
-rw-r--r--library/ShadowCopy/dllmain.cpp22
-rw-r--r--library/ShadowCopy/shadow.cpp178
-rw-r--r--library/ShadowCopy/shadow.h33
-rw-r--r--library/fileError.h25
-rw-r--r--library/fileHandling.cpp203
-rw-r--r--library/fileHandling.h45
-rw-r--r--library/filter.cpp97
-rw-r--r--library/filter.h6
-rw-r--r--library/globalFunctions.cpp49
-rw-r--r--library/globalFunctions.h88
-rw-r--r--library/iconBuffer.cpp298
-rw-r--r--library/iconBuffer.h51
-rw-r--r--library/localization.cpp208
-rw-r--r--library/localization.h52
-rw-r--r--library/pch.h23
-rw-r--r--library/processXml.cpp117
-rw-r--r--library/processXml.h81
-rw-r--r--library/resources.cpp34
-rw-r--r--library/resources.h32
-rw-r--r--library/shadow.cpp148
-rw-r--r--library/shadow.h31
-rw-r--r--library/statistics.cpp17
-rw-r--r--library/statistics.h13
-rw-r--r--library/zstring.cpp6
-rw-r--r--library/zstring.h60
-rw-r--r--mingwm10.dllbin23464 -> 0 bytes
-rw-r--r--resource.rc4
-rw-r--r--structures.cpp155
-rw-r--r--structures.h44
-rw-r--r--synchronization.cpp662
-rw-r--r--synchronization.h40
-rw-r--r--ui/MainDialog.cpp975
-rw-r--r--ui/MainDialog.h99
-rw-r--r--ui/SmallDialogs.cpp157
-rw-r--r--ui/SmallDialogs.h28
-rw-r--r--ui/SyncDialog.cpp136
-rw-r--r--ui/batchStatusHandler.cpp14
-rw-r--r--ui/gridView.cpp34
-rw-r--r--ui/gridView.h3
-rw-r--r--ui/guiGenerated.cpp546
-rw-r--r--ui/guiGenerated.h142
-rw-r--r--ui/guiStatusHandler.cpp6
-rw-r--r--ui/sorting.h18
-rw-r--r--version/version.h2
78 files changed, 6272 insertions, 2741 deletions
diff --git a/Application.cpp b/Application.cpp
index be358912..ca09f25a 100644
--- a/Application.cpp
+++ b/Application.cpp
@@ -7,7 +7,6 @@
#include "application.h"
#include "ui/mainDialog.h"
#include <wx/stdpaths.h>
-#include <wx/filename.h>
#include "library/globalFunctions.h"
#include <wx/msgdlg.h>
#include "comparison.h"
@@ -17,6 +16,10 @@
#include "ui/batchStatusHandler.h"
#include "ui/checkVersion.h"
#include "library/filter.h"
+#include <wx/file.h>
+#include <wx/filename.h>
+
+using FreeFileSync::FileError;
IMPLEMENT_APP(Application);
@@ -38,7 +41,12 @@ void Application::OnStartApplication(wxIdleEvent& event)
{
Disconnect(wxEVT_IDLE, wxIdleEventHandler(Application::OnStartApplication), NULL, this);
+ //if appname is not set, the default is the executable's name!
+ SetAppName(wxT("FreeFileSync"));
+
//test if FFS is to be started on UI with config file passed as commandline parameter
+
+//#warning
//this needs to happen BEFORE the working directory is set!
wxString cfgFilename;
if (argc > 1)
@@ -66,21 +74,23 @@ void Application::OnStartApplication(wxIdleEvent& event)
}
-//set working directory to current executable directory
- const wxString workingDir = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath();
+ //set working directory to current executable directory
+ const wxString workingDir = FreeFileSync::getInstallationDir();
if (!wxSetWorkingDirectory(workingDir))
{ //show messagebox and quit program immediately
wxMessageBox(wxString(_("Could not set working directory:")) + wxT(" ") + workingDir, _("An exception occured!"), wxOK | wxICON_ERROR);
return;
}
+ GlobalResources::getInstance().load(); //loads bitmap resources on program startup
+
try //load global settings from XML: must be called AFTER working dir was set
{
globalSettings = xmlAccess::readGlobalSettings();
}
catch (const FileError& error)
{
- if (wxFileExists(xmlAccess::GLOBAL_CONFIG_FILE))
+ if (wxFileExists(FreeFileSync::getGlobalConfigFile()))
{ //show messagebox and quit program immediately
wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
return;
@@ -90,12 +100,9 @@ void Application::OnStartApplication(wxIdleEvent& event)
//set program language: needs to happen after working directory has been set!
SetExitOnFrameDelete(false); //prevent error messagebox from becoming top-level window
- programLanguage.setLanguage(globalSettings.shared.programLanguage);
+ programLanguage.setLanguage(globalSettings.programLanguage);
SetExitOnFrameDelete(true);
-//load image resources from file: must be called after working directory has been set
- globalResource.load();
-
if (!cfgFilename.empty())
{
@@ -104,7 +111,7 @@ void Application::OnStartApplication(wxIdleEvent& event)
if (xmlConfigType == xmlAccess::XML_GUI_CONFIG) //start in GUI mode (configuration file specified)
{
MainDialog* frame = new MainDialog(NULL, cfgFilename, &programLanguage, globalSettings);
- frame->SetIcon(*globalResource.programIcon); //set application icon
+ frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
frame->Show();
}
else if (xmlConfigType == xmlAccess::XML_BATCH_CONFIG) //start in commandline mode
@@ -123,8 +130,8 @@ void Application::OnStartApplication(wxIdleEvent& event)
}
else //start in GUI mode (standard)
{
- MainDialog* frame = new MainDialog(NULL, xmlAccess::LAST_CONFIG_FILE, &programLanguage, globalSettings);
- frame->SetIcon(*globalResource.programIcon); //set application icon
+ MainDialog* frame = new MainDialog(NULL, FreeFileSync::getLastConfigFile(), &programLanguage, globalSettings);
+ frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
frame->Show();
}
}
@@ -142,15 +149,23 @@ int Application::OnRun()
{
wxApp::OnRun();
}
- catch (const RuntimeException& theException) //catch runtime errors during main event loop; wxApp::OnUnhandledException could be used alternatively
+ catch (const RuntimeException& e) //catch runtime errors during main event loop; wxApp::OnUnhandledException could be used alternatively
{
- wxMessageBox(theException.show(), _("An exception occured!"), wxOK | wxICON_ERROR);
- return -1;
+ //unfortunately it's not always possible to display a message box in this erroneous situation, however (non-stream) file output always works!
+ wxFile safeOutput(FreeFileSync::getLastErrorTxtFile(), wxFile::write);
+ safeOutput.Write(e.show());
+
+ wxMessageBox(e.show(), _("An exception occured!"), wxOK | wxICON_ERROR);
+ return -8;
}
catch (std::exception& e) //catch all STL exceptions
{
+ //unfortunately it's not always possible to display a message box in this erroneous situation, however (non-stream) file output always works!
+ wxFile safeOutput(FreeFileSync::getLastErrorTxtFile(), wxFile::write);
+ safeOutput.Write(wxString::From8BitData(e.what()));
+
wxMessageBox(wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR);
- return -1;
+ return -9;
}
return returnValue;
@@ -160,7 +175,7 @@ int Application::OnRun()
int Application::OnExit()
{
//get program language
- globalSettings.shared.programLanguage = programLanguage.getLanguage();
+ globalSettings.programLanguage = programLanguage.getLanguage();
try //save global settings to XML
{
@@ -192,7 +207,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet
//regular check for program updates
if (!batchCfg.silent)
- FreeFileSync::checkForUpdatePeriodically(globalSettings.shared.lastUpdateCheck);
+ FreeFileSync::checkForUpdatePeriodically(globalSettings.lastUpdateCheck);
try //begin of synchronization process (all in one try-catch block)
@@ -211,10 +226,10 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet
//COMPARE DIRECTORIES
FreeFileSync::FolderComparison folderCmp;
- FreeFileSync::CompareProcess comparison(globalSettings.shared.traverseDirectorySymlinks,
- globalSettings.shared.fileTimeTolerance,
- globalSettings.shared.ignoreOneHourDiff,
- globalSettings.shared.warningDependentFolders,
+ FreeFileSync::CompareProcess comparison(globalSettings.traverseDirectorySymlinks,
+ globalSettings.fileTimeTolerance,
+ globalSettings.ignoreOneHourDiff,
+ globalSettings.warnings,
filterInstance.get(),
statusHandler.get());
@@ -233,11 +248,9 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet
//START SYNCHRONIZATION
FreeFileSync::SyncProcess synchronization(
batchCfg.mainCfg.useRecycleBin,
- globalSettings.shared.copyFileSymlinks,
- globalSettings.shared.traverseDirectorySymlinks,
- globalSettings.shared.warningSignificantDifference,
- globalSettings.shared.warningNotEnoughDiskSpace,
- globalSettings.shared.warningUnresolvedConflicts,
+ globalSettings.copyFileSymlinks,
+ globalSettings.traverseDirectorySymlinks,
+ globalSettings.warnings,
statusHandler.get());
synchronization.startSynchronizationProcess(folderCmp);
diff --git a/Application.h b/Application.h
index 1a71b619..cf6d6dd4 100644
--- a/Application.h
+++ b/Application.h
@@ -25,7 +25,7 @@ public:
private:
void runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSettings& globalSettings);
- CustomLocale programLanguage;
+ FreeFileSync::CustomLocale programLanguage;
int returnValue;
xmlAccess::XmlGlobalSettings globalSettings; //settings used by GUI, batch mode or both
diff --git a/Changelog.txt b/BUILD/Changelog.txt
index 7a513639..22259889 100644
--- a/Changelog.txt
+++ b/BUILD/Changelog.txt
@@ -1,6 +1,30 @@
FreeFileSync
------------
+Changelog v2.0
+---------------
+Copy locked files using Windows Volume Shadow Copy
+Load file icons asynchronously for maximum display performance
+Handle include filter correctly when comparing
+Display optional summary window before starting synchronization
+Adjust sync direction properly when switching sides
+Info about sync variant on main dialog
+Issue a warning message for each conflict type when comparing
+Save default configuration in user application path (Installer based version)
+Limit main dialog minimum size
+Update grid row labels while scrolling
+Right-click selects cell before opening context menu
+New context menu options to manually assign a sync-direction
+Moved sync-preview switch into middle grid's context menu
+Possibility to remove top folder pair
+Fixed calculation of row total in sync preview
+File icons configurable for each side
+Many small GUI improvements
+Compiled successfully with GCC 4.4.0 and MS Visual C++ 2008
+Added Russian translation
+Updated translation files
+
+
Changelog v1.19
---------------
New synchronization preview
@@ -310,11 +334,11 @@ Written custom wxGrid class to avoid mapping of data to UI: huge performance inc
Filter files to include/exclude them from synchronization
Minor UI and text adaptions
Allow direct keyboard input for directory names
-Updated German translation
Added possibility to continue on error
Added indicator for sort direction
Simplified code concerning loading of UI resources
Prepared code to support unicode in some future version
+Updated German translation
Changelog v1.0
diff --git a/BUILD/Compress with UPX.cmd b/BUILD/Compress with UPX.cmd
new file mode 100644
index 00000000..40180a1e
--- /dev/null
+++ b/BUILD/Compress with UPX.cmd
@@ -0,0 +1,2 @@
+C:\Programme\C++\UPX\upx -9 --compress-icons=0 %1
+pause \ No newline at end of file
diff --git a/Languages/chinese_simple.lng b/BUILD/Languages/chinese_simple.lng
index a72ffc60..a4cf8017 100644
--- a/Languages/chinese_simple.lng
+++ b/BUILD/Languages/chinese_simple.lng
@@ -176,6 +176,8 @@ Build:
开发:
Cancel
取消
+Change direction
+
Check all
检查所有
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
配置自己的同步规则.
Confirm
确认
+Conflict detected:
+
Continue
继续
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
正复制文件 %x 到 %y
Copying file %x to %y overwriting target
复制文件 %x 并覆盖到目标 %y
+Could not determine volume name for file:
+
Could not set working directory:
无法设置工作目录:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
目录不存在:
Do not display visual status information but write to a logfile instead
不显示视觉状态信息,使用写入日志文件代替。
-Do not show this warning again
-不再显示警告信息
+Do not show this dialog again
+
Do nothing
保持不动
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
修改时间出错:
Error copying file:
复制文件出错:
+Error copying locked file %x!
+
Error creating directory:
创建目录出错:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
解决字符链接出错:
Error retrieving full path:
获取完整路径时出错:
+Error starting Volume Shadow Copy Service!
+
Error traversing directory:
遍历目录出错:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
带参数退出
Feedback and suggestions are welcome at:
欢迎在下面提出反馈意见和建议:
+File %x has an invalid date!
+
File Manager integration:
文件管理集成器:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
文件相差最多指定秒数但仍然具有相同的处理时间.
Filename
文件名
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+
+Files %x have the same date but a different size!
+
Files are found equal if\n - file content\nis the same.
如果文件内容相同则认为两者相同
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
移动下一行
Move column up
移动上一行
+Moving %x to Recycle Bin
+
Not all items have been synchronized! Have a look at the list.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
暂停
Paused
已暂停
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+
Please fill all empty directory fields.
请填满所有空的目录区域.
Press button to activate filter
请按键以激活过滤
-Preview
-视图
Published under the GNU General Public License:
在GNU通用公共许可下发布:
Question
@@ -614,10 +632,12 @@ Start
开始
Start synchronization
开始同步
+Statistics
+
Stop
停止
Swap sides
-换边
+
Synchronization Preview
Synchronization aborted!
@@ -626,8 +646,6 @@ Synchronization completed successfully!
同步成功完成!
Synchronization completed with errors!
同步已完成但有错误.
-Synchronization filter
-同步过滤
Synchronization settings
同步设置
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Synchronize both sides simultaneously: Copy new or updated files in both directions.
同时同步两侧: 复制新的或更新的文件在两个方向.
+Synchronize...
+
Synchronizing...
同步中...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
使用回收站
Use Recycle Bin when deleting or overwriting files during synchronization
当同步时使用回收站删除或覆盖档案
+Variant
+
+Volume name %x not part of filename %y!
+
Warning
警告
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/dutch.lng b/BUILD/Languages/dutch.lng
index 5e00740f..00a08d65 100644
--- a/Languages/dutch.lng
+++ b/BUILD/Languages/dutch.lng
@@ -171,11 +171,13 @@ Batch taak
Big thanks for localizing FreeFileSync goes out to:
Extra dank voor het vertalen van FreeFileSync gaat naar:
Browse
-Bestand opzoeken
+Map opzoeken
Build:
Gebouwd:
Cancel
Annuleren
+Change direction
+Zijdes omwisselen
Check all
Alles controleren
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Configureer uw eigen synchronisatieregels.
Confirm
Bevestig
+Conflict detected:
+Conflict gedetecteerd:
Continue
Doorgaan
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Bestand %x wordt gekopieerd naar %y
Copying file %x to %y overwriting target
Aan het overschrijven van bestand %x naar %y
+Could not determine volume name for file:
+Kon de schijfnaam niet vaststellen van bestand:
Could not set working directory:
Kan het pad in gebruik niet instellen:
Create a batch job
@@ -247,7 +253,7 @@ Map %x wordt aangemaakt
Current operation:
Huidige operatie:
Custom
-Gebruik
+Eigen regels
Customize columns
Aanpassen kolommen
DECISION TREE
@@ -278,8 +284,8 @@ Directory does not exist:
Map bestaat niet:
Do not display visual status information but write to a logfile instead
In plaats van visuele statusinformatie weergeven, alles naar een logbestand schrijven
-Do not show this warning again
-Deze waarschuwing niet meer tonen
+Do not show this dialog again
+Deze melding niet meer weergeven
Do nothing
Geen actie ondernemen
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Er is een fout opgetreden bij het aanpassen van de bestandstijd:
Error copying file:
Er is een fout opgetreden bij het kopiëren van bestand:
+Error copying locked file %x!
+Er is een fout opgetreden bij het kopiëren van %x omdat het bestand in gebruik is!
Error creating directory:
Er is een fout opgetreden bij het aanmaken van pad:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Er is een fout opgetreden bij het ophalen van een symbolische koppeling:
Error retrieving full path:
Er is een fout opgetreden bij het achterhalen van de volledige bestandslocatie:
+Error starting Volume Shadow Copy Service!
+Er is een fout opgetreden bij het starten van de Volume Schadow Copy Service!
Error traversing directory:
Er is een fout opgetreden bij het doorzoeken van map:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Afsluiten met RC < 0
Feedback and suggestions are welcome at:
Tips en suggesties zijn welkom op:
+File %x has an invalid date!
+Bestand %x heeft een ongeldige datum!
File Manager integration:
Integratie bestandsbeheer:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Bestandstijden die verschillen met maximaal de gespecificeerde tijd worden nog steeds behandeld alsof ze dezelfde tijd hebben.
Filename
Bestandsnaam
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+De bestanden %x hebben een bestandstijd verschil van minder dan één uur! Het is niet veilig te bepalen welke nieuwer is vanwege zomertijd instellingen
+Files %x have the same date but a different size!
+De bestanden %x hebben dezelfde data maar een afwijkende grootte!
Files are found equal if\n - file content\nis the same.
Bestanden worden gelijk beschouwd als,\n - de inhoud\novereenkomt.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Verplaats kolom naar beneden
Move column up
Verplaats kolom naar boven
+Moving %x to Recycle Bin
+%x aan het verplaatsen naar de Prullenbak
Not all items have been synchronized! Have a look at the list.
Niet alle bestanden zijn gesynchroniseerd! Bekijk de lijst.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pause
Paused
Gepauseerd
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Kopiëer alstublieft \"Shadow.dll\" (locatie in \"Shadow.zip\" archief) naar de FreeFileSync installatiemap om het gebruik van deze optie mogelijk te maken
Please fill all empty directory fields.
Vul alstublieft aan beide kanten een pad in.
Press button to activate filter
Druk op de knop om het filter te activeren.
-Preview
-Voorbeeld
Published under the GNU General Public License:
Gepubliceerd onder de GNU General Public License:
Question
@@ -614,10 +632,12 @@ Start
Start
Start synchronization
Start synchroniseren
+Statistics
+Statistieken
Stop
Stop
Swap sides
-Verwissel van kant
+Wissel zijdes
Synchronization Preview
Synchronisatie voorbeeldweergave
Synchronization aborted!
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Synchronisatie succesvol afgerond!
Synchronization completed with errors!
Synchronisatie afgerond. Er zijn fouten opgetreden.
-Synchronization filter
-Synchronisatie filter
Synchronization settings
Synchronisatie instellingen
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Synchroniseer alle .doc, .zip en .exe bestanden uitgezonderd alles in submap \"temp\"
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Synchroniseer beide zijde tegelijkertijd: kopieer nieuwe of geüpdatete bestanden in beide richtingen.
+Synchronize...
+Synchroniseer...
Synchronizing...
Aan het synchroniseren...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Gebruik de prullenbak
Use Recycle Bin when deleting or overwriting files during synchronization
Gebruik de prullenbak wanneer bestanden worden verwijderd of overschreven tijdens het synchroniseren
+Variant
+Variant
+Volume name %x not part of filename %y!
+Volume naam %x maakt niet deel uit van bestandsnaam %y!
Warning
Attentie
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/french.lng b/BUILD/Languages/french.lng
index fcf148d5..94824d5b 100644
--- a/Languages/french.lng
+++ b/BUILD/Languages/french.lng
@@ -27,7 +27,7 @@
%x files,
%x fichiers,
%x is not a valid FreeFileSync batch file!
-%x n'est pas un fichier batch FreeFileSync valide!
+%x n'est pas un fichier batch FreeFileSync valide !
%x of %y rows in view
%x sur %y lignes affichées
%x of 1 row in view
@@ -141,9 +141,9 @@
>> right file is newer\n
>> le fichier de droite est plus récent\n
A newer version of FreeFileSync is available:
-Une version plus récente de FreeFileSync est disponible:
+Une version plus récente de FreeFileSync est disponible :
Abort requested: Waiting for current operation to finish...
-Abandon demandé: En attente de la fin de l'opération en cours...
+Abandon demandé : En attente de la fin de l'opération en cours...
Aborted
Abandonné
About
@@ -153,29 +153,31 @@ Action
Add folder pair
Ajout d'un couple de dossiers
All items have been synchronized!
-Tous les éléments ont été synchronisés!
+Tous les éléments ont été synchronisés !
An exception occured!
Une violation s'est produite !
As a result the files are separated into the following categories:
-En conclusion, les fichiers sont répartis dans les catégories suivantes:
+En conclusion, les fichiers sont répartis dans les catégories suivantes :
As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:
-Comme le nom le suggère, deux fichiers qui ont le même nom sont considérés comme identiques si, et seulement si, leur contenu est identique. Cette option est utile pour les contrôles de cohérence plutôt que pour les opérations de sauvegarde. Toutefois, les dates et heures ne sont pas du tout prises en compte.\n\nAvec cette option, l'arbre de décision est plus simple:
+Comme le nom le suggère, deux fichiers qui ont le même nom sont considérés comme identiques si, et seulement si, leur contenu est identique. Cette option est utile pour les contrôles de cohérence plutôt que pour les opérations de sauvegarde. Toutefois, les dates et heures ne sont pas du tout prises en compte.\n\nAvec cette option, l'arbre de décision est plus simple :
Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner.
-Créer un fichier de commandespour une synchronisation automatique. Pour démarrer en mode batch, indiquer le nom du fichier à l'exécutable FreeFileSync: freefilesync.exe <fichier de commandes>. Ceci peut aussi être programmé dans le plannificateur de tâches.
+Créer un fichier de commandespour une synchronisation automatique. Pour démarrer en mode batch, indiquer le nom du fichier à l'exécutable FreeFileSync : freefilesync.exe <fichier de commandes>. Ceci peut aussi être programmé dans le plannificateur de tâches.
Batch execution
Exécution du fichier de commandes
Batch file created successfully!
-Fichier de commandes créé avec succès!
+Fichier de commandes créé avec succès !
Batch job
Fichier de commandes
Big thanks for localizing FreeFileSync goes out to:
-Pour les traductions de FreeFileSync, un grand merci à:
+Pour les traductions de FreeFileSync, un grand merci à :
Browse
Parcourir
Build:
-Créé:
+Créé le :
Cancel
Annuler
+Change direction
+Changer la direction
Check all
Cocher tout
Choose to hide filtered files/directories from list
@@ -205,11 +207,11 @@ Terminé
Configuration
Configuration
Configuration loaded!
-Configuration chargée!
+Configuration chargée !
Configuration overview:
-Contrôle des paramètres:
+Contrôle des paramètres :
Configuration saved!
-Configuration enregistrée!
+Configuration enregistrée !
Configure filter
Configuration des filtres
Configure filter...
@@ -218,10 +220,12 @@ Configure your own synchronization rules.
Paramétrage de vos règles de synchronisation.
Confirm
Confirmation
+Conflict detected:
+Conflit détecté :
Continue
Continuer
Conversion error:
-Erreur de conversion:
+Erreur de conversion :
Copy from left to right
Copie de gauche à droite
Copy from left to right overwriting
@@ -238,8 +242,10 @@ Copying file %x to %y
Copie le fichier %x vers %y
Copying file %x to %y overwriting target
Copie le fichier %x vers %y avec écrasement
+Could not determine volume name for file:
+Impossible de trouver le nom de volume pour le fichier :
Could not set working directory:
-Impossible de définir le répertoire de travail:
+Impossible de définir le répertoire de travail :
Create a batch job
Création du fichier de commandes
Creating folder %x
@@ -271,15 +277,15 @@ Suppression du fichier %x
Deleting folder %x
Suppression du dossier %x
Directories are dependent! Be careful when setting up synchronization rules:
-Les dossiers sont imbriqués! Attention à la mise à jour des règles de synchronisation:
+Les dossiers sont imbriqués ! Attention à la mise à jour des règles de synchronisation :
Directory
Répertoire
Directory does not exist:
-Le répertoire n'existe pas:
+Le répertoire n'existe pas :
Do not display visual status information but write to a logfile instead
Ne pas afficher les informations d'état à l'écran mais les enregistrer plutôt dans un fichier log
-Do not show this warning again
-Ne plus afficher cet avertissement
+Do not show this dialog again
+Ne pas afficher cette boîte de dialogue
Do nothing
Ne rien faire
Do you really want to delete the following objects(s)?
@@ -303,41 +309,45 @@ Activer le filtrage pour exclure les fichiers de la synchronisation
Error
Erreur
Error changing modification time:
-Erreur lors du changement de la date de modification:
+Erreur lors du changement de la date de modification :
Error copying file:
-Erreur lors de la copie du fichier:
+Erreur lors de la copie du fichier :
+Error copying locked file %x!
+Erreur lors de la copie du fichier verrouillé %x !
Error creating directory:
-Erreur lors de la création d'un répertoire:
+Erreur lors de la création d'un répertoire :
Error deleting directory:
-Erreur lors de la suppression d'un répertoire:
+Erreur lors de la suppression d'un répertoire :
Error deleting file:
-Erreur lors de la suppression d'un fichier:
+Erreur lors de la suppression d'un fichier :
Error handling
Erreur de gestion de fichiers
Error loading library function:
-Erreur lors du chargement de la bibliothèque de fonctions
+Erreur lors du chargement de la bibliothèque de fonctions :
Error moving to Recycle Bin:
-Erreur lors du déplacement dans la corbeille
+Erreur lors du déplacement dans la corbeille :
Error opening file:
-Erreur lors de l'ouverture du fichier:
+Erreur lors de l'ouverture du fichier :
Error parsing configuration file:
-Erreur lors de l'analyse du fichier de configuration:
+Erreur lors de l'analyse du fichier de configuration :
Error reading file attributes:
-Erreur lors de la lecture des attributs du fichier:
+Erreur lors de la lecture des attributs du fichier :
Error reading file:
-Erreur lors de la lecture du fichier:
+Erreur lors de la lecture du fichier :
Error resolving symbolic link:
-Erreur lors de la résolution du lien symbolique:
+Erreur lors de la résolution du lien symbolique :
Error retrieving full path:
-Erreur lors de la recherche du chemin:
+Erreur lors de la recherche du chemin :
+Error starting Volume Shadow Copy Service!
+Erreur lors du démarrage du service 'Volume Shadow Copy' !
Error traversing directory:
-Erreur lors du parcours du répertoire:
+Erreur lors du parcours du répertoire :
Error writing file attributes:
-Erreur lors de l'écriture des attributs du fichier:
+Erreur lors de l'écriture des attributs du fichier :
Error writing file:
-Erreur lors de l'écriture du fichier:
+Erreur lors de l'écriture du fichier :
Error: Source directory does not exist anymore:
-Erreur: le répertoire source n'existe plus:
+Erreur : le répertoire source n'existe plus :
Example
Exemple
Exclude
@@ -345,37 +355,43 @@ Exclure
Exclude temporarily
Exclure temporairement
Exclude via filter:
-Exclure à l'aide du filtre:
+Exclure à l'aide du filtre :
Exit immediately and set returncode < 0
Sortie immédiate avec le returncode < 0
Exit with RC < 0
Sortie avec RC < 0
Feedback and suggestions are welcome at:
Commentaires et suggestions sont les bienvenus à :
+File %x has an invalid date!
+Le fichier %x a une date invalide !
File Manager integration:
-Choix du Gestionnaire de Fichiers:
+Choix du Gestionnaire de Fichiers :
File Time tolerance (seconds):
-Tolérance sur l'heure de création du fichier (en secondes):
+Tolérance sur l'heure de création du fichier (en secondes) :
File already exists. Overwrite?
-Le fichier existe déjà. Voulez-vous le remplacer?
+Le fichier existe déjà. Voulez-vous le remplacer ?
File content
Contenu du fichier
File does not exist:
-Le fichier n'existe pas:
+Le fichier n'existe pas :
File list exported!
-Liste des fichiers exportée!
+Liste des fichiers exportée !
File size and date
Taille et date du fichier
File times that differ by up to the specified number of seconds are still handled as having same time.
Les fichiers ayant des heures qui diffèrent d'un nombre de secondes inférieur à celui spécifié sont considérés comme ayant la même heure.
Filename
Nom du fichier
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Les fichiers %x ont une différence de date inférieure à 1 heure ! Il n'est pas sain de décider quelle est la plus récente à cause de l'heure d'été.
+Files %x have the same date but a different size!
+Les fichiers %x ont la même data mais une taille différente !
Files are found equal if\n - file content\nis the same.
Les fichiers sont considérés comme identiques, si\n - leur contenu est identique.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
Les fichiers sont considérés comme identiques, si\n - leur taille\n - leur date et heure sont identiques.
Files remaining:
-Fichiers restants:
+Fichiers restants :
Files that exist on both sides and have different content
Les fichiers existent des deux côtés et ont des contenus différents
Files that exist on both sides, left one is newer
@@ -383,9 +399,9 @@ Fichiers existants des deux côtés, celui de gauche est plus récent
Files that exist on both sides, right one is newer
Fichiers existants des deux côtés, celui de droite est plus récent
Files/folders remaining:
-Fichiers/dossiers restants:
+Fichiers/dossiers restants :
Files/folders scanned:
-Fichiers/dossiers analysés
+Fichiers/dossiers analysés :
Files/folders that exist on left side only
Fichiers/répertoires existants seulement à gauche
Files/folders that exist on right side only
@@ -393,7 +409,7 @@ Fichiers/répertoires existants seulement à droite
Filter
Filtrage
Filter active: Press again to deactivate
-Filtrage actif: Cliquez de nouveau pour le désactiver
+Filtrage actif : Cliquez de nouveau pour le désactiver
Filter files
Filtrage des fichiers
Filter view
@@ -449,9 +465,9 @@ Masquer les éléments filtrés
Hide further error messages during the current process
Masquer les messages d'erreur suivants pendant le traitement
Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process
-Masquer les messages d'erreur pendant la synchronisation:\nIls sont collationnés et listés à la fin de l'opération
+Masquer les messages d'erreur pendant la synchronisation :\nIls sont collationnés et listés à la fin de l'opération
Hints:
-Conseils:
+Conseils :
Homepage
Accueil
If you like FFS
@@ -465,13 +481,13 @@ Ignorer les erreurs ultérieures
Ignore this error, retry or abort synchronization?
Ignorer l'erreur, réessayer ou abandonner la synchronisation ?
Ignore this error, retry or abort?
-Ignorer l'erreur, réessayer ou abandonner?
+Ignorer l'erreur, réessayer ou abandonner ?
Include
Inclure
Include temporarily
Inclure temporairement
Include: *.doc;*.zip;*.exe\nExclude: \\temp\\*
-Inclure: *.doc;*.zip;*.exe\nExclure: \\temp\\*
+Inclure : *.doc;*.zip;*.exe\nExclure : \\temp\\*
Info
Info
Information
@@ -479,15 +495,15 @@ Information
Initialization of Recycle Bin failed!
Erreur lors de l'initialisation de la corbeille !
It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :)
-Impossible d'accéder à la corbeille!\n\nIl est probable que vous n'utilisez pas Windows.\nSi vous désirez utilisee cette fonctionnalité, veuillez contacter l'auteur. :)
+Impossible d'accéder à la corbeille !\n\nIl est probable que vous n'utilisez pas Windows.\nSi vous désirez utilisee cette fonctionnalité, veuillez contacter l'auteur. :)
Left:
-Gauche:
+Gauche :
Load configuration from file
Charger la configuration à partir du fichier
Load configuration history (press DEL to delete items)
Charger l'historique des configuration (appuyez sur Suppr pour supprimer des éléments)
Log-messages:
-Messages log:
+Messages log :
Logging
Connexion
Mirror ->>
@@ -495,17 +511,19 @@ Mirroir ->>
Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization.
Sauvegarde miroir du répertoire de gauche : Le répertoire de droite sera écrasé et exactement identique au répertoire de gauche après la synchronisation.
More than 50% of the total number of files will be copied or deleted!
-Plus de 50% des fichiers seront copiés ou détruits!
+Plus de 50% des fichiers seront copiés ou détruits !
Move column down
Déplacer la colonne vers le bas
Move column up
Déplacer la colonne vers le haut
+Moving %x to Recycle Bin
+Déplacement de %x vers la Corbeille
Not all items have been synchronized! Have a look at the list.
Tout n'a pas été synchronisé ! Vérifiez la liste.
Not enough free disk space available in:
Espace disque insuffisant sur :
Nothing to synchronize according to configuration!
-Rien à synchroniser dans cette configuration!
+Rien à synchroniser dans cette configuration !
Number of files and directories that will be created
Nombre de fichiers et de répertoires qui seront créés
Number of files and directories that will be deleted
@@ -515,27 +533,27 @@ Nombre de fichiers qui seront remplacés
OK
OK
Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the synchronization directories.
-Seuls les fichiers/répertoires filtrés seront sélectionnés pour la synchronisation. Le filtre sera appliqué aux noms relatifs pour la synchronisation.
+Seuls les fichiers/répertoires filtrés seront sélectionnés pour la synchronisation. Le filtre sera appliqué aux noms relatifs(!) pour la synchronisation.
Open with File Manager\tD-Click
Ouvrir avec le Gestionnaire de Fichiers\tClick droit
Operation aborted!
-Opération abandonnée!
+Opération abandonnée !
Operation:
-Opération:
+Opération :
Overview
Présentation
Pause
Pause
Paused
En pause
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Veuillez copier le fichier \"Shadow.dll\" (situé dans l'archive \"Shadow.zip\") vers le répertoire d'installation de FreeFileSync pour utiliser cette fonctionnalité.
Please fill all empty directory fields.
Veuillez remplir tous les champs vides du répertoire.
Press button to activate filter
Cliquez pour activer le filtrage
-Preview
-Prévoir
Published under the GNU General Public License:
-Publié sous la licence GNU General Public:
+Publié sous la licence GNU General Public :
Question
Question
Quit
@@ -549,7 +567,7 @@ Réinitialiser
Reset all warning messages
Réinitialisation de tous les avertissements
Reset all warning messages?
-Réinitialiser tous les avertissements?
+Réinitialiser tous les avertissements ?
Result
Situation
Right:
@@ -565,13 +583,13 @@ Enregistrer la configuration courante
Scanning...
Lecture en cours...
Scanning:
-Lecture en cours:
+Lecture en cours :
Select a folder
Choisissez un répertoire
Select logfile directory:
-Choisissez un dossier pour le fichier .log
+Choisissez un dossier pour le fichier .log :
Select variant:
-Choisissez une variante:
+Choisissez une variante :
Show conflicts
Afficher les conflits
Show file icons
@@ -607,13 +625,15 @@ Taille
Sorting file list...
Tri de la liste des fichiers...
Source code written completely in C++ utilizing:
-Code source écrit totalement en C++ et utilisant:
+Code source écrit totalement en C++ et utilisant :
Speed:
Vitesse :
Start
Démarrer
Start synchronization
Démarrer la synchronisation
+Statistics
+Statistiques
Stop
Arrêt
Swap sides
@@ -621,13 +641,11 @@ Permuter les côtés
Synchronization Preview
Prévisualisation de la synchronisation
Synchronization aborted!
-Synchronisation abandonnée!
+Synchronisation abandonnée !
Synchronization completed successfully!
-Synchronisation terminée avec succès!
+Synchronisation terminée avec succès !
Synchronization completed with errors!
-Synchronisation terminée avec des erreurs!
-Synchronization filter
-Filtre de synchronisation
+Synchronisation terminée avec des erreurs !
Synchronization settings
Paramétrage de la synchronisation
Synchronization status
@@ -635,15 +653,17 @@ Etat de la synchronisation
Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\".
Synchroniser rous les fichiers .doc, .zip et .exe sauf ceux du dossier \"temp\".
Synchronize both sides simultaneously: Copy new or updated files in both directions.
-Synchronisation simultanée des deux côtés. Copie des fichiers nouveaux ou mis à jour.
+Synchronisation simultanée des deux côtés : Copie des fichiers nouveaux ou mis à jour.
+Synchronize...
+Synchroniser...
Synchronizing...
Synchronisation en cours...
System out of memory!
-Erreur mémoire système!
+Erreur mémoire système !
Target file already existing!
-Le fichier de destination existe déjà!
+Le fichier de destination existe déjà !
The file does not contain a valid configuration:
-Le fichier ne contient pas de configuration valide
+Le fichier ne contient pas de configuration valide :
This commandline will be executed each time you doubleclick on a filename. %name serves as a placeholder for the selected file.
Cette ligne de commandes sera exécutée chaque fois que vous double-cliquerez sur un fichier. %name sert d'emplacement pour le fichier sélectionné.
This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time.
@@ -651,7 +671,7 @@ Cette variante définit comme identiques deux fichiers de même nom lorsqu'ils o
Time
Heure
Time elapsed:
-Temps écoulé:
+Temps écoulé :
Time remaining:
Temps restant :
Total amount of data that will be transferred
@@ -659,17 +679,17 @@ Volume de données à transférer
Total required free disk space:
Espace disque nécessaire :
Total time:
-Temps total:
+Temps total :
Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.
Traiter les heures qui différent exactement de +/- 1 heure comme égales, et celles qui diffèrent de moins d'une heure comme conflit sur la gestion de l'heure d'été.
Two way <->
Des 2 côtés <->
Unable to connect to sourceforge.net!
-Impossible de se connecter à sourceforge.net!
+Impossible de se connecter à sourceforge.net !
Unable to create logfile!
-Impossible de créer un fichier log!
+Impossible de créer un fichier log !
Unable to initialize Recycle Bin!
-Impossible d'initialiser la corbeille!
+Impossible d'initialiser la corbeille !
Uncheck all
Décocher tout
Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization.
@@ -680,14 +700,18 @@ Use Recycle Bin
Utilisation de la corbeille
Use Recycle Bin when deleting or overwriting files during synchronization
Utilisation de la corbeille lors de la suppression ou du remplacement des fichiers pendant la synchronisation
+Variant
+Variante
+Volume name %x not part of filename %y!
+Le nom de volume %x ne fait pas partie du nom de fichier %y !
Warning
Attention
Warning: Synchronization failed for %x item(s):
-Attention: La synchronisation a échouée pour %x élément(s):
+Attention : La synchronisation a échouée pour %x élément(s) :
Warnings:
-Avertissements:
+Avertissements :
When the comparison is started with this option set the following decision tree is processed:
-Lorsque la comparaison démarre avec cette option, l'arbre de décision suivant est exécuté:
+Lorsque la comparaison démarre avec cette option, l'arbre de décision suivant est exécuté :
You may try to synchronize remaining items again (WITHOUT having to re-compare)!
Vous pouvez essayer de synchroniser à nouveau les éléments restants (SANS avoir à les re-comparer) !
different
diff --git a/Languages/german.lng b/BUILD/Languages/german.lng
index 01b69eb9..08ceea4b 100644
--- a/Languages/german.lng
+++ b/BUILD/Languages/german.lng
@@ -176,6 +176,8 @@ Build:
Build:
Cancel
Abbrechen
+Change direction
+Richtung ändern
Check all
Alles auswählen
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Eigene Synchronisationsregeln definieren.
Confirm
Bestätigen
+Conflict detected:
+Ein Konflikt wurde erkannt:
Continue
Fortfahren
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Kopiere Datei %x nach %y
Copying file %x to %y overwriting target
Kopiere Datei %x nach %y und überschreibe Ziel
+Could not determine volume name for file:
+Der Laufwerksname für folgende Datei konnte nicht ermittelt werden:
Could not set working directory:
Das Arbeitsverzeichnis konnte nicht gesetzt werden:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
Das Verzeichnis existiert nicht:
Do not display visual status information but write to a logfile instead
Keine graphischen Statusinformationen anzeigen, sondern eine Logdatei schreiben
-Do not show this warning again
-Diese Warnung nicht mehr anzeigen
+Do not show this dialog again
+Diesen Dialog nicht mehr anzeigen
Do nothing
Nichts tun
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Fehler beim Setzen der Dateiänderungszeit:
Error copying file:
Fehler beim Kopieren der Datei:
+Error copying locked file %x!
+Fehler beim Kopieren der gesperrten Datei %x!
Error creating directory:
Fehler beim Erstellen des Verzeichnisses:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Fehler beim Auflösen des Symbolischen Links:
Error retrieving full path:
Fehler beim Ermitteln des kompletten Pfades:
+Error starting Volume Shadow Copy Service!
+Fehler beim Starten des Volume Shadow Copy Service!
Error traversing directory:
Fehler beim Durchsuchen des Verzeichnisses:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Beenden mit RC < 0
Feedback and suggestions are welcome at:
Feedback und Vorschläge sind willkommen unter:
+File %x has an invalid date!
+Die Datei %x hat ein ungültiges Datum!
File Manager integration:
Einbinden des Dateimanagers:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Dateiänderungszeiten, die um bis zu der angegebenen Anzahl an Sekunden abweichen, werden trotzdem als gleich angesehen.
Filename
Dateiname
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Die Dateien %x haben eine Abweichung der Dateizeit von unter einer Stunde! Aufgrund der Zeitumstellungsproblematik kann nicht zweifelsfrei festgestellt werden, welche die aktuellere ist.
+Files %x have the same date but a different size!
+Die Dateien %x haben dasselbe Datum, aber eine unterschiedliche Größe!
Files are found equal if\n - file content\nis the same.
Dateien gelten als gleich, wenn\n - der Inhalt\ngleich ist.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Spalte nach unten verschieben
Move column up
Spalte nach oben verschieben
+Moving %x to Recycle Bin
+Verschiebe %x in den Papierkorb
Not all items have been synchronized! Have a look at the list.
Nicht alle Elemente wurden synchronisiert! Siehe verbliebene Elemente im Hauptfenster.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pause
Paused
Angehalten
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Um diese Funktionalität zu aktivieren, bitte die entsprechende Datei \"Shadow.dll\" (siehe Archiv \"Shadow.zip\") in das FreeFileSync Installationsverzeichnis kopieren.
Please fill all empty directory fields.
Bitte die leeren Verzeichnisfelder füllen.
Press button to activate filter
Taste drücken, um Filter zu aktivieren
-Preview
-Vorschau
Published under the GNU General Public License:
Veröffentlicht unter der GNU General Public License:
Question
@@ -614,6 +632,8 @@ Start
Start
Start synchronization
Synchronisation starten
+Statistics
+Statistiken
Stop
Stop
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Synchronisation erfolgreich abgeschlossen!
Synchronization completed with errors!
Synchronisation mit Fehlern abgeschlossen!
-Synchronization filter
-Filter für Synchronisation
Synchronization settings
Synchronisationseinstellungen
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Alle .doc, .zip und .exe Dateien mit Ausnahme des Verzeichnisses \"temp\" werden synchronisiert.
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Beide Seiten gleichzeitig synchronisieren: Neue oder aktualisierte Dateien werden in beide Richtungen kopiert.
+Synchronize...
+Synchronisieren
Synchronizing...
Synchronisiere...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Papierkorb verwenden
Use Recycle Bin when deleting or overwriting files during synchronization
Papierkorb für zu löschende oder zu überschreibende Dateien nutzen
+Variant
+Variante
+Volume name %x not part of filename %y!
+Laufwerksname %x ist kein Teil des Dateinamens %y!
Warning
Warnung
Warning: Synchronization failed for %x item(s):
@@ -687,7 +711,7 @@ Warnung: Synchronisation fehlgeschlagen für %x Element(e):
Warnings:
Warnungen:
When the comparison is started with this option set the following decision tree is processed:
-Wenn der Vergleich mit dieser Option gestarted wurde, wird folgender Entscheidungsbaum abgearbeitet:
+Wenn der Vergleich mit dieser Option gestartet wurde, wird folgender Entscheidungsbaum abgearbeitet:
You may try to synchronize remaining items again (WITHOUT having to re-compare)!
Verbliebene Elemente können nochmals synchronisiert werden (OHNE dass ein erneuter Vergleich notwendig ist)!
different
diff --git a/Languages/hungarian.lng b/BUILD/Languages/hungarian.lng
index 5311e56b..6cf67623 100644
--- a/Languages/hungarian.lng
+++ b/BUILD/Languages/hungarian.lng
@@ -11,23 +11,23 @@
TB
TB
day(s)
-
+ nap
hour(s)
-
+ óra
kB
kB
min
-
+ perc
sec
-
+ másodperc
!= files are different\n
!= a fájlok különböznek\n
%x directories
-%x könyvtár
+%x mappa
%x files,
%x fájl,
%x is not a valid FreeFileSync batch file!
-
+A(z) %x nem megfelelő FreeFileSync kötegelt feladat fájl!
%x of %y rows in view
%x sor látható a(z) %y sorból
%x of 1 row in view
@@ -43,7 +43,7 @@
&Cancel
&Mégsem
&Check for new version
-
+&Új verzió keresése
&Create batch job
&Kötegelt feladat létrehozása
&Default
@@ -65,7 +65,7 @@
&Load configuration
&Beállítások betöltése
&No
-
+&Nem
&OK
&OK
&Pause
@@ -77,19 +77,19 @@
&Save
&Mestés
&Yes
-
+&Igen
,
.
- do not copy\n
-
+- nem másolni\n
- conflict
-
+- ütközés
- conflict (same date, different size)
-
+- ütközés (ugyanaz a dátum, különböző méret)
- different
- különböző
- equal
-- egyforma
+- egyezik
- exists left only
- csak a bal oldalon létezik
- exists right only
@@ -103,21 +103,21 @@
- right newer
- a jobb oldali újabb
-> copy to right side\n
-
+-> másolni a jobb oldalra\n
-Open-Source file synchronization-
-Nyílt forráskódú fájlszinkronizálás-
.
,
/sec
-
+/másodperc
1 directory
-1 könyvtár
+1 mappa
1 file,
1 fájl,
1. &Compare
1. &Összehasonlítás
1. Enter relative file or directory names separated by ';' or a new line.
-
+1. A relatív fájl- és mappanevek megadása pontosvesszővel elválasztva vagy új sorban.
2. &Synchronize...
2. &Szinkronizálás
2. Use wildcard characters '*' and '?'.
@@ -125,11 +125,11 @@
3. Exclude files directly on main grid via context menu.
3. Fájlok közvetlen kizárása a fő listából helyi menü segítségével.
<- copy to left side\n
-
+<- másolni a bal oldalra\n
<< left file is newer\n
<< a bal oldali fájl újabb\n
<Directory>
-<Könyvtár>
+<Mappa>
<Last session>
<Utolsó munkamenet>
<multiple selection>
@@ -137,11 +137,11 @@
<| file on left side only\n
<| csak a bal oldalon lévő fájl\n
== files are equal\n
-
+== egyező fájlok\n
>> right file is newer\n
>> a jobb oldali fájl újabb\n
A newer version of FreeFileSync is available:
-
+Elérhető a FreeFileSync egy újabb verziója:
Abort requested: Waiting for current operation to finish...
Megszakítási kérelem: Várakozás a folyamatban lévő művelet befejezésére...
Aborted
@@ -151,7 +151,7 @@ A programról
Action
Művelet
Add folder pair
-Könyvtár pár megadása
+Mappa pár megadása
All items have been synchronized!
Minden elem szinkronizálva lett!
An exception occured!
@@ -171,19 +171,21 @@ Kötegelt feladat
Big thanks for localizing FreeFileSync goes out to:
Nagy köszönet a FreeFileSync lokalizációjáért\na következő személyeknek:
Browse
-
+Tallózás
Build:
Build:
Cancel
Mégsem
+Change direction
+Irány megváltoztatása
Check all
Mindent kijelöl
Choose to hide filtered files/directories from list
-Szűrt fájlok/könyvtárak elrejése a listában
+Szűrt fájlok/mappák elrejtése a listában
Comma separated list
Comma separated values
Compare
-
+Összehasonlítás
Compare both sides
Mindkét oldal összehasonlítása
Compare by \"File content\"
@@ -197,9 +199,9 @@ Tartalom összehasonlítása
Comparing content of files %x
%x fájlok tartalmának összehasonlítása
Comparing content...
-
+Tartalom összehasonlítása...
Comparison Result
-
+Az összehasonlítás eredménye
Completed
Befejezve
Configuration
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Saját szinkronizálási szabályok beállítása.
Confirm
Megerősítés
+Conflict detected:
+Ütközés történt:
Continue
Folytatás
Conversion error:
@@ -231,19 +235,21 @@ Másolás a jobb oldalról a bal oldalra
Copy from right to left overwriting
Másolás a jobb oldalról a bal oldalra felülírással
Copy new or updated files to right folder.
-Új vagy frissített fájlok másolása a jobb oldali könyvtárba.
+Új vagy frissített fájlok másolása a jobb oldali mappába.
Copy to clipboard\tCTRL+C
Másolás a vágólapra\tCTRL+C
Copying file %x to %y
%x fájl másolása a(z) %y fájlba
Copying file %x to %y overwriting target
-
+A(z) %x fájl másolása a(z) %y fájlba fölülírva a célt
+Could not determine volume name for file:
+A következő fájlnak nem lehet meghatározni a kötetnevét:
Could not set working directory:
-Munkakönyvtár beállítása sikertelen:
+Munkamappa beállítása sikertelen:
Create a batch job
Kötegelt feladat létrehozása
Creating folder %x
-Könyvtár létrehozása %x
+%x mappa létrehozása
Current operation:
Aktuális művelet:
Custom
@@ -257,9 +263,9 @@ Hátralévő adat:
Date
Dátum
Delete files/folders existing on left side only
-Csak a bal oldalon létező fájlok/könyvtárak törlése
+Csak a bal oldalon létező fájlok/mappák törlése
Delete files/folders existing on right side only
-Csak a jobb oldalon létező fájlok/könyvtárak törlése
+Csak a jobb oldalon létező fájlok/mappák törlése
Delete files\tDEL
Fájlok törlése\tDEL
Delete on both sides
@@ -269,17 +275,17 @@ Törlés mindkét oldalon, még akkor is, ha csak egyik oldalon lett kijelölve
Deleting file %x
Fájl törlése %x
Deleting folder %x
-Könyvtár törlése %x
+Mappa törlése %x
Directories are dependent! Be careful when setting up synchronization rules:
-A könyvtárak függenek egymástól! Legyen óvatos, amikor megadja a szinkronizálási szabályokat:
+A mappák függenek egymástól! Legyen óvatos, amikor megadja a szinkronizálási szabályokat:
Directory
-
+Mappa
Directory does not exist:
-A könyvtár nem létezik:
+A mappa nem létezik:
Do not display visual status information but write to a logfile instead
-
-Do not show this warning again
-Ennek a figyelmeztetésnek az elrejtése legközelebb
+Ne mutasd a vizuális állapotinformációkat, helyette naplózd
+Do not show this dialog again
+Ne mutasd újra ezt a párbeszédablakot
Do nothing
Nincs mit csinálni
Do you really want to delete the following objects(s)?
@@ -287,29 +293,31 @@ Valóban törölni akarja a az alábbi objektumo(ka)t?
Do you really want to move the following objects(s) to the Recycle Bin?
Valóban a Lomtárba (Recycle Bin) akarja mozgatni az alábbi objektumo(ka)t?
Do you want FreeFileSync to automatically check for updates every week?
-
+Akarod, hogy a FreeFileSync automatikusan minden héten keressen frissítést?
Don't ask me again
-
+Ne kérdezd még egyszer
Donate with PayPal
Ha szereted a FreeFileSync-et, támogasd a PayPal segítségével.
Download now?
-
+Letöltsem most?
Drag && drop
Húzd && Ejtsd
Email
-
+E-mail
Enable filter to exclude files from synchronization
-
+Szűrő engedélyezése fájlok a szinkronizációból való kizárásához
Error
Hiba
Error changing modification time:
Az utolsó változtatás dátumának módosítása sikertelen:
Error copying file:
A fájl másolása sikertelen:
+Error copying locked file %x!
+Hiba történt a(z) %x zárolt fájl másolása közben!
Error creating directory:
-A könyvtár létrehozása sikertelen:
+A mappa létrehozása sikertelen:
Error deleting directory:
-A könyvtár törlése sikertelen:
+A mappa törlése sikertelen:
Error deleting file:
A fájl törlése sikertelen:
Error handling
@@ -329,21 +337,23 @@ A fájl olvasása sikertelen:
Error resolving symbolic link:
A szimbolikus link feloldása sikertelen:
Error retrieving full path:
-
+A teljes elérési útvonal meghatározása sikertelen:
+Error starting Volume Shadow Copy Service!
+Hiba történt a Volume Shadow Copy szolgáltatás indítása közben!
Error traversing directory:
-Könyvtár átnézése sikertelen:
+A mappa átnézése sikertelen:
Error writing file attributes:
A fájl attribútumainak írása sikertelen:
Error writing file:
A fájl írása sikertelen:
Error: Source directory does not exist anymore:
-Hiba: A forráskönyvtár többé nem létezik:
+Hiba: A forrásként megadott mappa többé nem létezik:
Example
Példa
Exclude
-Kizárás
+Kizár
Exclude temporarily
-Ideiglenes kizárás
+Ideiglenesen kizár
Exclude via filter:
Kizárás szűrő segítségével:
Exit immediately and set returncode < 0
@@ -352,10 +362,12 @@ Exit with RC < 0
Kilépés (visszatérési érték < 0)
Feedback and suggestions are welcome at:
A visszajelzéseket és javaslatokat ide várjuk:
+File %x has an invalid date!
+A(z) %x fájlnak érvénytelen a dátuma!
File Manager integration:
Beépülés a Fájlkezelőbe:
File Time tolerance (seconds):
-
+Fájl dátum tolerancia (másodpercek):
File already exists. Overwrite?
A fájl már létezik. Felülírjuk?
File content
@@ -367,13 +379,17 @@ A fájllista exportálása befejeződött!
File size and date
fájlméret és dátum alapján
File times that differ by up to the specified number of seconds are still handled as having same time.
-Két fájl, melyeknek dátuma legfeljebb az itt megadott másodperccel tér el egymástól, úgy lesz kezelve, mintha egyforma lenne a dátumuk.
+Két fájl, melyeknek dátuma legfeljebb az itt megadott másodperccel tér el egymástól, úgy lesz kezelve, mintha megegyezne a dátumuk.
Filename
Fájlnév
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+A(z) %x fájlok dátuma kevesebb mint 1 órával eltér! A nyári időszámítás miatt nem biztonságos annak eldöntése, hogy melyik az újabb közülük.
+Files %x have the same date but a different size!
+A(z) %x fájlok dátuma megegyezik, de a mérete nem!
Files are found equal if\n - file content\nis the same.
-A fájlok megegyeznek ha\n - a fájlok tartalma\nmegegyezik.
+A fájlok megegyező ha\n - a fájlok tartalma\nmegegyezik.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
-A fájlok megegyeznek ha\n - a fájlméret\n - az utolsó módosítás dátuma\nmegegyezik.
+A fájlok megegyező ha\n - a fájlméret\n - az utolsó módosítás dátuma\nmegegyezik.
Files remaining:
Hátralévő fájlok:
Files that exist on both sides and have different content
@@ -383,15 +399,15 @@ Mindkét oldalon létező fájlok, de a bal oldali újabb
Files that exist on both sides, right one is newer
Mindkét oldalon létező fájlok, de a jobb oldali újabb
Files/folders remaining:
-Hátralévő fájlok/könyvtárak:
+Hátralévő fájlok/mappák:
Files/folders scanned:
-Vizsgált fájlok/könyvtárak:
+Vizsgált fájlok/mappák:
Files/folders that exist on left side only
-Csak a bal oldalon létező fájlok/könyvtárak
+Csak a bal oldalon létező fájlok/mappák
Files/folders that exist on right side only
-Csak a jobb oldalon létező fájlok/könyvtárak
+Csak a jobb oldalon létező fájlok/mappák
Filter
-
+Szűrő
Filter active: Press again to deactivate
Szűrő aktív: Nyomja meg újra a deaktiváláshoz
Filter files
@@ -399,11 +415,11 @@ Fájlok szűrése
Filter view
Szűrő nézet
Folder Comparison and Synchronization
-Könyvtár összehasonlítás és szinkronizáció
+Mappa összehasonlítás és szinkronizáció
Folder pair
-Könyvtár pár
+Mappa pár
FreeFileSync - Folder Comparison and Synchronization
-FreeFileSync - Könyvtár összehasonlítás és szinkronizáció
+FreeFileSync - Mappa összehasonlítás és szinkronizáció
FreeFileSync Batch Job
FreeFileSync kötegelt feladat
FreeFileSync at Sourceforge
@@ -413,9 +429,9 @@ FreeFileSync kötegelt fájl
FreeFileSync configuration
FreeFileSync beállítások
FreeFileSync is up to date!
-
+A FreeFileSync naprakész!
Full path
-
+Teljes elérési útvonal
Generating file list...
Fájllista generálása...
Global settings
@@ -425,7 +441,7 @@ Súgó
Hide all error and warning messages
Összes hibaüzenet és figyelmeztetés elrejtése
Hide conflicts
-
+Ütközések elrejtése
Hide files that are different
A nem egyező fájlok elrejtése
Hide files that are equal
@@ -439,11 +455,11 @@ Csak a bal oldalon létező fájlok elrejtése
Hide files that exist on right side only
Csak a jobb oldalon létező fájlok elrejtése
Hide files that will be copied to the left side
-
+A bal oldalra másolandó fájlok elrejtése
Hide files that will be copied to the right side
-
+A jobb oldalra másolandó fájlok elrejtése
Hide files that won't be copied
-
+A nem másolandó fájlok elrejtése
Hide filtered items
A szűrt elemek elrejtése
Hide further error messages during the current process
@@ -453,11 +469,11 @@ Hibaüzenetek elrejtése szinkronizálás közben:\nÖssze lesznek gyűjtve és
Hints:
Tippek:
Homepage
-
+Honlap
If you like FFS
FFS támogatása
Ignore 1-hour file time difference
-
+1 órás fájl dátum különbségek figyelmen kívül hagyása
Ignore errors
Hibák figyelmen kívül hagyása
Ignore subsequent errors
@@ -467,11 +483,11 @@ Figyelmen kívül hagyja ezt a hibát, újra megpróbálja vagy megszakítja a s
Ignore this error, retry or abort?
Figyelmen kívül hagyja ezt a hibát, újra megpróbálja vagy megszakítja?
Include
-Tartalmaz
+Csatol
Include temporarily
Ideiglenesen tartalmaz
Include: *.doc;*.zip;*.exe\nExclude: \\temp\\*
-
+Csatol: *.doc;*.zip;*.exe\nKizár: \\temp\\*
Info
Információ
Information
@@ -481,7 +497,7 @@ A Lomtár (Recycle Bin) inicializálása sikertelen!
It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :)
Lehetetlen a Lomtár (Recycle Bin) inicializálása!\n\nValószínűleg azért, mert nem Windost használ.\nHa szeretné ezt a funkciót használni, kérjük, lépjen kapcsolatba a szerzővel. :)
Left:
-
+Bal oldal:
Load configuration from file
Beállítások betöltése fájlból
Load configuration history (press DEL to delete items)
@@ -489,33 +505,35 @@ Beállítások előzményeinek a betöltése (Nyomja meg a DEL gombot a törlés
Log-messages:
Naplóbejegyzések:
Logging
-
+Naplózás
Mirror ->>
Tükrözés ->>
Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization.
-A bal oldali könyvtár tükrözött másolata: A jobb oldali könyvtár felülíródik és pontosan megegyezik majd a bal oldalival a szinkronizálás után.
+A bal oldali mappa tükrözött másolata: A jobb oldali mappa felülíródik és pontosan megegyezik majd a bal oldalival a szinkronizálás után.
More than 50% of the total number of files will be copied or deleted!
-
+Az összes fájl több mint 50%-a másolva vagy törölve lesz!
Move column down
Oszlop mozgatása lefelé
Move column up
Oszlop mozgatása felfelé
+Moving %x to Recycle Bin
+%x mozgatása a Lomtárba
Not all items have been synchronized! Have a look at the list.
-
+Nem minden elem szinkronizálódott! Tekintsd meg a listát.
Not enough free disk space available in:
-
+Nincs elég szabad lemezterület:
Nothing to synchronize according to configuration!
A beállításoknak megfelelően nincs mit szinkronizálni!
Number of files and directories that will be created
-A létrehozandó fájlok és könyvtárak száma
+A létrehozandó fájlok és mappák száma
Number of files and directories that will be deleted
-A törlendő fájlok és könyvtárak száma
+A törlendő fájlok és mappák száma
Number of files that will be overwritten
A felülírandó fájlok száma
OK
OK
Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the synchronization directories.
-
+Csak azok a fájlok/mappák lesznek kijelölve a szinkronizációhoz, amelyek átmennek a szűrésen. A szűrő a szinkronizálás mappájához relatív(!) nevekre lesz alkalmazva.
Open with File Manager\tD-Click
Megnyitás a Fájlkezelőben\tD-Click
Operation aborted!
@@ -523,43 +541,43 @@ Művelet megszakítva!
Operation:
Művelet:
Overview
-
+Összefoglaló
Pause
Szünet
Paused
-
+Szüneteltetve
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Ennek a funkciónak a használatához, kérjük, másold a megfelelő \"Shadow.dll\" fájlt (megtalálható a \"Shadow.zip\" archívumban) abba a mappába, amelybe a FreeFileSync-et telepítetted.
Please fill all empty directory fields.
-Kérjük, töltse ki az összes üres könyvtár mezőt.
+Kérjük, töltse ki az összes üres mappa mezőt.
Press button to activate filter
Nyomja meg a gombot a szűrő aktiválásához
-Preview
-Előnézet
Published under the GNU General Public License:
Kiadva a GNU General Public License alatt:
Question
-
+Kérdés
Quit
Kilépés
Relative path
Relatív útvonal
Remove folder pair
-Könyvtár párok eltávolítása
+Mappa párok eltávolítása
Reset
Helyreállítás
Reset all warning messages
-
+Összes figyelmeztető üzenet helyreállítása
Reset all warning messages?
Helyreállítja az összes figyelmeztető üzenetet?
Result
Eredmény
Right:
-
+Jobb oldal:
S&ave configuration
Beállítások mentés&e
S&witch view
-
+Nézet v&áltása
Save changes to current configuration?
-
+Mentsük a beállítások változásait?
Save current configuration to file
Aktuális beállítások mentése fájlba
Scanning...
@@ -567,15 +585,15 @@ Vizsgálat folyamatban...
Scanning:
Vizsgálat:
Select a folder
-Könyvtár kiválasztása
+Mappa kiválasztása
Select logfile directory:
-
+Naplófájl mappájának kiválasztása:
Select variant:
Változat kiválasztása:
Show conflicts
-
+Ütközések mutatása
Show file icons
-
+Fájlok ikonjainak mutatása
Show files that are different
Eltérő fájlok mutatása
Show files that are equal
@@ -589,17 +607,17 @@ Csak a bal oldalon létező fájlok mutatása
Show files that exist on right side only
Csak a jobb oldalon létező fájlok mutatása
Show files that will be copied to the left side
-
+A bal oldalra másolandó fájlok mutatása
Show files that will be copied to the right side
-
+A jobb oldalra másolandó fájlok mutatása
Show files that won't be copied
-
+A nem másolandó fájlok mutatása
Show popup
Felbukkanó ablak mutatása
Show popup on errors or warnings
Értesítés felbukkanó ablakban a hibákról és figyelmeztetésekről
Significant difference detected:
-
+Jelentős különbség érzékelve:
Silent mode
Csendes mód
Size
@@ -609,33 +627,35 @@ Fájllista rendezése...
Source code written completely in C++ utilizing:
A forráskód teljes egészében C++-ban íródott\na következők felhasználásával:
Speed:
-
+Sebesség:
Start
Indítás
Start synchronization
Szinkronizáció indítása
+Statistics
+Statisztikák
Stop
Megállítás
Swap sides
Oldalak felcserélése
Synchronization Preview
-
+Szinkronizáció előnézete
Synchronization aborted!
A szinkronizáció megszakítva!
Synchronization completed successfully!
A szinkronizáció sikeresen befejeződött!
Synchronization completed with errors!
A szinkronizáció befejeződött, de akadtak hibák!
-Synchronization filter
-Szinkronizáció szűrője
Synchronization settings
Szinkronizáció beállításai
Synchronization status
Szinkronizáció állapota
Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\".
-
+Minden .doc, .zip és .exe fájl szinkronizálása a \"temp\" almappában találhatók kivételével.
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Mindkét oldal szinkronizálása egyszerre: Új és frissített fájlok másolása mindkét irányban.
+Synchronize...
+Szinkronizálás
Synchronizing...
Szinkronizálás folyamatban...
System out of memory!
@@ -647,25 +667,25 @@ A következő fájl nem tartalmaz érvényes beállításokat:
This commandline will be executed each time you doubleclick on a filename. %name serves as a placeholder for the selected file.
Ez a parancssor lesz végrehajtva minden fájlnéven történő dupla kattintás esetében. %name helyettesíti a kiválasztott fájlt.
This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time.
-Ez a változat akkor tekint egyformának két azonos nevű fájlt, ha azok mérete ÉS az utolsó módosításuk ideje azonos.
+Ez a változat akkor tekint egyezőnek két azonos nevű fájlt, ha azok mérete ÉS az utolsó módosításuk ideje azonos.
Time
Idő
Time elapsed:
Eltelt idő:
Time remaining:
-
+Hátralévő idő:
Total amount of data that will be transferred
A mozgatandó adatok összmérete
Total required free disk space:
-
+Összes igényelt szabad lemezterület:
Total time:
Becsült idő:
Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.
-
+A fájlok dátumának pontosan +/- 1 órával való eltérése esetén a fájlok egyeznek, a kevesebb mint 1 órával való eltérés esetén pedig ütköznek, a Nyári Időszámítás kezeléséhez.
Two way <->
Kétirányú <->
Unable to connect to sourceforge.net!
-
+A csatlakozás a sourceforge.net-hez sikertelen!
Unable to create logfile!
Nem lehet létrehozni a naplófájlt!
Unable to initialize Recycle Bin!
@@ -673,13 +693,17 @@ Nem lehet inicializálni a Lomtárat (Recycle Bin)!
Uncheck all
Összes kijelölést megszűntet
Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization.
-
+Feloldatlan ütközések vannak! \n\nFigyelmen kívül hagyhatod az ütközéseket és folytathatod a szinkronizálást.
Update ->
Frissítés ->
Use Recycle Bin
Lomtár (Recycle Bin) használata
Use Recycle Bin when deleting or overwriting files during synchronization
A Lomtár (Recycle Bin) használata fájlok szinkronizálása közbeni törlésnél vagy felülírásnál
+Variant
+Variáns
+Volume name %x not part of filename %y!
+A(z) %x kötetnevet nem tartalmazza a(z) %y fájlnév!
Warning
Figyelem
Warning: Synchronization failed for %x item(s):
@@ -695,7 +719,7 @@ különböző
file exists on both sides
mindkét oldalon létező fájlok
flash conflict\n
-
+jelzés ütközés\n
on one side only
csak az egy oldalon létező fájlok
|> file on right side only\n
diff --git a/Languages/italian.lng b/BUILD/Languages/italian.lng
index 207294c4..8a1f1332 100644
--- a/Languages/italian.lng
+++ b/BUILD/Languages/italian.lng
@@ -176,6 +176,8 @@ Build:
Build:
Cancel
Annulla
+Change direction
+Cambia direzione
Check all
Seleziona tutto
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Configura le tue regole di sincronizzazione.
Confirm
Conferma
+Conflict detected:
+Rilevato conflitto:
Continue
Continua
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Copia di file da %x a %y
Copying file %x to %y overwriting target
Copia file %x su %y sovrascrivendo la destinazione
+Could not determine volume name for file:
+Impossibile determinare il nome volume per il file:
Could not set working directory:
Impossibile definire la directory di lavoro:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
La directory non esiste:
Do not display visual status information but write to a logfile instead
Non visualizzare le informazioni di stato ma scrivile in un file di log
-Do not show this warning again
-Non mostrare più questo messaggio
+Do not show this dialog again
+Non visualizzare più questo messaggio
Do nothing
Non fare nulla
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Errore durante la modifica della data:
Error copying file:
Errore durante la copia del file:
+Error copying locked file %x!
+Errore durante la copia del file bloccato %x!
Error creating directory:
Errore durante la creazione della directory:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Errore nella risoluzione di collegamento simbolico:
Error retrieving full path:
Errore nel reperire il percorso completo:
+Error starting Volume Shadow Copy Service!
+Errore in avvio del Servizio Volume Shadow Copy!
Error traversing directory:
Errore nel percorso della directory:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Esci con RC < 0
Feedback and suggestions are welcome at:
Commenti e suggerimenti sono i benvenuti:
+File %x has an invalid date!
+Il file %x ha una data non valida!
File Manager integration:
Integrazione File Manager:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
File time che differiscono per meno dello specificato numero di secondi sono considerati come aventi lo stesso File time.
Filename
Nome del file
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+La data dei file %x differisce per meno di 1 ora! Non è sicuro decidere quale dei due è il più recente con la funzione Daylight Saving Time.
+Files %x have the same date but a different size!
+I file %x hanno la stessa data ma dimensione diversa!
Files are found equal if\n - file content\nis the same.
I file sono considerati identici se\n - il contenuto\nè identico.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Sposta colonna giu'
Move column up
Sposta colonna su'
+Moving %x to Recycle Bin
+Spostamento di %x nel Cestino
Not all items have been synchronized! Have a look at the list.
Non tutti gli oggetti sono stati sincronizzati! Controlla la lista.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pausa
Paused
In pausa
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Per abilitare questa funzione è necessario copiare l'appropriata \"Shadow.dll\" (che si trova nell'archivio \"Shadow.zip\") nella directory di installazione di FreeFileSync.
Please fill all empty directory fields.
Compilare tutti i campi di directory vuoti.
Press button to activate filter
Cliccare per attivare il filtro
-Preview
-Anteprima
Published under the GNU General Public License:
Pubblicato sotto licenza GNU General Public:
Question
@@ -614,6 +632,8 @@ Start
Avvia
Start synchronization
Avvia sincronizzazione
+Statistics
+Statistiche
Stop
Stop
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Sincronizzazione completata con successo!
Synchronization completed with errors!
Sincronizzazione terminata con errori!
-Synchronization filter
-Filtro di sincronizzazione
Synchronization settings
Parametri di sincronizzazione
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Sincronizza tutti i file .doc, .zip e .exe eccetto tutti quelli nella cartella \"temp\".
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Sincronizza simultaneamente entrambi i lati: Copia file nuovi o aggiornati in entrambe le direzioni.
+Synchronize...
+Sincronizza...
Synchronizing...
Sincronizzazione in corso...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Usa il Cestino
Use Recycle Bin when deleting or overwriting files during synchronization
Usa il Cestino quando si cancella o sovrascrivono file durante la sincronizzazione
+Variant
+Variante
+Volume name %x not part of filename %y!
+Il nome volume %x non è parte del nome file %y!
Warning
Attenzione
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/japanese.lng b/BUILD/Languages/japanese.lng
index ae591d05..6ac7f498 100644
--- a/Languages/japanese.lng
+++ b/BUILD/Languages/japanese.lng
@@ -176,6 +176,8 @@ Build:
ビルド:
Cancel
中止
+Change direction
+方向を変更
Check all
すべて選択
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
あなたの設定した同期規則
Confirm
確認
+Conflict detected:
+検出された競合:
Continue
続行
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
ファイル %x を %y にコピー中
Copying file %x to %y overwriting target
ファイル %x をコピー、%y に上書き中
+Could not determine volume name for file:
+ファイルのボリューム名が決定されていません:
Could not set working directory:
作業ディレクトリが設定できません:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
ディレクトリが存在しません:
Do not display visual status information but write to a logfile instead
進捗状況などのメッセージを表示しないで、ログファイルの書き込みは実施する。
-Do not show this warning again
-次回からこの警告を表示しない
+Do not show this dialog again
+次回から表示しない
Do nothing
何もしない
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
時間の修正中のエラー:
Error copying file:
ファイルのコピーに失敗:
+Error copying locked file %x!
+コピーに失敗! ファイル%x はロックされています!
Error creating directory:
ディレクトリ作成エラー:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
シンボリックリンクの解決に失敗:
Error retrieving full path:
フルパスの取得に失敗:
+Error starting Volume Shadow Copy Service!
+ボリュームシャドウコピーの開始に失敗!
Error traversing directory:
ディレクトリの移動エラー:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
RC で終了 < 0
Feedback and suggestions are welcome at:
フィードバック、提案など:
+File %x has an invalid date!
+ファイル %x の日付は無効なものです!
File Manager integration:
ファイラとの統合:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
ファイル時刻の指定された秒以内の誤差は、同じものとして取り扱われます。
Filename
ファイル名
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+ファイル %x の時間には、一時間未満の誤差があります! 夏時間の問題により、より新しい方を時間で決定するのは安全ではありません。
+Files %x have the same date but a different size!
+ファイル %x は、同じ時間ですがサイズが異なっています!
Files are found equal if\n - file content\nis the same.
ファイルが同様だった場合\n - ファイル内容\nで判断する
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
列を下に移動
Move column up
列を上に移動
+Moving %x to Recycle Bin
+%x をゴミ箱に移動中
Not all items have been synchronized! Have a look at the list.
すべてのアイテムは同期されていません、リストを確認してください
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
一時停止
Paused
一時停止中
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+ \"Shadow.dll\" (\"Shadow.zip\" アーカイブ内) を、FreeFileSync インストールフォルダにコピーすることで、この機能を利用できるようになります。
Please fill all empty directory fields.
アイテムが選択されていません!
Press button to activate filter
ボタンをクリックで有効化
-Preview
-プレビュー
Published under the GNU General Public License:
Published under the GNU General Public License:
Question
@@ -614,6 +632,8 @@ Start
開始
Start synchronization
同期の開始
+Statistics
+統計
Stop
停止
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
同期処理はすべて正常に完了しました!
Synchronization completed with errors!
同期処理は、エラーで終了しています!
-Synchronization filter
-同期フィルター
Synchronization settings
同期処理設定
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
\"temp\" のサブフォルダを除いて、すべての.doc、.zip、および.exeファイルを同期
Synchronize both sides simultaneously: Copy new or updated files in both directions.
両側を同時に処理: 両方のディレクトリのより新しいファイルをコピー
+Synchronize...
+同期処理...
Synchronizing...
同期処理中...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
ゴミ箱を使用
Use Recycle Bin when deleting or overwriting files during synchronization
同期処理の間、ファイルの上書き/削除をする時にゴミ箱を使用
+Variant
+変化
+Volume name %x not part of filename %y!
+ボリューム名 %x にファイル名 %y はありません!
Warning
警告
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/polish.lng b/BUILD/Languages/polish.lng
index 324542c9..fae04f18 100644
--- a/Languages/polish.lng
+++ b/BUILD/Languages/polish.lng
@@ -176,6 +176,8 @@ Build:
Buduj:
Cancel
Anuluj
+Change direction
+Zmień kierunek
Check all
Sprawdź wszystko
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Skonfiguruj swoje własne zasady synchronizacji.
Confirm
Potwierdź
+Conflict detected:
+Wykryto konflikt:
Continue
Kontynuuj
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Kopiowanie pliku %x do %y
Copying file %x to %y overwriting target
Nadpisywanie pliku %y plikiem %x
+Could not determine volume name for file:
+Nie można określić nazwy dysku dla pliku:
Could not set working directory:
Nie można ustawić poprawnego folderu:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
Katalog nie istnieje:
Do not display visual status information but write to a logfile instead
Nie wyświetla informacji o statusie, ale tworzy plik z logami
-Do not show this warning again
-Nie pokazuj tego ostrzeżenia ponownie
+Do not show this dialog again
+Nie pokazuj tego okna ponownie
Do nothing
Nic nie rób
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Błąd zmiany godziny modyfikacji:
Error copying file:
Błąd podczas kopiowania pliku:
+Error copying locked file %x!
+Błąd podczas kopiowania zablokowanego pliku %x!
Error creating directory:
Błąd podczas tworzenia katalogu:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Błąd odczytu dowiązania symbolicznego:
Error retrieving full path:
Błąd odzyskiwania pełnej ścieżki:
+Error starting Volume Shadow Copy Service!
+Błąd podczas uruchamianiu usługi Shadow Copy!
Error traversing directory:
Błąd podczas odczytywania katalogu:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Zakończ z RC < 0
Feedback and suggestions are welcome at:
Komentarze i sugestie mile widziane na:
+File %x has an invalid date!
+Plik %x ma nieprawidłową datę!
File Manager integration:
Menadżer plików:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Plik różniące się określoną liczbą sekund traktowane są jako równe.
Filename
Nazwa pliku
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Pliki %x różnią się mniej niż 1 godzinę. Nie można bezpiecznie określić, który plik jest nowszy zgodnie z przesunięciem czasu letniego.
+Files %x have the same date but a different size!
+Pliki %x mają tą samą datę lecz różne rozmiary!
Files are found equal if\n - file content\nis the same.
Pliki są jednakowe jeżeli\n - zawartość pliku\njest identyczna.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Przesuń kolumnę w dół
Move column up
Przesuń kolumnę do góry
+Moving %x to Recycle Bin
+Przenoszenie %x do kosza.
Not all items have been synchronized! Have a look at the list.
Nie wszystkie elementy zostały zsynchronizowane! Zobacz tą listę.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pauza
Paused
Pauza
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Skopiuj odpowiedni plik \"Shadow.dll\" (ulokowany w \"Shadow.zip\") do folderu z instalacją FreeFileSync aby uaktywnić tą opcję.
Please fill all empty directory fields.
Podaj foldery do synchronizacji.
Press button to activate filter
Kliknij aby aktywować filtr
-Preview
-Podgląd
Published under the GNU General Public License:
Udostępnione na zasadach licencji GNU General Public License:
Question
@@ -614,6 +632,8 @@ Start
Rozpocznij
Start synchronization
Rozpocznij synchronizację
+Statistics
+Statystyki
Stop
Zatrzymaj
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Synchronizacja zakończona pomyślnie!
Synchronization completed with errors!
Synchronizacja zakończona z błędami.
-Synchronization filter
-Filtr synchronizacji
Synchronization settings
Ustawienia synchronizacji
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Synchronizuj wszystkie pliki .doc, .zip i exe z wyjątkiem folderu \"temp\"
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Synchronizuj obie strony jednocześnie: Kopiuj nowe albo uaktualniaj w obu folderach.
+Synchronize...
+Synchronizuj...
Synchronizing...
Synchronizuję...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Użyj kosza
Use Recycle Bin when deleting or overwriting files during synchronization
Użyj Kosza podczas usuwania bądź nadpisywania plików w trakcie synchronizacji
+Variant
+Wariant
+Volume name %x not part of filename %y!
+Dysk %x nie jest częścią pliku %y!
Warning
Uwaga
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/portuguese.lng b/BUILD/Languages/portuguese.lng
index 5808fe8d..04002221 100644
--- a/Languages/portuguese.lng
+++ b/BUILD/Languages/portuguese.lng
@@ -176,6 +176,8 @@ Build:
Criado:
Cancel
Cancelar
+Change direction
+Mudar direcção
Check all
Verificar tudo
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Configure as suas regras de sincronização.
Confirm
Confirmar
+Conflict detected:
+Conflito detectado:
Continue
Continuar
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Copiar ficheiro %x para %y
Copying file %x to %y overwriting target
Copiar ficheiro %x para %y substituindo
+Could not determine volume name for file:
+Não é possível determinar o nome do volume para o ficheiro:
Could not set working directory:
Não pode definir pasta de trabalho:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
A pasta não existe:
Do not display visual status information but write to a logfile instead
Não apresentar informação de estado, mas escrever num ficheiro log
-Do not show this warning again
-Não voltar a mostrar este aviso
+Do not show this dialog again
+Não mostrar novamente
Do nothing
Não fazer nada
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Erro ao mudar a hora de modificação:
Error copying file:
Erro ao copiar ficheiro:
+Error copying locked file %x!
+Erro ao copiar ficheiro bloqueado %x!
Error creating directory:
Erro ao criar a pasta:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Erro na resolução do link simbólico:
Error retrieving full path:
Erro no retorno do caminho:
+Error starting Volume Shadow Copy Service!
+Erro ao iniciar o serviço Volume Shadow Copy!
Error traversing directory:
Erro ao percorrer a pasta:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Sair com RC < 0
Feedback and suggestions are welcome at:
Comentários e sugestões são benvindos em:
+File %x has an invalid date!
+Ficheiro %x tem data inválida!
File Manager integration:
Integração c/ Gestor de Ficheiros:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Ficheiro com diferença de tempo até ao número especificado de segundos são tratados como tendo o mesmo tempo.
Filename
Nome do ficheiro
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Os ficheiros %x têm uma diferença de tempo inferior a 1 hora! Não é seguro decidir qual o mais novo devido às mudanças de Hora de Verão.
+Files %x have the same date but a different size!
+Os ficheiros %x têm a mesma data, mas tamanho diferente!
Files are found equal if\n - file content\nis the same.
Os ficheiros são considerados iguais se\n - o conteúdo é o mesmo.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Mover coluna para baixo
Move column up
Mover coluna para cima
+Moving %x to Recycle Bin
+Mover %x para a Reciclagem
Not all items have been synchronized! Have a look at the list.
Nem todos os ficheiros foram sincronizados! Verifique a lista.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pausa
Paused
Em pausa
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Por favor copie o \"Shadow.dll\" correcto (localizado no arquivo \"Shadow.zip\") para a pasta da instalação do FreeFileSync para activar esta opção.
Please fill all empty directory fields.
Por favor, preencha todos os campos vazios.
Press button to activate filter
Pressione para activar o filtro
-Preview
-Pré-visualizar
Published under the GNU General Public License:
Publicado sobre GNU General Public License:
Question
@@ -614,6 +632,8 @@ Start
Iniciar
Start synchronization
Iniciar a sincronização
+Statistics
+Estatísticas
Stop
Parar
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Sincronização completa com sucesso!
Synchronization completed with errors!
Sincronização completa com erros!
-Synchronization filter
-Filtro sincronização
Synchronization settings
Parâmetros de sincronização
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Sincronizar todos os ficheiros .doc, .zip e .exe excepto os da pasta \"temp\".
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Sincronizar ambos os lados simultaneamente: Copiar os ficheiros novos ou mais recentes em ambas as direcções.
+Synchronize...
+Sincronizar...
Synchronizing...
A sincronizar...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Utilizar Reciclagem
Use Recycle Bin when deleting or overwriting files during synchronization
Utilizar a Reciclagem ao eliminar ou substituir ficheiros durante a sincronização
+Variant
+Variável
+Volume name %x not part of filename %y!
+Nome do volume %x não faz parte do ficheiro %y!
Warning
Atenção
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/portuguese_br.lng b/BUILD/Languages/portuguese_br.lng
index a8af22da..359b22d1 100644
--- a/Languages/portuguese_br.lng
+++ b/BUILD/Languages/portuguese_br.lng
@@ -65,7 +65,7 @@
&Load configuration
&Carregar configuração
&No
-
+&Não
&OK
&OK
&Pause
@@ -77,15 +77,15 @@
&Save
&Salvar
&Yes
-
+&Sim
,
.
- do not copy\n
-
+- não copiar\n
- conflict
-
+- conflito
- conflict (same date, different size)
-
+- conflito (mesma data, tamanho diferente)
- different
- diferente
- equal
@@ -103,7 +103,7 @@
- right newer
- mais recente à direita
-> copy to right side\n
-
+-> copiar para o lado direito\n
-Open-Source file synchronization-
-Sincronização de Arquivos Open-Source-
.
@@ -117,15 +117,15 @@
1. &Compare
1. &Comparar
1. Enter relative file or directory names separated by ';' or a new line.
-
+1. Entre os nomes dos arquivos ou diretórios relativos separados por ';' ou uma nova linha.
2. &Synchronize...
2. &Sincronizar...
2. Use wildcard characters '*' and '?'.
-2. Usar '*' e '?' como caracteres de procura.
+2. Usar '*' e '?' como caracteres coringa.
3. Exclude files directly on main grid via context menu.
3. Excluir arquivos diretamente do grid principal através do menu de contexto.
<- copy to left side\n
-
+<- copiar para o lado esquerdo\n
<< left file is newer\n
<< arquivo à esquerda é mais recente\n
<Directory>
@@ -137,7 +137,7 @@
<| file on left side only\n
<| arquivo apenas à esquerda\n
== files are equal\n
-
+== arquivos são iguais\n
>> right file is newer\n
>> arquivo à direita é mais recente\n
A newer version of FreeFileSync is available:
@@ -171,19 +171,21 @@ Arquivo Batch
Big thanks for localizing FreeFileSync goes out to:
Pela tradução do FreeFileSync, um agradecimento a:
Browse
-
+Procurar
Build:
Criado:
Cancel
Cancelar
+Change direction
+Inverter sentido
Check all
-Verificar tudo
+Marcar todos
Choose to hide filtered files/directories from list
Ocultar arquivos/diretórios filtrados da lista
Comma separated list
Lista de itens separada por vírgula
Compare
-
+Comparar
Compare both sides
Comparar os dois lados
Compare by \"File content\"
@@ -197,9 +199,9 @@ Comparando conteúdo
Comparing content of files %x
Comparando conteúdo do arquivo %x
Comparing content...
-
+Comparando conteúdo...
Comparison Result
-
+Resultado da Comparação
Completed
Finalizado
Configuration
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Configure as suas próprias regras de sincronização.
Confirm
Confirmar
+Conflict detected:
+Conflito detectado:
Continue
Continuar
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Copiando arquivo %x para %y
Copying file %x to %y overwriting target
Copiando arquivo %x para %y substituindo destino
+Could not determine volume name for file:
+Não foi possível determinar o nome do volume para o arquivo:
Could not set working directory:
Não se pode definir pasta de trabalho:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
Diretório não existe:
Do not display visual status information but write to a logfile instead
Ao invés de mostrar informação do estado visualmente, escrever para um arquivo log
-Do not show this warning again
-Não mostrar novamente este aviso
+Do not show this dialog again
+Não mostrar esse diálogo novamente
Do nothing
Não fazer nada
Do you really want to delete the following objects(s)?
@@ -289,7 +295,7 @@ Quer mesmo mover o(s) seguinte(s) item(s) para a Lixeira?
Do you want FreeFileSync to automatically check for updates every week?
Deseja que o FreeFileSync procure automaticamente novas versões toda semana?
Don't ask me again
-
+Não perguntar novamente
Donate with PayPal
Doar usando PayPal
Download now?
@@ -306,6 +312,8 @@ Error changing modification time:
Erro ao mudar a hora de modificação:
Error copying file:
Erro ao copiar arquivo:
+Error copying locked file %x!
+Erro ao copiar arquivo bloqueado %x!
Error creating directory:
Erro ao criar diretório:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Erro na resolução de link simbólico:
Error retrieving full path:
Erro ao obter caminho completo:
+Error starting Volume Shadow Copy Service!
+Erro ao inicializar o Serviço de Cópias de Sombra de Volume!
Error traversing directory:
Erro ao percorrer diretório:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Sair com RC < 0
Feedback and suggestions are welcome at:
Comentários e sugestões são bem-vindos em:
+File %x has an invalid date!
+Arquivo %x tem uma data inválida!
File Manager integration:
Integração com Gerenciador de Arquivos:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Arquivos com diferença de horário até o número especificado de segundos são tratados como tendo o mesmo horário.
Filename
Nome do arquivo
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Arquivos %x têm diferença no horário de criação menor do que 1 hora! Não é seguro decidir qual é o mais novo devido a problemas relacionados com o Horário de Verão.
+Files %x have the same date but a different size!
+Arquivos %x têm a mesma data mas tamanhos diferentes!
Files are found equal if\n - file content\nis the same.
Os arquivos são considerados iguais se\n - o conteúdo do arquivo\né o mesmo.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -415,7 +431,7 @@ FreeFileSync configuração
FreeFileSync is up to date!
FreeFileSync está atualizado!
Full path
-
+Caminho completo
Generating file list...
Gerando lista de arquivos...
Global settings
@@ -425,7 +441,7 @@ Ajuda
Hide all error and warning messages
Ocultar todas as mensagens de erro ou aviso
Hide conflicts
-
+Ocultar conflitos
Hide files that are different
Ocultar arquivos que são diferentes
Hide files that are equal
@@ -439,11 +455,11 @@ Ocultar arquivos que existem somente à esquerda
Hide files that exist on right side only
Ocultar arquivos que existem somente à direita
Hide files that will be copied to the left side
-
+Ocultar arquivos que serão copiados para o lado esquerdo
Hide files that will be copied to the right side
-
+Ocultar arquivos que serão copiados para o lado direito
Hide files that won't be copied
-
+Ocultar arquivos que não serão copiados
Hide filtered items
Ocultar itens filtrados
Hide further error messages during the current process
@@ -457,7 +473,7 @@ Homepage
If you like FFS
Se gosta do FFS
Ignore 1-hour file time difference
-
+Ignorar diferença de tempo do arquivo de 1 hora
Ignore errors
Ignorar erros
Ignore subsequent errors
@@ -471,7 +487,7 @@ Incluir
Include temporarily
Incluir temporariamente
Include: *.doc;*.zip;*.exe\nExclude: \\temp\\*
-
+Incluir: *.doc;*.zip;*.exe\nExcluir: \\temp\\*
Info
Info
Information
@@ -500,8 +516,10 @@ Move column down
Mover coluna para baixo
Move column up
Mover coluna para cima
+Moving %x to Recycle Bin
+Movendo %x para a Lixeira
Not all items have been synchronized! Have a look at the list.
-
+Nem todos os itens foram sincronizados! Olhe a lista.
Not enough free disk space available in:
Espaço em disco insuficiente em:
Nothing to synchronize according to configuration!
@@ -515,7 +533,7 @@ Número de arquivos que serão substituídos
OK
OK
Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the synchronization directories.
-
+Apenas arquivos/diretórios que passarem a filtragem serão selecionados para sincronização. O filtro será aplicado ao nome em relação(!) aos diretórios de sincronização.
Open with File Manager\tD-Click
Abrir com Gerenciador de Arquivos\tD-Click
Operation aborted!
@@ -528,16 +546,16 @@ Pause
Pausa
Paused
Pausado
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Por favor, copie o \"Shadow.dll\" apropriado (localizado no arquivo \"Shadow.zip\") no diretório de instalação do FreeFileSync para habilitar essa funcionalidade.
Please fill all empty directory fields.
Por favor, preencha todos os campos de diretórios vazios.
Press button to activate filter
Pressione para ativar o filtro
-Preview
-Pré-visualização
Published under the GNU General Public License:
Publicado sobre a GNU General Public License:
Question
-
+Questão
Quit
Sair
Relative path
@@ -547,19 +565,19 @@ Remover par de pastas
Reset
Reiniciar
Reset all warning messages
-
+Resetar todas as mensagens de aviso
Reset all warning messages?
-Reiniciar todas as mensagens de aviso?
+Resetar todas as mensagens de aviso?
Result
Resultado
Right:
-Direita:
+Direita:
S&ave configuration
S&alvar configuração
S&witch view
-
+A&lterar visualização
Save changes to current configuration?
-
+Salvar modificações para a configuração atual?
Save current configuration to file
Salvar configuração atual para arquivo
Scanning...
@@ -573,9 +591,9 @@ Escolha um diretório para salvar o arquivo log:
Select variant:
Selecione uma variante:
Show conflicts
-
+Mostrar conflitos
Show file icons
-
+Mostrar ícones dos arquivos
Show files that are different
Mostrar arquivos que são diferentes
Show files that are equal
@@ -589,11 +607,11 @@ Mostrar arquivos que existem somente à esquerda
Show files that exist on right side only
Mostrar arquivos que existem somente à direita
Show files that will be copied to the left side
-
+Mostrar arquivos que serão copiados para o lado esquerdo
Show files that will be copied to the right side
-
+Mostrar arquivos que serão copiados para o lado direito
Show files that won't be copied
-
+Mostrar arquivos que não serão copiados
Show popup
Mostrar popup
Show popup on errors or warnings
@@ -614,28 +632,30 @@ Start
Iniciar
Start synchronization
Iniciar sincronização
+Statistics
+Estatísticas
Stop
Parar
Swap sides
Inverter lados
Synchronization Preview
-
+Pré-visualização da Sincronização
Synchronization aborted!
Sincronização cancelada!
Synchronization completed successfully!
Sincronização finalizada com sucesso!
Synchronization completed with errors!
Sincronização finalizada com erros!
-Synchronization filter
-Filtro de sincronização
Synchronization settings
Parâmetros de sincronização
Synchronization status
Estado da sincronização
Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\".
-
+Sincronizar todos arquivos .doc, .zip e .exe exceto tudo que estiver na subpasta \"temp\".
Synchronize both sides simultaneously: Copy new or updated files in both directions.
-Sincronizar ambos os lados simultaneamente: Copiar os arquivos novos ou mais recentes em ambas as direções.
+Sincronizar ambos os lados simultaneamente: Copia os arquivos novos ou mais recentes em ambas as direções.
+Synchronize...
+Sincronizar...
Synchronizing...
Sincronizando...
System out of memory!
@@ -661,7 +681,7 @@ Espaço livre total requerido:
Total time:
Tempo total:
Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.
-
+Tratar tempo dos arquivos que diferem exatamente por +/- 1 hora como igual, menor que 1 hora como conflito para lidar com mudanças de Horário de Verão.
Two way <->
Dois sentidos <->
Unable to connect to sourceforge.net!
@@ -671,15 +691,19 @@ Não foi possível criar arquivo log!
Unable to initialize Recycle Bin!
Não foi possível inicializar a Lixeira!
Uncheck all
-Deselecionar todos
+Desmarcar todos
Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization.
-
+Conflitos não resolvidos existentes! \n\nVocê pode ignorar conflitos e continuar a sincronização.
Update ->
Atualizar ->
Use Recycle Bin
Utilizar Lixeira
Use Recycle Bin when deleting or overwriting files during synchronization
Utilizar a Lixeira ao apagar ou substituir arquivos durante a sincronização
+Variant
+Variante
+Volume name %x not part of filename %y!
+Nome do volume %x não é parte do arquivo %y!
Warning
Atenção
Warning: Synchronization failed for %x item(s):
@@ -695,7 +719,7 @@ diferente
file exists on both sides
arquivo existe em ambos os lados
flash conflict\n
-
+raio conflito\n
on one side only
existente apenas em um lado
|> file on right side only\n
diff --git a/BUILD/Languages/russian.lng b/BUILD/Languages/russian.lng
new file mode 100644
index 00000000..2e3aa21e
--- /dev/null
+++ b/BUILD/Languages/russian.lng
@@ -0,0 +1,726 @@
+ MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE
+ MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI Framework\n wxFormBuilder\t- wxWidgets GUI-Builder\n CodeBlocks \t- Open-Source IDE
+ Byte
+ Байт
+ GB
+ ГБ
+ MB
+ МБ
+ PB
+ ПБ
+ TB
+ ТБ
+ day(s)
+ день(ей)
+ hour(s)
+ час(ов)
+ kB
+ кБ
+ min
+ мин.
+ sec
+ сек.
+!= files are different\n
+!= файлы разные\n
+%x directories
+%x папки
+%x files,
+%x файл(ов),
+%x is not a valid FreeFileSync batch file!
+%x не корректная группа FreeFileSync файл!
+%x of %y rows in view
+%x из %y строк(и) показано
+%x of 1 row in view
+%x из 1 строка показана
+&Abort
+&Отмена
+&About...
+&О программе...
+&Advanced
+&Дополнительно
+&Apply
+&Принять
+&Cancel
+&Отмена
+&Check for new version
+&Проверить наличие новой версии
+&Create batch job
+&Создать задание
+&Default
+&По-умолчанию
+&Export file list
+&Экспортировать список файлов
+&File
+&Файл
+&Global settings
+&Глобальные настройки
+&Help
+&Помощь
+&Ignore
+&Игнорировать
+&Language
+&Язык
+&Load
+&Загрузить
+&Load configuration
+&Загрузить конфигурацию
+&No
+&Нет
+&OK
+&OK
+&Pause
+&Пауза
+&Quit
+&Выход
+&Retry
+&Повторить
+&Save
+&Сохранить
+&Yes
+&Да
+,
+.
+- do not copy\n
+ не копировать\n
+- conflict
+ конфликт
+- conflict (same date, different size)
+конфликт (даты совпадают, размеры разные)
+- different
+разные
+- equal
+одинаковые
+- exists left only
+только левые существуют
+- exists right only
+только правые существуют
+- left
+левые
+- left newer
+левые новее
+- right
+правые
+- right newer
+правые новее
+-> copy to right side\n
+-> скопировать на правую сторону\n
+-Open-Source file synchronization-
+Синхронизатор файлов с открытым исходным кодом
+.
+,
+/sec
+/сек.
+1 directory
+1 папка
+1 file,
+1 файл,
+1. &Compare
+1. &Сравнить
+1. Enter relative file or directory names separated by ';' or a new line.
+1. Введите имена файлов или папок, разделяя знаком ';' или с новой строки.
+2. &Synchronize...
+2. &Синхронизировать
+2. Use wildcard characters '*' and '?'.
+2. Используйте символы '*' и '?' для замены неизвестных.
+3. Exclude files directly on main grid via context menu.
+3. Исключите файлы прямо в главном окне через контекстное меню.
+<- copy to left side\n
+<- скопировать на левую сторону\n
+<< left file is newer\n
+<< файл слева новее\n
+<Directory>
+<Папка>
+<Last session>
+<Последняя сессия>
+<multiple selection>
+<групповое выделение>
+<| file on left side only\n
+<| файлы только слева\n
+== files are equal\n
+== файлы одинаковые\n
+>> right file is newer\n
+>> файлы справа новее\n
+A newer version of FreeFileSync is available:
+Доступна новая версия FreeFileSync:
+Abort requested: Waiting for current operation to finish...
+Запрос отмены: Ожидайте, пока текущая операция завершится...
+Aborted
+Отменено
+About
+О программе
+Action
+Действие
+Add folder pair
+Добавить папку
+All items have been synchronized!
+Все пункты были синхронизированы!
+An exception occured!
+Исключение произошло!
+As a result the files are separated into the following categories:
+Как результат файлы разделяются на следующие категории:
+As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:
+Как написано в названии, два файла с одинаковым именем отмечаются равными, только если они имеют то же самое содержание. Эта опция полезна для проверки согласованности, а не операции резервного копирования. Поэтому даты файлов не учитываются вообще.\n\nС этой опцией алгоритм короче:
+Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner.
+Создайте файл задания для автоматизированной синхронизации. Чтобы запустить программу в этом режиме просто передайте название файла на выполнение FreeFileSync: FreeFileSync.exe <batchfile>. Это также может быть записано в планировщике задач Вашей операционной системы.
+Batch execution
+Выполнение пакетного задания
+Batch file created successfully!
+Файл задания создан успешно!
+Batch job
+Пакетное задание
+Big thanks for localizing FreeFileSync goes out to:
+Большое спасибо за перевод FreeFileSync:
+Browse
+Обзор
+Build:
+Сборка:
+Cancel
+Отмена
+Change direction
+Поменять направление
+Check all
+Проверить все
+Choose to hide filtered files/directories from list
+Выберите для скрытия отфильтрованных файлов/папок из списка
+Comma separated list
+Список, разделяемый запятыми
+Compare
+Сравнить
+Compare both sides
+Сравнить обе стороны
+Compare by \"File content\"
+Сравнивать по содержимому
+Compare by \"File size and date\"
+Сравнивать по размеру и дате
+Compare by...
+Критерии сравнения
+Comparing content
+Сравнивать содержание
+Comparing content of files %x
+Сравнение содержания файлов %x
+Comparing content...
+Сравнение содержания...
+Comparison Result
+Результаты сравнения
+Completed
+Завершено
+Configuration
+Настройка
+Configuration loaded!
+Настройка загружена!
+Configuration overview:
+Конфигурация:
+Configuration saved!
+Настройка сохранена!
+Configure filter
+Настройка фильтра
+Configure filter...
+Настроить фильтр
+Configure your own synchronization rules.
+Настроить свои собственные правила синхронизации.
+Confirm
+Подтвердить
+Conflict detected:
+Обнаружен конфликт:
+Continue
+Продолжить
+Conversion error:
+Ошибка преобразования:
+Copy from left to right
+Скопировать слева направо
+Copy from left to right overwriting
+Скопировать слева направо с перезаписью
+Copy from right to left
+Скопировать справа налево
+Copy from right to left overwriting
+Скопировать справа налево с перезаписью
+Copy new or updated files to right folder.
+Копировать новые или обновлять файлы на правой стороне.
+Copy to clipboard\tCTRL+C
+Копировать в буфер обмена\tCTRL+C
+Copying file %x to %y
+Копирование файла %x в %y
+Copying file %x to %y overwriting target
+Копирование файла %x в %y с заменой
+Could not determine volume name for file:
+Не удалось определить название тома для файла:
+Could not set working directory:
+Не удалось установить рабочую папку:
+Create a batch job
+Создать пакетное задание
+Creating folder %x
+Создание папки %x
+Current operation:
+Текущая операция:
+Custom
+Выборочно
+Customize columns
+Выбор колонок
+DECISION TREE
+Древо решений
+Data remaining:
+Осталось:
+Date
+Дата
+Delete files/folders existing on left side only
+Удалить файлы/папки, существующие только на левой стороне
+Delete files/folders existing on right side only
+Удалить файлы/папки, существующие только на правой стороне
+Delete files\tDEL
+Удалить файлы\tDEL
+Delete on both sides
+Удалить на обоих сторонах
+Delete on both sides even if the file is selected on one side only
+Удалить на обоих сторонах, если даже файл выделен только на одной стороне
+Deleting file %x
+Удаление файла %x
+Deleting folder %x
+Удаление папки %x
+Directories are dependent! Be careful when setting up synchronization rules:
+Зависимые папки! Будьте внимательны при настройке правил синхронизации:
+Directory
+Папка
+Directory does not exist:
+Папка не существует:
+Do not display visual status information but write to a logfile instead
+Не показывать информацию по статусу, но записывать в лог-файл
+Do not show this dialog again
+Больше не показывать это окно
+Do nothing
+Ничего не делать
+Do you really want to delete the following objects(s)?
+Вы действительно хотите удалить следующие объекты?
+Do you really want to move the following objects(s) to the Recycle Bin?
+Вы действительно хотите отправить следующие объекты в Корзину?
+Do you want FreeFileSync to automatically check for updates every week?
+Вы хотите, чтобы FreeFileSync автоматически проверял наличие обновлений каждую неделю?
+Don't ask me again
+Не спрашивать меня больше
+Donate with PayPal
+Отправить деньги через PayPal
+Download now?
+Загрузить сейчас?
+Drag && drop
+Drag && drop
+Email
+Почта
+Enable filter to exclude files from synchronization
+Применить фильтр, чтобы исключить файлы из задания на синхронизацию
+Error
+Ошибка
+Error changing modification time:
+Ошибка при изменении времени модификации файла:
+Error copying file:
+Ошибка при копировании файла:
+Error copying locked file %x!
+Ошибка при копировании заблокированного файла %x!
+Error creating directory:
+Ошибка при создании папки:
+Error deleting directory:
+Ошибка при удалении папки:
+Error deleting file:
+Ошибка при удалении файла:
+Error handling
+Обработка ошибок
+Error loading library function:
+Ошибка при загрузке функции библиотеки:
+Error moving to Recycle Bin:
+Ошибка при отправке в Корзину:
+Error opening file:
+Ошибка при открытии файла:
+Error parsing configuration file:
+Ошибка при анализе файла конфигурации:
+Error reading file attributes:
+Ошибка при чтении параметров файла:
+Error reading file:
+Ошибка при чтении файла:
+Error resolving symbolic link:
+Ошибка при решении символической ссылки:
+Error retrieving full path:
+Ошибка при получении полного пути:
+Error starting Volume Shadow Copy Service!
+Ошибка при запуске Службы Теневого Копирования Тома!
+Error traversing directory:
+Ошибка при пересечении папок:
+Error writing file attributes:
+Ошибка при записи параметров файла:
+Error writing file:
+Ошибка при записи файла:
+Error: Source directory does not exist anymore:
+Ошибка: Исходная папка больше не существует:
+Example
+Пример
+Exclude
+Исключая
+Exclude temporarily
+Исключить временные
+Exclude via filter:
+Исключить через фильтр:
+Exit immediately and set returncode < 0
+Выйти немедленно и установить код возврата <0
+Exit with RC < 0
+Выход с RC <0
+Feedback and suggestions are welcome at:
+Отзывы и предложения присылайте по адресу:
+File %x has an invalid date!
+Файл %x имеет недействительную дату!
+File Manager integration:
+Интеграция в Проводник:
+File Time tolerance (seconds):
+Допуск по времени файла (секунд):
+File already exists. Overwrite?
+Файл уже существует. Перезаписать?
+File content
+Содержимое файла
+File does not exist:
+Файл не существует:
+File list exported!
+Список файлов экспортирован!
+File size and date
+Размер и дата файла
+File times that differ by up to the specified number of seconds are still handled as having same time.
+Время файлов отличающееся на определенное количество секунд рассматривается как равное.
+Filename
+Имя файла
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Файлы %x имеют время отличающееся менее чем на 1 час! Решать какой новее небезопасно ввиду перехода на летнее время.
+Files %x have the same date but a different size!
+Файлы %x имеют одинаковую дату, но различаются по размеру!
+Files are found equal if\n - file content\nis the same.
+Файлы считаются равными, если\n - содержание файлов одинаковое
+Files are found equal if\n - filesize\n - last write time and date\nare the same.
+Файлы считаются равными, если одинаковые\n - размер файла\n - дата и время последнего изменения
+Files remaining:
+Файлов осталось:
+Files that exist on both sides and have different content
+Файлы, существующие на обоих сторонах и имеющие разное содержание
+Files that exist on both sides, left one is newer
+Файлы, существующие на обоих сторонах, левый новее
+Files that exist on both sides, right one is newer
+Файлы, существующие на обоих сторонах, правый новее
+Files/folders remaining:
+Файлов/папко осталось:
+Files/folders scanned:
+Файлов/папок просканировано:
+Files/folders that exist on left side only
+Файлы/папки, существующие только на левой стороне
+Files/folders that exist on right side only
+Файлы/папки, существующие только на правой стороне
+Filter
+Фильтр
+Filter active: Press again to deactivate
+Фильтр активен: Нажмите еще раз для отключения
+Filter files
+Фильтр файлов
+Filter view
+Вид фильтра
+Folder Comparison and Synchronization
+Сравнение и синхронизация
+Folder pair
+Дополнительная папка
+FreeFileSync - Folder Comparison and Synchronization
+FreeFileSync - Сравнение и синхронизация
+FreeFileSync Batch Job
+Пакетное задание FreeFileSync
+FreeFileSync at Sourceforge
+FreeFileSync на Sourceforge
+FreeFileSync batch file
+Файл задания FreeFileSync
+FreeFileSync configuration
+FreeFileSync настройка
+FreeFileSync is up to date!
+У Вас самый последний FreeFileSync!
+Full path
+Полный путь
+Generating file list...
+Создание списка файлов...
+Global settings
+Глобальные настройки
+Help
+Помощь
+Hide all error and warning messages
+Скрывать все ошибки и сообщения с предупреждениями
+Hide conflicts
+Скрыть конфликтующие файлы
+Hide files that are different
+Скрыть различающиеся файлы
+Hide files that are equal
+Скрыть одинаковые файлы
+Hide files that are newer on left
+Скрыть файлы, которые новее слева
+Hide files that are newer on right
+Скрыть файлы, которые новее справа
+Hide files that exist on left side only
+Скрыть файлы, существующие только слева
+Hide files that exist on right side only
+Скрыть файлы, существующие только справа
+Hide files that will be copied to the left side
+Скрыть файлы, которые будут скопированы на левую сторону
+Hide files that will be copied to the right side
+Скрыть файлы, которые будут скопированы на правую сторону
+Hide files that won't be copied
+Скрыть файлы, которые не будут скопированы
+Hide filtered items
+Скрыть отфильтрованные
+Hide further error messages during the current process
+Скрыть последующие ошибки во время текущего процесса
+Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process
+Скрыть сообщения об ошибках во время синхронизации:\nони накапливаются и показываются как список в конце процесса
+Hints:
+Подсказка:
+Homepage
+Оф.сайт
+If you like FFS
+Если Вам понравился FFS
+Ignore 1-hour file time difference
+Игнорировать 1-часовую разницу во времени
+Ignore errors
+Игнорировать ошибки
+Ignore subsequent errors
+Игнорировать последующие ошибки
+Ignore this error, retry or abort synchronization?
+Игнорировать эту ошибку, повторить или отменить синхронизацию?
+Ignore this error, retry or abort?
+Игнорировать эту ошибку, повторить или отменить?
+Include
+Включая
+Include temporarily
+Включая временные
+Include: *.doc;*.zip;*.exe\nExclude: \\temp\\*
+Включая: *.doc;*.zip;*.exe\nИсключая: \\temp\\*
+Info
+Информация
+Information
+Информация
+Initialization of Recycle Bin failed!
+Инициализация Корзины провалена!
+It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :)
+Невозможно инициализировать Корзину!\n\nВероятно, что Вы не используете Windows.\nЕсли Вы хотите, чтобы эта функция была, пожалуйста свяжитесь с автором.:)
+Left:
+Слева:
+Load configuration from file
+Загрузить конфигурацию из файла
+Load configuration history (press DEL to delete items)
+Выбрать конфигурацию из списка (нажмите DEL для удаления пунктов)
+Log-messages:
+Лог-сообщения:
+Logging
+Лог-файлы
+Mirror ->>
+Зеркало ->>
+Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization.
+Резервная копия левой папки: правая папка будет перезаписана и после синхронизации будет точно соответствовать левой папке
+More than 50% of the total number of files will be copied or deleted!
+Более 50% общего количества файлов будет скопировано или удалено!
+Move column down
+Переместить вниз
+Move column up
+Переместить вверх
+Moving %x to Recycle Bin
+Отправка %x в Корзину
+Not all items have been synchronized! Have a look at the list.
+Не все пункты были синхронизированы! Посмотрите список.
+Not enough free disk space available in:
+Не достаточно свободного места в:
+Nothing to synchronize according to configuration!
+Ничего нет для синхронизации в соответствии с конфигурацией!
+Number of files and directories that will be created
+Число файлов и папок, которые будут созданы
+Number of files and directories that will be deleted
+Число файлов и папок, которые будут удалены
+Number of files that will be overwritten
+Число файлов, которые будут перезаписаны
+OK
+OK
+Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the synchronization directories.
+Только файлы/папки, которые проходят фильтрацию, будут отобраны для синхронизации. Этот фильтр будет применяться к пути папки.
+Open with File Manager\tD-Click
+Открыть файловым менеджером\tD-Click
+Operation aborted!
+Операция отменена!
+Operation:
+Операция:
+Overview
+Главная
+Pause
+Пауза
+Paused
+Пауза
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Пожалуйста, скопируйте соответствующий \"Shadow.dll\" (находящийся в архиве \"Shadow.zip\") в папку установки FreeFileSync для включения этой функции.
+Please fill all empty directory fields.
+Пожалуйста, заполните все пустые поля папок
+Press button to activate filter
+Включить фильтр
+Published under the GNU General Public License:
+Издается под GNU General Public License:
+Question
+Вопрос
+Quit
+Выход
+Relative path
+Относительный путь
+Remove folder pair
+Удалить папку
+Reset
+Сбросить
+Reset all warning messages
+Сбросить все сообщения с предупреждениями
+Reset all warning messages?
+Сбросить все сообщения с предупреждениями?
+Result
+Описание
+Right:
+Справа:
+S&ave configuration
+Сохранить конфигурацию
+S&witch view
+Переключить вид
+Save changes to current configuration?
+Сохранить изменения в текущей конфигурации?
+Save current configuration to file
+Сохранить текущую конфигурацию в файл
+Scanning...
+Сканирование...
+Scanning:
+Сканирую:
+Select a folder
+Выделить папку
+Select logfile directory:
+Выберите папку для лог-файлов:
+Select variant:
+Выберите вариант:
+Show conflicts
+Показать конфликтующие файлы
+Show file icons
+Показывать иконки файлов
+Show files that are different
+Показать различающиеся файлы
+Show files that are equal
+Показать одинаковые файлы
+Show files that are newer on left
+Показать файлы, которые новее слева
+Show files that are newer on right
+Показать файлы, которые новее справа
+Show files that exist on left side only
+Показать файлы, существующие только слева
+Show files that exist on right side only
+Показать файлы, существующие только справа
+Show files that will be copied to the left side
+Показать файлы, которые будут скопированы на левую сторону
+Show files that will be copied to the right side
+Показать файлы, которые будут скопированы на правую сторону
+Show files that won't be copied
+Показать файлы, которые не будут скопированы
+Show popup
+Показывать всплывающие окна
+Show popup on errors or warnings
+Показывать всплывающие окна при ошибках и замечаниях
+Significant difference detected:
+Обнаружено существенное различие:
+Silent mode
+Скрытый режим
+Size
+Размер
+Sorting file list...
+Формирование списка файлов...
+Source code written completely in C++ utilizing:
+Исходный код написан на С++ с использованием:
+Speed:
+Скорость:
+Start
+Старт
+Start synchronization
+Начать синхронизацию
+Statistics
+Статистика
+Stop
+Стоп
+Swap sides
+
+Synchronization Preview
+Предпросмотр синхронизации
+Synchronization aborted!
+Синхронизация отменена!
+Synchronization completed successfully!
+Синхронизация прошла успешно!
+Synchronization completed with errors!
+Синхронизация закончена с ошибками!
+Synchronization settings
+Настройки синхронизации
+Synchronization status
+Статус синхронизации
+Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\".
+Синхронизировать все .doc, .zip и .exe файлы, за исключением всех файлов из подпапки \"temp\"
+Synchronize both sides simultaneously: Copy new or updated files in both directions.
+Синхронизировать обе стороны одновременно: копировать новые или обновлять файлы в обоих направлениях.
+Synchronize...
+Синхронизировать
+Synchronizing...
+Синхронизация...
+System out of memory!
+Нехватка памяти!
+Target file already existing!
+Конечный файл уже существует!
+The file does not contain a valid configuration:
+Файл не содержит действительную конфигурацию:
+This commandline will be executed each time you doubleclick on a filename. %name serves as a placeholder for the selected file.
+Эта командная строка будет выполняться каждый раз, когда Вы дважды кликните на имени файла. %name служит указателем места для выбранного файла.
+This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time.
+Этот вариант сравнивает два файла с одинаковыми именами и считает их равными, если они имеют одинаковый размер файла и одинаковую дату и время последнего изменения.
+Time
+Время
+Time elapsed:
+Времени прошло:
+Time remaining:
+Времени осталось:
+Total amount of data that will be transferred
+Общий объем данных, который будет передаваться
+Total required free disk space:
+Общее требуемое свободное дисковое пространство:
+Total time:
+Общее время:
+Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.
+Обрабатывать файлы, которые отличаются по времени на 1 час, как равные, менее чем на 1 час, как конфликтные, чтобы справиться с переходом на летнее время.
+Two way <->
+В обоих направлениях <->
+Unable to connect to sourceforge.net!
+Невозможно соединиться с sourceforge.net!
+Unable to create logfile!
+Невозможно создать лог!
+Unable to initialize Recycle Bin!
+Невозможно инициализировать Корзину!
+Uncheck all
+Снять выделение со всех
+Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization.
+Существуют нерешенные конфликты \n\nВы можете проигнорировать их и продолжить синхронизацию.
+Update ->
+Обновить ->
+Use Recycle Bin
+Использовать "Корзину"
+Use Recycle Bin when deleting or overwriting files during synchronization
+Использовать "Корзину" при удалении или перезаписи во время синхронизации
+Variant
+Вариант
+Volume name %x not part of filename %y!
+Имя тома %x не является частью имени файла %y!
+Warning
+Внимание
+Warning: Synchronization failed for %x item(s):
+Внимание: Синхронизация провалена для %x
+Warnings:
+Предупреждения:
+When the comparison is started with this option set the following decision tree is processed:
+Когда сравнение запущено с этими критериями, алгоритм следующий:
+You may try to synchronize remaining items again (WITHOUT having to re-compare)!
+Вы можете попытаться синхронизировать оставшиеся пункты снова (без повторного сравнения)!
+different
+разные
+file exists on both sides
+файлы существуют на обоих сторонах
+flash conflict\n
+молния конфликт\n
+on one side only
+файлы существуют только на одной стороне
+|> file on right side only\n
+|> файлы только на правой стороне\n
diff --git a/Languages/slovenian.lng b/BUILD/Languages/slovenian.lng
index ee021d62..90ecd55c 100644
--- a/Languages/slovenian.lng
+++ b/BUILD/Languages/slovenian.lng
@@ -176,6 +176,8 @@ Build:
Izgradnja:
Cancel
Prekliči
+Change direction
+Spremeni smer
Check all
Preveri vse
Choose to hide filtered files/directories from list
@@ -215,9 +217,11 @@ Konfiguriraj filter
Configure filter...
Konfiguriraj filter...
Configure your own synchronization rules.
-Konfiguriraj vaša lastna sinhronizacijska pravila.
+Konfigurirajte vaša lastna sinhronizacijska pravila.
Confirm
Potrdi
+Conflict detected:
+Zaznan spor:
Continue
Nadaljuj
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Kopiram datoteko %x v %y
Copying file %x to %y overwriting target
Kopiram datoteko %x v %y s prepisovanjem cilja
+Could not determine volume name for file:
+Ne morem določiti imena volumna za datoteko:
Could not set working directory:
Ne morem nastaviti delovnega imenika:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
Imenik ne obstaja:
Do not display visual status information but write to a logfile instead
Ne prikazuj vidnih statusnih informacij, ampak piši v dnevniško datoteko
-Do not show this warning again
-Ne prikazuj več tega obvestila
+Do not show this dialog again
+Ne prikaži več tega pogovornega okna
Do nothing
Ne naredi ničesar
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Napaka pri spreminjanju časa modifikacije:
Error copying file:
Napaka pri kopiranju datoteke:
+Error copying locked file %x!
+Napaka pri kopiranju zaklenjene datoteke %x!
Error creating directory:
Napaka pri ustvarjanju imenika:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Napaka pri razreševanju simbolične povezave:
Error retrieving full path:
Napaka pri pridobivanju polne poti:
+Error starting Volume Shadow Copy Service!
+Napaka pri zagonu servisa Volume Shadow Copy!
Error traversing directory:
Napaka pri prehajanju imenika:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Zapusti z RC < 0
Feedback and suggestions are welcome at:
Povratne informacije in predlogi so dobrodošli na:
+File %x has an invalid date!
+Datoteka %x ima neveljaven datum!
File Manager integration:
Integracija z urejevalnikom datotek:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Časi sprememb datotek, ki se razlikujejo do navedenega števila sekund so smatrani kot da imajo isti čas spremembe.
Filename
Ime datoteke
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+Datoteki %x imata razliko v času spremembe manj kot 1 uro! Ni se varno odločiti katera je novejša zaradi vprašanj v zvezi s Poletnim časom.
+Files %x have the same date but a different size!
+Datoteki %x imata enak datum ampak različno velikost!
Files are found equal if\n - file content\nis the same.
Datoteki sta enaki, če\n - je vsebina datoteke\nenaka.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Premakni stolpec dol
Move column up
Premakni stolpec gor
+Moving %x to Recycle Bin
+Premikam %x v Koš
Not all items have been synchronized! Have a look at the list.
Vse stvari niso bile sinhronizirane! Preglejte seznam.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pavza
Paused
Na pavzi
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+Prosim prekopirajte ustrezno \"Shadow.dll\" (ki se nahaja v \"Shadow.zip\" arhivu) v FreeFileSync namestitveni imenik, da omogočite to lastnost.
Please fill all empty directory fields.
Prosim izpolnite vse imenike s praznimi polji.
Press button to activate filter
Kliknite za aktivacijo filtra
-Preview
-Predogled
Published under the GNU General Public License:
Objavljeno pod licenco GNU General Public:
Question
@@ -614,6 +632,8 @@ Start
Začni
Start synchronization
Začni sinhronizacijo
+Statistics
+Statistika
Stop
Ustavi
Swap sides
@@ -626,8 +646,6 @@ Synchronization completed successfully!
Sinhronizacija uspešno zaključena!
Synchronization completed with errors!
Sinhronizacija se je končala z napakami!
-Synchronization filter
-Filter sinhronizacije
Synchronization settings
Nastavitve sinhronizacije
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Sinhroniziraj vse .doc, .zip in .exe datoteke, razen iz podmape \"temp\".
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Sinhroniziraj obe strani istočasno: Kopiraj nove ali posodobljene datoteke v obe smeri.
+Synchronize...
+Sinhroniziraj...
Synchronizing...
Sinhroniziram...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Uporabi Koš
Use Recycle Bin when deleting or overwriting files during synchronization
Uporabi Koš, ko se briše ali prepisuje datoteke med sinhronizacijo
+Variant
+Različica
+Volume name %x not part of filename %y!
+Ime volumna %x ni del imena datoteke %y!
Warning
Pozor
Warning: Synchronization failed for %x item(s):
diff --git a/Languages/spanish.lng b/BUILD/Languages/spanish.lng
index b27055a3..5db32640 100644
--- a/Languages/spanish.lng
+++ b/BUILD/Languages/spanish.lng
@@ -176,6 +176,8 @@ Build:
Construído:
Cancel
Cancelar
+Change direction
+
Check all
Verificar todo
Choose to hide filtered files/directories from list
@@ -218,6 +220,8 @@ Configure your own synchronization rules.
Configure sus propias reglas de sincronización.
Confirm
Confirmar
+Conflict detected:
+
Continue
Continuar
Conversion error:
@@ -238,6 +242,8 @@ Copying file %x to %y
Copiar fichero %x a %y
Copying file %x to %y overwriting target
+Could not determine volume name for file:
+
Could not set working directory:
No se pudo definir el directorio de trabajo:
Create a batch job
@@ -278,8 +284,8 @@ Directory does not exist:
El directorio no existe:
Do not display visual status information but write to a logfile instead
-Do not show this warning again
-No mostrar este aviso otra vez
+Do not show this dialog again
+
Do nothing
No hacer nada
Do you really want to delete the following objects(s)?
@@ -306,6 +312,8 @@ Error changing modification time:
Error al modificar hora:
Error copying file:
Erro al copiar fichero:
+Error copying locked file %x!
+
Error creating directory:
Error al crear directorio:
Error deleting directory:
@@ -330,6 +338,8 @@ Error resolving symbolic link:
Error al resolver enlace simbólico:
Error retrieving full path:
+Error starting Volume Shadow Copy Service!
+
Error traversing directory:
Error al trasladar directorio:
Error writing file attributes:
@@ -352,6 +362,8 @@ Exit with RC < 0
Salir com RC < 0
Feedback and suggestions are welcome at:
Los comentarios y sugerencias será bienvenidos en:
+File %x has an invalid date!
+
File Manager integration:
Integración con el Explorador:
File Time tolerance (seconds):
@@ -370,6 +382,10 @@ File times that differ by up to the specified number of seconds are still handle
Las horas de los ficheros que difieren hasta el número de segundos especificados, son consideradas iguales.
Filename
Nombre del fichero
+Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.
+
+Files %x have the same date but a different size!
+
Files are found equal if\n - file content\nis the same.
Los ficheros serán considerados iguales si\n - el contenido del fichero\nes el mismo.
Files are found equal if\n - filesize\n - last write time and date\nare the same.
@@ -500,6 +516,8 @@ Move column down
Mover columna abajo
Move column up
Mover columna arriba
+Moving %x to Recycle Bin
+
Not all items have been synchronized! Have a look at the list.
Not enough free disk space available in:
@@ -528,12 +546,12 @@ Pause
Pausa
Paused
+Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature.
+
Please fill all empty directory fields.
Por favor, rellene todos los campos del directorio vacíos.
Press button to activate filter
Presione el botón para activar el filtro
-Preview
-Previsualizar
Published under the GNU General Public License:
Publicado bajo "GNU General Public License":
Question
@@ -614,10 +632,12 @@ Start
Iniciar
Start synchronization
Iniciar a sincronización
+Statistics
+
Stop
Parar
Swap sides
-Intercambiar lados
+
Synchronization Preview
Synchronization aborted!
@@ -626,8 +646,6 @@ Synchronization completed successfully!
¡Sincronización completada con éxito!
Synchronization completed with errors!
¡Sincronización completada con errores!
-Synchronization filter
-Filtro de sincronización
Synchronization settings
Parámetros de sincronización
Synchronization status
@@ -636,6 +654,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\
Synchronize both sides simultaneously: Copy new or updated files in both directions.
Sincronizar ambos lados simultáneamente: Copiar ficheros nuevos o actualizados en ambas direcciones.
+Synchronize...
+
Synchronizing...
Sincronizando...
System out of memory!
@@ -680,6 +700,10 @@ Use Recycle Bin
Utilizar la Papelera
Use Recycle Bin when deleting or overwriting files during synchronization
Utilizar la papelera en el borrado o sustitución de ficheros durante la sincronización.
+Variant
+
+Volume name %x not part of filename %y!
+
Warning
Atención
Warning: Synchronization failed for %x item(s):
diff --git a/License.txt b/BUILD/License.txt
index 94a9ed02..94a9ed02 100644
--- a/License.txt
+++ b/BUILD/License.txt
diff --git a/Readme.txt b/BUILD/Readme.txt
index 821de3ab..5410ca5b 100644
--- a/Readme.txt
+++ b/BUILD/Readme.txt
@@ -1,4 +1,4 @@
-FreeFileSync v1.19
+FreeFileSync v2.0
------------------
Usage
@@ -44,8 +44,10 @@ Key Features
22. Handle daylight saving time changes on FAT/FAT32 volumes correctly.
23. Portable version (.zip) available.
24. No Windows registry entries for portable version.
-25. Support for \\?\ path prefix for unrestricted path length. (windows only)
+25. Support for \\?\ path prefix for unrestricted path length. (Windows only)
26. Check for updates from within FreeFileSync automatically.
+27. Copy locked files using Windows Volume Shadow Copy. (Windows only)
+28. Load file icons asynchronously for maximum display performance.
Advanced topics
@@ -93,6 +95,15 @@ Assuming you plan to synchronize two folders "C:\Source" and "D:\Target", you'll
This will exclude all files and folders within the two directories that contain a "\" character. These are exactly the subfolders and -files you want to exclude.
+5.) Synchronize with FTP
+
+FreeFileSync does not support FTP directly. But the FTP functionality can be easily activated by mapping the FTP webspace to a drive letter:
+
+Example: Use the free utility NetDrive (http://www.netdrive.net/)
+- Add a "New Site" and specify site name, site URL, drive letter, account and password.
+- Use the newly created drive as if it were a regular hard disk.
+
+
Links
------
FreeFileSync on SourceForge:
diff --git a/Resources.dat b/BUILD/Resources.dat
index 436e96e8..2590f076 100644
--- a/Resources.dat
+++ b/BUILD/Resources.dat
Binary files differ
diff --git a/BUILD/Shadow.zip b/BUILD/Shadow.zip
new file mode 100644
index 00000000..fbf0d585
--- /dev/null
+++ b/BUILD/Shadow.zip
Binary files differ
diff --git a/BUILD/mingwm10.dll b/BUILD/mingwm10.dll
new file mode 100644
index 00000000..572f8886
--- /dev/null
+++ b/BUILD/mingwm10.dll
Binary files differ
diff --git a/Cleanup.cmd b/Cleanup.cmd
new file mode 100644
index 00000000..23f31809
--- /dev/null
+++ b/Cleanup.cmd
@@ -0,0 +1,28 @@
+@if NOT [%1]==[] echo Don't pass a parameter! && pause && exit
+
+@echo off
+
+::clean codeblocks garbage
+del FreeFileSync.layout
+del FreeFileSync.depend
+
+::clean Visual C++ garbage
+del FreeFileSync.ncb
+attrib FreeFileSync.suo -h
+del FreeFileSync.suo
+del FreeFileSync.vcproj.*.user
+del FreeFileSync.sln
+del BUILD\FreeFileSync.pdb
+
+del library\ShadowCopy\ShadowCopy.ncb
+attrib library\ShadowCopy\ShadowCopy.suo -h
+del library\ShadowCopy\ShadowCopy.suo
+del library\ShadowCopy\ShadowDll.vcproj.*.user
+del library\ShadowCopy\ShadowTest.vcproj.*.user
+del library\ShadowCopy\Shadow.pdb
+del library\ShadowCopy\Shadow.ilk
+del library\ShadowCopy\Shadow.exp
+del library\ShadowCopy\Shadow.lib
+del library\ShadowCopy\ShadowTest.ilk
+del library\ShadowCopy\ShadowTest.pdb
+
diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp
index 42cb6edb..6cb09052 100644
--- a/FreeFileSync.cbp
+++ b/FreeFileSync.cbp
@@ -7,13 +7,16 @@
<Option compiler="gcc" />
<Build>
<Target title="Debug">
- <Option output="FreeFileSync" prefix_auto="1" extension_auto="1" />
- <Option object_output="obj\Debug\" />
+ <Option output="BUILD\FreeFileSync" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="BUILD\" />
+ <Option object_output="OBJ\Debug\" />
<Option type="0" />
<Option compiler="gcc" />
<Option projectLinkerOptionsRelation="2" />
<Compiler>
<Add option="-g" />
+ <Add option="-Winvalid-pch" />
+ <Add option='-include &quot;library/pch.h&quot;' />
<Add option="-D__WXDEBUG__" />
<Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswud" />
</Compiler>
@@ -30,8 +33,9 @@
</Linker>
</Target>
<Target title="Release">
- <Option output="FreeFileSync" prefix_auto="1" extension_auto="1" />
- <Option object_output="obj\Release\" />
+ <Option output="BUILD\FreeFileSync" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="BUILD\" />
+ <Option object_output="OBJ\Release\" />
<Option type="0" />
<Option compiler="gcc" />
<Option projectLinkerOptionsRelation="2" />
@@ -54,14 +58,16 @@
</Linker>
</Target>
<Target title="Unit Test">
- <Option output="obj\Unit Test\Unit Test" prefix_auto="1" extension_auto="1" />
- <Option working_dir="obj\Unit Test\" />
- <Option object_output="obj\Unit Test\" />
+ <Option output="OBJ\Unit Test\Unit Test" prefix_auto="1" extension_auto="1" />
+ <Option working_dir="OBJ\Unit Test\" />
+ <Option object_output="OBJ\Unit Test\" />
<Option type="1" />
<Option compiler="gcc" />
<Option projectLinkerOptionsRelation="2" />
<Compiler>
<Add option="-g" />
+ <Add option="-Winvalid-pch" />
+ <Add option='-include &quot;library/pch.h&quot;' />
<Add option="-D__WXDEBUG__" />
<Add directory="library\gtest" />
<Add directory="library\gtest\include" />
@@ -87,6 +93,7 @@
<Add option="-DFFS_WIN" />
<Add option="-DTIXML_USE_STL" />
<Add option="-DwxUSE_UNICODE" />
+ <Add option="-DZSTRING_WIDE_CHAR" />
<Add directory="C:\Programme\C++\wxWidgets\include" />
<Add directory="C:\Programme\C++\wxWidgets\contrib\include" />
</Compiler>
@@ -107,48 +114,51 @@
<Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" />
</Linker>
<Unit filename="WxWizFrame.fbp">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="algorithm.cpp" />
- <Unit filename="algorithm.h" />
+ <Unit filename="algorithm.h">
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
<Unit filename="application.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="application.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="comparison.cpp" />
<Unit filename="comparison.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\customButton.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="library\customButton.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\customGrid.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="library\customGrid.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
+ <Unit filename="library\fileError.h">
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\fileHandling.cpp" />
- <Unit filename="library\fileHandling.h" />
+ <Unit filename="library\fileHandling.h">
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
<Unit filename="library\filter.cpp" />
- <Unit filename="library\filter.h" />
+ <Unit filename="library\filter.h">
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
<Unit filename="library\globalFunctions.cpp" />
<Unit filename="library\globalFunctions.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\gtest\main.cpp">
<Option target="Unit Test" />
@@ -169,7 +179,7 @@
<Option target="Unit Test" />
</Unit>
<Unit filename="library\gtest\unittest.h">
- <Option target="Unit Test" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\gtest\unittest1.cpp">
<Option target="Unit Test" />
@@ -180,45 +190,58 @@
<Unit filename="library\gtest\unittest3.cpp">
<Option target="Unit Test" />
</Unit>
- <Unit filename="library\localization.cpp" />
- <Unit filename="library\localization.h">
+ <Unit filename="library\iconBuffer.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
- <Unit filename="library\multithreading.cpp" />
- <Unit filename="library\multithreading.h">
+ <Unit filename="library\iconBuffer.h">
<Option target="Debug" />
<Option target="Release" />
</Unit>
+ <Unit filename="library\localization.cpp" />
+ <Unit filename="library\localization.h">
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
+ <Unit filename="library\multithreading.cpp">
+ <Option target="Unit Test" />
+ </Unit>
+ <Unit filename="library\pch.h">
+ <Option compile="1" />
+ <Option weight="0" />
+ <Option target="Debug" />
+ <Option target="Unit Test" />
+ </Unit>
<Unit filename="library\processXml.cpp" />
<Unit filename="library\processXml.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\resources.cpp" />
<Unit filename="library\resources.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
+ <Unit filename="library\shadow.cpp" />
+ <Unit filename="library\shadow.h">
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\statistics.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="library\statistics.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\statusHandler.cpp" />
<Unit filename="library\statusHandler.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="library\tinyxml\tinystr.cpp" />
<Unit filename="library\tinyxml\tinyxml.cpp" />
<Unit filename="library\tinyxml\tinyxmlerror.cpp" />
<Unit filename="library\tinyxml\tinyxmlparser.cpp" />
<Unit filename="library\zstring.cpp" />
- <Unit filename="library\zstring.h" />
+ <Unit filename="library\zstring.h">
+ <Option target="&lt;{~None~}&gt;" />
+ </Unit>
<Unit filename="resource.rc">
<Option compilerVar="WINDRES" />
<Option target="Debug" />
@@ -226,89 +249,77 @@
</Unit>
<Unit filename="structures.cpp" />
<Unit filename="structures.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="synchronization.cpp" />
<Unit filename="synchronization.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\batchStatusHandler.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\batchStatusHandler.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\checkVersion.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\checkVersion.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\dragAndDrop.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\dragAndDrop.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\gridView.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\gridView.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\guiGenerated.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\guiGenerated.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\guiStatusHandler.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\guiStatusHandler.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\mainDialog.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\mainDialog.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\smallDialogs.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\smallDialogs.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\sorting.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Unit filename="ui\syncDialog.cpp">
<Option target="Debug" />
<Option target="Release" />
</Unit>
<Unit filename="ui\syncDialog.h">
- <Option target="Debug" />
- <Option target="Release" />
+ <Option target="&lt;{~None~}&gt;" />
</Unit>
<Extensions>
<code_completion />
diff --git a/FreeFileSync.vcproj b/FreeFileSync.vcproj
new file mode 100644
index 00000000..81692ad0
--- /dev/null
+++ b/FreeFileSync.vcproj
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="FreeFileSync"
+ ProjectGUID="{147B0400-A05F-4EEC-9702-F0EEB3C5DF06}"
+ RootNamespace="FreeFileSync"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="OBJ\$(ConfigurationName)"
+ IntermediateDirectory="OBJ\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswud&quot;"
+ PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;__WXDEBUG__;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4290"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="0"
+ AdditionalIncludeDirectories="C:\Programme\C++\wxWidgets\include;C:\Programme\C++\wxWidgets\lib\vc_lib\mswud"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wxmsw28ud_adv.lib &#x0A;wxmsw28ud_core.lib &#x0A;wxbase28ud.lib &#x0A;wxpngd.lib&#x0A; wxzlibd.lib &#x0A;wxbase28ud_net.lib comctl32.lib ws2_32.lib Rpcrt4.lib"
+ OutputFile="BUILD\$(ProjectName).exe"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
+ GenerateManifest="true"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="true"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="clean up"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="OBJ\$(ConfigurationName)"
+ IntermediateDirectory="OBJ\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswu&quot;"
+ PreprocessorDefinitions="wxUSE_UNICODE;__WXMSW__;FFS_WIN;NDEBUG;TIXML_USE_STL;ZSTRING_WIDE_CHAR"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4290"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ Culture="1033"
+ AdditionalIncludeDirectories="&quot;C:\Programme\C++\wxWidgets\include&quot;;&quot;C:\Programme\C++\wxWidgets\lib\vc_lib\mswu&quot;"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="wxmsw28u_adv.lib &#x0A;wxmsw28u_core.lib &#x0A;wxbase28u.lib &#x0A;wxpng.lib &#x0A;wxzlib.lib &#x0A;wxbase28u_net.lib comctl32.lib ws2_32.lib"
+ OutputFile="BUILD\$(ProjectName).exe"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\Programme\C++\wxWidgets\lib\vc_lib"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\algorithm.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\application.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\batchStatusHandler.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\checkVersion.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\comparison.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\customButton.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\customGrid.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\dragAndDrop.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\fileHandling.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\filter.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\globalFunctions.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\gridView.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\guiGenerated.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\guiStatusHandler.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\iconBuffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\localization.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\mainDialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\processXml.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\resources.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\shadow.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\smallDialogs.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\statistics.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\statusHandler.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\structures.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\syncDialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\synchronization.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinystr.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinyxml.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinyxmlerror.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinyxmlparser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\library\zstring.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\algorithm.h"
+ >
+ </File>
+ <File
+ RelativePath=".\application.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\batchStatusHandler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\checkVersion.h"
+ >
+ </File>
+ <File
+ RelativePath=".\comparison.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\customButton.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\customGrid.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\dragAndDrop.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\fileError.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\fileHandling.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\filter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\globalFunctions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\gridView.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\guiGenerated.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\guiStatusHandler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\iconBuffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\localization.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\mainDialog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\pch.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\processXml.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\resources.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\shadow.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\smallDialogs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\sorting.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\statistics.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\statusHandler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\structures.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ui\syncDialog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\synchronization.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinystr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\tinyxml\tinyxml.h"
+ >
+ </File>
+ <File
+ RelativePath=".\library\zstring.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\resource.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_UNICODE;UNICODE;wxUSE_NO_MANIFEST"
+ Culture="1033"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_UNICODE;UNICODE;wxUSE_NO_MANIFEST"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Makefile b/Makefile
index 42349022..11195262 100644
--- a/Makefile
+++ b/Makefile
@@ -1,103 +1,104 @@
-CPPFLAGS=-Wall -pipe -DNDEBUG `wx-config --cppflags` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -O3 -pthread -c
+CPPFLAGS=-Wall -pipe -DNDEBUG `wx-config --cppflags` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c
ENDFLAGS=`wx-config --libs` -O3 -pthread
all: FreeFileSync
init:
- if [ ! -d obj ]; then mkdir obj; fi
+ if [ ! -d OBJ ]; then mkdir OBJ; fi
+removeBOM: tools/removeBOM.cpp
+ g++ -o removeBOM tools/removeBOM.cpp
+
structures.o: structures.cpp
- g++ $(CPPFLAGS) structures.cpp -o obj/structures.o
+ g++ $(CPPFLAGS) structures.cpp -o OBJ/structures.o
algorithm.o: algorithm.cpp
- g++ $(CPPFLAGS) algorithm.cpp -o obj/algorithm.o
+ g++ $(CPPFLAGS) algorithm.cpp -o OBJ/algorithm.o
comparison.o: comparison.cpp
- g++ $(CPPFLAGS) comparison.cpp -o obj/comparison.o
+ g++ $(CPPFLAGS) comparison.cpp -o OBJ/comparison.o
synchronization.o: synchronization.cpp
- g++ $(CPPFLAGS) synchronization.cpp -o obj/synchronization.o
+ g++ $(CPPFLAGS) synchronization.cpp -o OBJ/synchronization.o
application.o: application.cpp
- g++ $(CPPFLAGS) application.cpp -o obj/application.o
+ g++ $(CPPFLAGS) application.cpp -o OBJ/application.o
globalFunctions.o: library/globalFunctions.cpp
- g++ $(CPPFLAGS) library/globalFunctions.cpp -o obj/globalFunctions.o
+ g++ $(CPPFLAGS) library/globalFunctions.cpp -o OBJ/globalFunctions.o
guiGenerated.o: ui/guiGenerated.cpp
- g++ $(CPPFLAGS) ui/guiGenerated.cpp -o obj/guiGenerated.o
+ g++ $(CPPFLAGS) ui/guiGenerated.cpp -o OBJ/guiGenerated.o
gridView.o: ui/gridView.cpp
- g++ $(CPPFLAGS) ui/gridView.cpp -o obj/gridView.o
+ g++ $(CPPFLAGS) ui/gridView.cpp -o OBJ/gridView.o
mainDialog.o: ui/mainDialog.cpp
- g++ $(CPPFLAGS) ui/mainDialog.cpp -o obj/mainDialog.o
+ g++ $(CPPFLAGS) ui/mainDialog.cpp -o OBJ/mainDialog.o
syncDialog.o: ui/syncDialog.cpp
- g++ $(CPPFLAGS) ui/syncDialog.cpp -o obj/syncDialog.o
+ g++ $(CPPFLAGS) ui/syncDialog.cpp -o OBJ/syncDialog.o
checkVersion.o: ui/checkVersion.cpp
- g++ $(CPPFLAGS) ui/checkVersion.cpp -o obj/checkVersion.o
+ g++ $(CPPFLAGS) ui/checkVersion.cpp -o OBJ/checkVersion.o
batchStatusHandler.o: ui/batchStatusHandler.cpp
- g++ $(CPPFLAGS) ui/batchStatusHandler.cpp -o obj/batchStatusHandler.o
+ g++ $(CPPFLAGS) ui/batchStatusHandler.cpp -o OBJ/batchStatusHandler.o
guiStatusHandler.o: ui/guiStatusHandler.cpp
- g++ $(CPPFLAGS) ui/guiStatusHandler.cpp -o obj/guiStatusHandler.o
+ g++ $(CPPFLAGS) ui/guiStatusHandler.cpp -o OBJ/guiStatusHandler.o
customGrid.o: library/customGrid.cpp
- g++ $(CPPFLAGS) library/customGrid.cpp -o obj/customGrid.o
+ g++ $(CPPFLAGS) library/customGrid.cpp -o OBJ/customGrid.o
fileHandling.o: library/fileHandling.cpp
- g++ $(CPPFLAGS) library/fileHandling.cpp -o obj/fileHandling.o
-
-multithreading.o: library/multithreading.cpp
- g++ $(CPPFLAGS) library/multithreading.cpp -o obj/multithreading.o
+ g++ $(CPPFLAGS) library/fileHandling.cpp -o OBJ/fileHandling.o
statusHandler.o: library/statusHandler.cpp
- g++ $(CPPFLAGS) library/statusHandler.cpp -o obj/statusHandler.o
+ g++ $(CPPFLAGS) library/statusHandler.cpp -o OBJ/statusHandler.o
resources.o: library/resources.cpp
- g++ $(CPPFLAGS) library/resources.cpp -o obj/resources.o
+ g++ $(CPPFLAGS) library/resources.cpp -o OBJ/resources.o
smallDialogs.o: ui/smallDialogs.cpp
- g++ $(CPPFLAGS) ui/smallDialogs.cpp -o obj/smallDialogs.o
+ g++ $(CPPFLAGS) ui/smallDialogs.cpp -o OBJ/smallDialogs.o
dragAndDrop.o: ui/dragAndDrop.cpp
- g++ $(CPPFLAGS) ui/dragAndDrop.cpp -o obj/dragAndDrop.o
+ g++ $(CPPFLAGS) ui/dragAndDrop.cpp -o OBJ/dragAndDrop.o
-localization.o: library/localization.cpp
- g++ $(CPPFLAGS) library/localization.cpp -o obj/localization.o
+localization.o: library/localization.cpp removeBOM
+ ./removeBOM library/localization.cpp
+ g++ $(CPPFLAGS) library/localization.cpp -o OBJ/localization.o
tinyxml.o: library/tinyxml/tinyxml.cpp
- g++ $(CPPFLAGS) library/tinyxml/tinyxml.cpp -o obj/tinyxml.o
+ g++ $(CPPFLAGS) library/tinyxml/tinyxml.cpp -o OBJ/tinyxml.o
tinystr.o: library/tinyxml/tinystr.cpp
- g++ $(CPPFLAGS) library/tinyxml/tinystr.cpp -o obj/tinystr.o
+ g++ $(CPPFLAGS) library/tinyxml/tinystr.cpp -o OBJ/tinystr.o
tinyxmlerror.o: library/tinyxml/tinyxmlerror.cpp
- g++ $(CPPFLAGS) library/tinyxml/tinyxmlerror.cpp -o obj/tinyxmlerror.o
+ g++ $(CPPFLAGS) library/tinyxml/tinyxmlerror.cpp -o OBJ/tinyxmlerror.o
tinyxmlparser.o: library/tinyxml/tinyxmlparser.cpp
- g++ $(CPPFLAGS) library/tinyxml/tinyxmlparser.cpp -o obj/tinyxmlparser.o
+ g++ $(CPPFLAGS) library/tinyxml/tinyxmlparser.cpp -o OBJ/tinyxmlparser.o
processXml.o: library/processXml.cpp
- g++ $(CPPFLAGS) library/processXml.cpp -o obj/processXml.o
+ g++ $(CPPFLAGS) library/processXml.cpp -o OBJ/processXml.o
statistics.o: library/statistics.cpp
- g++ $(CPPFLAGS) library/statistics.cpp -o obj/statistics.o
+ g++ $(CPPFLAGS) library/statistics.cpp -o OBJ/statistics.o
zstring.o: library/zstring.cpp
- g++ $(CPPFLAGS) library/zstring.cpp -o obj/zstring.o
+ g++ $(CPPFLAGS) library/zstring.cpp -o OBJ/zstring.o
customButton.o: library/customButton.cpp
- g++ $(CPPFLAGS) library/customButton.cpp -o obj/customButton.o
+ g++ $(CPPFLAGS) library/customButton.cpp -o OBJ/customButton.o
filter.o: library/filter.cpp
- g++ $(CPPFLAGS) library/filter.cpp -o obj/filter.o
+ g++ $(CPPFLAGS) library/filter.cpp -o OBJ/filter.o
-FreeFileSync: init application.o structures.o algorithm.o comparison.o customButton.o filter.o checkVersion.o batchStatusHandler.o guiStatusHandler.o synchronization.o globalFunctions.o guiGenerated.o gridView.o mainDialog.o syncDialog.o customGrid.o fileHandling.o resources.o smallDialogs.o dragAndDrop.o multithreading.o statusHandler.o localization.o tinyxml.o tinystr.o tinyxmlerror.o tinyxmlparser.o processXml.o statistics.o zstring.o
- g++ $(ENDFLAGS) -o FreeFileSync obj/application.o obj/structures.o obj/algorithm.o obj/comparison.o obj/customButton.o obj/filter.o obj/batchStatusHandler.o obj/guiStatusHandler.o obj/checkVersion.o obj/synchronization.o obj/globalFunctions.o obj/guiGenerated.o obj/gridView.o obj/mainDialog.o obj/syncDialog.o obj/customGrid.o obj/fileHandling.o obj/resources.o obj/smallDialogs.o obj/dragAndDrop.o obj/multithreading.o obj/statusHandler.o obj/localization.o obj/tinyxml.o obj/tinystr.o obj/tinyxmlerror.o obj/tinyxmlparser.o obj/processXml.o obj/statistics.o obj/zstring.o
+FreeFileSync: init application.o structures.o algorithm.o comparison.o customButton.o filter.o checkVersion.o batchStatusHandler.o guiStatusHandler.o synchronization.o globalFunctions.o guiGenerated.o gridView.o mainDialog.o syncDialog.o customGrid.o fileHandling.o resources.o smallDialogs.o dragAndDrop.o statusHandler.o localization.o tinyxml.o tinystr.o tinyxmlerror.o tinyxmlparser.o processXml.o statistics.o zstring.o
+ g++ $(ENDFLAGS) -o BUILD/FreeFileSync OBJ/application.o OBJ/structures.o OBJ/algorithm.o OBJ/comparison.o OBJ/customButton.o OBJ/filter.o OBJ/batchStatusHandler.o OBJ/guiStatusHandler.o OBJ/checkVersion.o OBJ/synchronization.o OBJ/globalFunctions.o OBJ/guiGenerated.o OBJ/gridView.o OBJ/mainDialog.o OBJ/syncDialog.o OBJ/customGrid.o OBJ/fileHandling.o OBJ/resources.o OBJ/smallDialogs.o OBJ/dragAndDrop.o OBJ/statusHandler.o OBJ/localization.o OBJ/tinyxml.o OBJ/tinystr.o OBJ/tinyxmlerror.o OBJ/tinyxmlparser.o OBJ/processXml.o OBJ/statistics.o OBJ/zstring.o
clean:
find obj -type f -exec rm {} \;
diff --git a/Makefile_Win.cmd b/Makefile_Win.cmd
deleted file mode 100644
index 2296d1f6..00000000
--- a/Makefile_Win.cmd
+++ /dev/null
@@ -1,45 +0,0 @@
-::-------------------------------------------------------
-::set these variables to the appropriate directories
-set widgets=C:\Programme\C++\wxWidgets
-set widgetslib=C:\Programme\C++\wxWidgets\lib\gcc_lib\mswu
-set sources=.
-set mingw=C:\Programme\C++\MinGW\bin
-::-------------------------------------------------------
-
-set parameters=-Wall -pipe -mthreads -D__GNUWIN32__ -DwxUSE_UNICODE -D__WXMSW__ -DFFS_WIN -O3 -DNDEBUG -DTIXML_USE_STL
-path=%path%;%mingw%
-if not exist obj md obj
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\structures.cpp -o obj\structures.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\application.cpp -o obj\application.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\algorithm.cpp -o obj\algorithm.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\comparison.cpp -o obj\comparison.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\synchronization.cpp -o obj\synchronization.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\globalFunctions.cpp -o obj\globalFunctions.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\multithreading.cpp -o obj\multithreading.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\statusHandler.cpp -o obj\statusHandler.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\fileHandling.cpp -o obj\fileHandling.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\guiGenerated.cpp -o obj\GUI_Generated.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\gridView.cpp -o obj\gridView.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\mainDialog.cpp -o obj\MainDialog.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\syncDialog.cpp -o obj\SyncDialog.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\checkVersion.cpp -o obj\checkVersion.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\batchStatusHandler.cpp -o obj\batchStatusHandler.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\guiStatusHandler.cpp -o obj\guiStatusHandler.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\customGrid.cpp -o obj\CustomGrid.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\resources.cpp -o obj\Resources.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\localization.cpp -o obj\localization.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\statistics.cpp -o obj\statistics.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\smallDialogs.cpp -o obj\SmallDialogs.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\ui\dragAndDrop.cpp -o obj\dragAndDrop.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\tinyxml\tinyxml.cpp -o obj\tinyxml.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\tinyxml\tinystr.cpp -o obj\tinystr.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\tinyxml\tinyxmlerror.cpp -o obj\tinyxmlerror.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\tinyxml\tinyxmlparser.cpp -o obj\tinyxmlparser.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\processXml.cpp -o obj\processXml.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\zstring.cpp -o obj\zstring.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\customButton.cpp -o obj\customButton.o
-mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\filter.cpp -o obj\filter.o
-
-windres.exe -i %sources%\resource.rc -J rc -o obj\resource.res -O coff -I%widgets%\include -I%widgetslib%
-mingw32-g++.exe -L%widgets%\lib\gcc_lib -o FreeFileSync.exe obj\structures.o obj\application.o obj\algorithm.o obj\dragAndDrop.o obj\comparison.o obj\batchStatusHandler.o obj\statistics.o obj\guiStatusHandler.o obj\synchronization.o obj\globalFunctions.o obj\checkVersion.o obj\multithreading.o obj\statusHandler.o obj\fileHandling.o obj\customButton.o obj\filter.o obj\localization.o obj\GUI_Generated.o obj\gridView.o obj\MainDialog.o obj\SyncDialog.o obj\CustomGrid.o obj\Resources.o obj\SmallDialogs.o obj\resource.res obj\tinyxml.o obj\tinystr.o obj\tinyxmlerror.o obj\tinyxmlparser.o obj\processXml.o obj\zstring.o -s -mthreads -lwxmsw28u_adv -lwxmsw28u_core -lwxbase28u_net -lwxbase28u -lwxpng -lwxzlib -lkernel32 -lws2_32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 -mwindows
-pause \ No newline at end of file
diff --git a/algorithm.cpp b/algorithm.cpp
index 00c1e81f..4ce2c911 100644
--- a/algorithm.cpp
+++ b/algorithm.cpp
@@ -87,17 +87,17 @@ wxString FreeFileSync::formatFilesizeToShortString(const double filesize)
case 0:
return _("Error");
case 1:
- temp = wxString(wxT("0")) + GlobalResources::DECIMAL_POINT + wxT("0") + temp;
+ temp = wxString(wxT("0")) + FreeFileSync::DECIMAL_POINT + wxT("0") + temp;
break; //0,01
case 2:
- temp = wxString(wxT("0")) + GlobalResources::DECIMAL_POINT + temp;
+ temp = wxString(wxT("0")) + FreeFileSync::DECIMAL_POINT + temp;
break; //0,11
case 3:
- temp.insert(1, GlobalResources::DECIMAL_POINT);
+ temp.insert(1, FreeFileSync::DECIMAL_POINT);
break; //1,11
case 4:
temp = temp.substr(0, 3);
- temp.insert(2, GlobalResources::DECIMAL_POINT);
+ temp.insert(2, FreeFileSync::DECIMAL_POINT);
break; //11,1
case 5:
temp = temp.substr(0, 3);
@@ -122,14 +122,14 @@ Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname)
return Zstring();
if (!endsWithPathSeparator(dirnameTmp))
- dirnameTmp += GlobalResources::FILE_NAME_SEPARATOR;
+ dirnameTmp += FreeFileSync::FILE_NAME_SEPARATOR;
//don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix
return dirnameTmp;
}
-void FreeFileSync::swapGrids(FolderComparison& folderCmp)
+void FreeFileSync::swapGrids(const SyncConfiguration& config, FolderComparison& folderCmp)
{
for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
{
@@ -148,16 +148,57 @@ void FreeFileSync::swapGrids(FolderComparison& folderCmp)
else if (i->cmpResult == FILE_LEFT_NEWER)
i->cmpResult = FILE_RIGHT_NEWER;
- //swap sync direction
- if (i->direction == SYNC_DIR_LEFT)
- i->direction = SYNC_DIR_RIGHT;
- else if (i->direction == SYNC_DIR_RIGHT)
- i->direction = SYNC_DIR_LEFT;
-
//swap file descriptors
std::swap(i->fileDescrLeft, i->fileDescrRight);
}
}
+
+ //adjust sync direction
+ redetermineSyncDirection(config, folderCmp);
+}
+
+
+void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, FolderComparison& folderCmp)
+{
+ //do not handle i->selectedForSynchronization in this method! handled in synchronizeFile(), synchronizeFolder()!
+
+
+ for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
+ {
+ FileComparison& fileCmp = j->fileCmp;
+ for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
+ {
+ switch (i->cmpResult)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ i->direction = config.exLeftSideOnly;
+ break;
+
+ case FILE_RIGHT_SIDE_ONLY:
+ i->direction = config.exRightSideOnly;
+ break;
+
+ case FILE_RIGHT_NEWER:
+ i->direction = config.rightNewer;
+ break;
+
+ case FILE_LEFT_NEWER:
+ i->direction = config.leftNewer;
+ break;
+
+ case FILE_DIFFERENT:
+ i->direction = config.different;
+ break;
+
+ case FILE_CONFLICT:
+ i->direction = SYNC_UNRESOLVED_CONFLICT;
+ break;
+
+ case FILE_EQUAL:
+ i->direction = SYNC_DIR_NONE;
+ }
+ }
+ }
}
@@ -175,7 +216,7 @@ void FreeFileSync::addSubElements(const FileComparison& fileCmp, const FileCompa
else
return;
- relevantDirectory += GlobalResources::FILE_NAME_SEPARATOR; //FILE_NAME_SEPARATOR needed to exclude subfile/dirs only
+ relevantDirectory += FreeFileSync::FILE_NAME_SEPARATOR; //FILE_NAME_SEPARATOR needed to exclude subfile/dirs only
for (FileComparison::const_iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
{
@@ -266,7 +307,7 @@ wxString FreeFileSync::deleteFromGridAndHDPreview(const FileComparison& fileCmp,
}
wxString filesToDelete;
- for (std::set<SortedFileName>::iterator i = outputTable.begin(); i != outputTable.end(); ++i)
+ for (std::set<SortedFileName>::const_iterator i = outputTable.begin(); i != outputTable.end(); ++i)
filesToDelete += (i->name + wxT("\n")).c_str();
return filesToDelete;
@@ -282,7 +323,7 @@ public:
~RemoveAtExit()
{
- removeRowsFromVector(gridToWrite, rowsProcessed);
+ globalFunctions::removeRowsFromVector(rowsProcessed, gridToWrite);
}
void removeRow(int nr)
@@ -348,7 +389,7 @@ void deleteFromGridAndHDOneSide(FileComparison& fileCmp,
const SyncConfiguration& syncConfig,
ErrorHandler* errorHandler)
{
- for (std::set<int>::iterator i = rowsToDeleteOneSide.begin(); i != rowsToDeleteOneSide.end(); ++i)
+ for (std::set<int>::const_iterator i = rowsToDeleteOneSide.begin(); i != rowsToDeleteOneSide.end(); ++i)
{
//get descriptor for file to be deleted; evaluated at compile time
const FileDescrLine* const fileDescr = leftSide ? &fileCmp[*i].fileDescrLeft : &fileCmp[*i].fileDescrRight;
@@ -494,9 +535,9 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zst
wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") +
filename.c_str() + wxT("\n\n") + getLastErrorFormatted().c_str());
- if (localFileTime.dwHighDateTime > 2147483647) //== 256^4 / 2 - 1 == 0x7fffffff
+ if (localFileTime.dwHighDateTime > 0x7fffffff)
return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever!
- //Testcase (UTC): dateHigh = 2147483647 -> year 30000
+ //Testcase (UTC): dateHigh = 2147483647 (=0x7fffffff) -> year 30000
// dateLow = 4294967295
SYSTEMTIME time;
@@ -543,7 +584,7 @@ wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zst
#ifdef FFS_WIN
Zstring FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try to get additional Windows error information
{
- //determine error code if none was specified
+ //determine error code if none was specified
const unsigned long lastErrorCode = lastError == 0 ? GetLastError() : lastError;
Zstring output = Zstring(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastErrorCode).c_str();
diff --git a/algorithm.h b/algorithm.h
index f05eb95d..13d3d0fc 100644
--- a/algorithm.h
+++ b/algorithm.h
@@ -17,7 +17,9 @@ namespace FreeFileSync
bool endsWithPathSeparator(const Zstring& name);
- void swapGrids(FolderComparison& folderCmp);
+ void swapGrids(const SyncConfiguration& config, FolderComparison& folderCmp);
+
+ void redetermineSyncDirection(const SyncConfiguration& config, FolderComparison& folderCmp);
void addSubElements(const FileComparison& fileCmp, const FileCompareLine& relevantRow, std::set<int>& subElements);
@@ -62,7 +64,7 @@ inline
bool FreeFileSync::endsWithPathSeparator(const Zstring& name)
{
const size_t len = name.length();
- return len && (name[len - 1] == GlobalResources::FILE_NAME_SEPARATOR);
+ return len && (name[len - 1] == FreeFileSync::FILE_NAME_SEPARATOR);
}
diff --git a/comparison.cpp b/comparison.cpp
index 253b3d81..3305a510 100644
--- a/comparison.cpp
+++ b/comparison.cpp
@@ -12,10 +12,7 @@
#include "library/fileHandling.h"
#include "synchronization.h"
#include "library/filter.h"
-
-#ifdef FFS_WIN
-#include <wx/msw/wrapwin.h> //includes "windows.h"
-#endif //FFS_WIN
+#include "library/processXml.h"
using namespace FreeFileSync;
@@ -45,8 +42,13 @@ public:
wxDirTraverseResult OnFile(const Zstring& fullFileName, const FileInfo& details) //virtual impl.
{
//apply filter before processing (use relative name!)
- if (filterInstance && !filterInstance->matchesFileFilter(fullFileName.c_str() + prefixLength))
- return wxDIR_CONTINUE;
+ if (filterInstance)
+ if ( !filterInstance->matchesFileFilterIncl(fullFileName.c_str() + prefixLength) ||
+ filterInstance->matchesFileFilterExcl(fullFileName.c_str() + prefixLength))
+ {
+ statusHandler->requestUiRefresh();
+ return wxDIR_CONTINUE;
+ }
FileDescrLine fileDescr;
fileDescr.fullName = fullFileName;
@@ -83,13 +85,26 @@ public:
wxDirTraverseResult OnDir(const Zstring& fullDirName) //virtual impl.
{
//apply filter before processing (use relative name!)
- if (filterInstance && !filterInstance->matchesDirFilter(fullDirName.c_str() + prefixLength))
- return wxDIR_IGNORE;
-
+ if (filterInstance)
+ {
+ if (!filterInstance->matchesDirFilterIncl(fullDirName.c_str() + prefixLength))
+ {
+ statusHandler->requestUiRefresh(); //if not included: CONTINUE traversing subdirs
+ return wxDIR_CONTINUE;
+ }
+ else if (filterInstance->matchesDirFilterExcl(fullDirName.c_str() + prefixLength))
+ {
+ statusHandler->requestUiRefresh(); //if excluded: do NOT traverse subdirs
+ return wxDIR_IGNORE;
+ }
+ }
#ifdef FFS_WIN
if ( fullDirName.EndsWith(wxT("\\RECYCLER")) ||
fullDirName.EndsWith(wxT("\\System Volume Information")))
+ {
+ statusHandler->requestUiRefresh();
return wxDIR_IGNORE;
+ }
#endif // FFS_WIN
FileDescrLine fileDescr;
@@ -292,12 +307,12 @@ bool foldersHaveDependencies(const std::vector<FolderPair>& folderPairs, wxStrin
CompareProcess::CompareProcess(const bool traverseSymLinks,
const unsigned int fileTimeTol,
const bool ignoreOneHourDiff,
- bool& warningDependentFolders,
+ xmlAccess::WarningMessages& warnings,
const FilterProcess* filter, //may be NULL
StatusHandler* handler) :
fileTimeTolerance(fileTimeTol),
ignoreOneHourDifference(ignoreOneHourDiff),
- m_warningDependentFolders(warningDependentFolders),
+ m_warnings(warnings),
statusUpdater(handler),
txtComparingContentOfFiles(Zstring(_("Comparing content of files %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false))
{
@@ -487,7 +502,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director
//init process: keep at beginning so that all gui elements are initialized properly
statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects
- //format directory pairs: ensure they end with GlobalResources::FILE_NAME_SEPARATOR!
+ //format directory pairs: ensure they end with FreeFileSync::FILE_NAME_SEPARATOR!
std::vector<FolderPair> directoryPairsFormatted;
for (std::vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i)
directoryPairsFormatted.push_back(
@@ -505,7 +520,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director
}
//check if folders have dependencies
- if (m_warningDependentFolders) //test if check should be executed
+ if (m_warnings.warningDependentFolders) //test if check should be executed
{
wxString warningMessage;
if (foldersHaveDependencies(directoryPairsFormatted, warningMessage))
@@ -513,7 +528,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director
bool dontShowAgain = false;
statusUpdater->reportWarning(warningMessage.c_str(),
dontShowAgain);
- m_warningDependentFolders = !dontShowAgain;
+ m_warnings.warningDependentFolders = !dontShowAgain;
}
}
@@ -553,6 +568,59 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPair>& director
}
+//check for very old dates or dates in the future
+void CompareProcess::issueWarningInvalidDate(const Zstring& fileNameFull, const wxLongLong& utcTime)
+{
+ if (m_warnings.warningInvalidDate)
+ {
+ bool dontShowAgain = false;
+ Zstring msg = Zstring(_("File %x has an invalid date!")).Replace(wxT("%x"), Zstring(wxT("\"")) + fileNameFull + wxT("\""));
+ msg += Zstring(wxT("\n\n")) + _("Date") + wxT(": ") + utcTimeToLocalString(utcTime, fileNameFull).c_str();
+ statusUpdater->reportWarning(Zstring(_("Conflict detected:")) + wxT("\n") + msg,
+ dontShowAgain);
+ m_warnings.warningInvalidDate = !dontShowAgain;
+ }
+}
+
+
+//check for changed files with same modification date
+void CompareProcess::issueWarningSameDateDiffSize(const FileCompareLine& cmpLine)
+{
+ if (m_warnings.warningSameDateDiffSize)
+ {
+ bool dontShowAgain = false;
+ Zstring msg = Zstring(_("Files %x have the same date but a different size!")).Replace(wxT("%x"), Zstring(wxT("\"")) + cmpLine.fileDescrLeft.relativeName.c_str() + wxT("\""));
+ msg += wxT("\n\n");
+ msg += Zstring(_("Left:")) + wxT(" \t") + _("Date") + wxT(": ") + utcTimeToLocalString(cmpLine.fileDescrLeft.lastWriteTimeRaw,
+ cmpLine.fileDescrLeft.fullName).c_str() + wxT(" \t") + _("Size") + wxT(": ") + cmpLine.fileDescrLeft.fileSize.ToString().c_str() + wxT("\n");
+ msg += Zstring(_("Right:")) + wxT(" \t") + _("Date") + wxT(": ") + utcTimeToLocalString(cmpLine.fileDescrRight.lastWriteTimeRaw,
+ cmpLine.fileDescrRight.fullName).c_str() + wxT(" \t") + _("Size") + wxT(": ") + cmpLine.fileDescrRight.fileSize.ToString().c_str();
+
+ statusUpdater->reportWarning(Zstring(_("Conflict detected:")) + wxT("\n") + msg,
+ dontShowAgain);
+ m_warnings.warningSameDateDiffSize = !dontShowAgain;
+ }
+}
+
+
+//check for files that have a difference in file modification date below 1 hour when DST check is active
+void CompareProcess::issueWarningChangeWithinHour(const FileCompareLine& cmpLine)
+{
+ if (m_warnings.warningDSTChangeWithinHour)
+ {
+ bool dontShowAgain = false;
+ Zstring msg = Zstring(_("Files %x have a file time difference of less than 1 hour! It's not safe to decide which one is newer due to Daylight Saving Time issues.")).Replace(wxT("%x"), Zstring(wxT("\"")) + cmpLine.fileDescrLeft.relativeName.c_str() + wxT("\""));
+ msg += wxT("\n\n");
+ msg += Zstring(_("Left:")) + wxT(" \t") + _("Date") + wxT(": ") + utcTimeToLocalString(cmpLine.fileDescrLeft.lastWriteTimeRaw, cmpLine.fileDescrLeft.fullName).c_str() + wxT("\n");
+ msg += Zstring(_("Right:")) + wxT(" \t") + _("Date") + wxT(": ") + utcTimeToLocalString(cmpLine.fileDescrRight.lastWriteTimeRaw, cmpLine.fileDescrRight.fullName).c_str();
+
+ statusUpdater->reportWarning(Zstring(_("Conflict detected:")) + wxT("\n") + msg,
+ dontShowAgain);
+ m_warnings.warningDSTChangeWithinHour = !dontShowAgain;
+ }
+}
+
+
const CompareFilesResult FILE_UNDEFINED = CompareFilesResult(42);
@@ -596,6 +664,10 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP
i->fileDescrRight.lastWriteTimeRaw > oneYearFromNow) //dated more than one year in future
{
i->cmpResult = FILE_CONFLICT;
+ if (i->fileDescrLeft.lastWriteTimeRaw < 0 || i->fileDescrLeft.lastWriteTimeRaw > oneYearFromNow)
+ issueWarningInvalidDate(i->fileDescrLeft.fullName, i->fileDescrLeft.lastWriteTimeRaw);
+ else
+ issueWarningInvalidDate(i->fileDescrRight.fullName, i->fileDescrRight.lastWriteTimeRaw);
}
else //from this block on all dates are at least "valid"
{
@@ -605,7 +677,10 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP
if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize)
i->cmpResult = FILE_EQUAL;
else
+ {
i->cmpResult = FILE_CONFLICT; //same date, different filesize
+ issueWarningSameDateDiffSize(*i);
+ }
}
else
{
@@ -616,13 +691,17 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP
if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, 3600 - 2 - 1))
{
i->cmpResult = FILE_CONFLICT;
+ issueWarningChangeWithinHour(*i);
}
else //exact +/- 1-hour detected: treat as equal
{
if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize)
i->cmpResult = FILE_EQUAL;
else
+ {
i->cmpResult = FILE_CONFLICT; //same date, different filesize
+ issueWarningSameDateDiffSize(*i);
+ }
}
}
else
@@ -640,7 +719,10 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP
if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize)
i->cmpResult = FILE_EQUAL;
else
+ {
i->cmpResult = FILE_CONFLICT; //same date, different filesize
+ issueWarningSameDateDiffSize(*i);
+ }
}
}
}
@@ -655,7 +737,7 @@ public:
~RemoveAtExit()
{
- removeRowsFromVector(gridToWrite, rowsToDelete);
+ globalFunctions::removeRowsFromVector(rowsToDelete, gridToWrite);
}
void markRow(int nr)
@@ -679,7 +761,7 @@ void getBytesToCompare(const FolderComparison& grid, const FolderCompRef& rowsTo
const FileComparison& fileCmp = j->fileCmp;
const std::set<int>& index = rowsToCompare[j - grid.begin()];
- for (std::set<int>::iterator i = index.begin(); i != index.end(); ++i)
+ for (std::set<int>::const_iterator i = index.begin(); i != index.end(); ++i)
{
const FileCompareLine& line = fileCmp[*i];
dataTotal += line.fileDescrLeft.fileSize;
@@ -749,7 +831,7 @@ void CompareProcess::compareByContent(const std::vector<FolderPair>& directoryPa
RemoveAtExit removeRowsAtExit(fileCmp); //note: running at individual folder pair level!
const std::set<int>& index = rowsToCompareBytewise[j - output.begin()];
- for (std::set<int>::iterator i = index.begin(); i != index.end(); ++i)
+ for (std::set<int>::const_iterator i = index.begin(); i != index.end(); ++i)
{
FileCompareLine& gridline = fileCmp[*i];
diff --git a/comparison.h b/comparison.h
index 2ec212ab..eaa4e2c8 100644
--- a/comparison.h
+++ b/comparison.h
@@ -2,11 +2,11 @@
#define COMPARISON_H_INCLUDED
#include "structures.h"
+#include "library/processXml.h"
class StatusHandler;
class DirectoryDescrBuffer;
-
namespace FreeFileSync
{
class FilterProcess;
@@ -18,7 +18,7 @@ namespace FreeFileSync
CompareProcess(const bool traverseSymLinks,
const unsigned fileTimeTol,
const bool ignoreOneHourDiff,
- bool& warningDependentFolders,
+ xmlAccess::WarningMessages& warnings,
const FilterProcess* filter, //may be NULL
StatusHandler* handler);
@@ -37,13 +37,19 @@ namespace FreeFileSync
//create comparison result table and fill relation except for files existing on both sides
void performBaseComparison(const FolderPair& pair, FileComparison& output);
+
+ void issueWarningInvalidDate(const Zstring& fileNameFull, const wxLongLong& utcTime);
+ void issueWarningSameDateDiffSize(const FileCompareLine& cmpLine);
+ void issueWarningChangeWithinHour(const FileCompareLine& cmpLine);
+
+
//buffer accesses to the same directories; useful when multiple folder pairs are used
DirectoryDescrBuffer* descriptionBuffer;
const unsigned int fileTimeTolerance; //max allowed file time deviation
const bool ignoreOneHourDifference;
- bool& m_warningDependentFolders;
+ xmlAccess::WarningMessages& m_warnings;
StatusHandler* statusUpdater;
const Zstring txtComparingContentOfFiles;
diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp
index 048bc5e0..591230e2 100644
--- a/library/CustomGrid.cpp
+++ b/library/CustomGrid.cpp
@@ -6,16 +6,19 @@
#include "resources.h"
#include <typeinfo>
#include "../ui/gridView.h"
+#include "../synchronization.h"
#ifdef FFS_WIN
+#include <wx/timer.h>
#include <wx/icon.h>
-#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "iconBuffer.h"
+#include "statusHandler.h"
+#include <cmath>
#elif defined FFS_LINUX
#include <gtk/gtk.h>
#endif
-
using namespace FreeFileSync;
@@ -234,6 +237,7 @@ public:
return xmlAccess::ColumnTypes(1000);
}
+ virtual Zstring getFileName(const unsigned int row) const = 0;
private:
std::vector<xmlAccess::ColumnTypes> columnPositions;
@@ -271,11 +275,11 @@ public:
switch (getTypeAtPos(col))
{
case xmlAccess::FULL_PATH:
- return wxString(gridLine->fileDescrLeft.fullName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrLeft.fullName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::FILENAME: //filename
- return wxString(gridLine->fileDescrLeft.relativeName.c_str()).AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrLeft.relativeName.c_str()).AfterLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::REL_PATH: //relative path
- return wxString(gridLine->fileDescrLeft.relativeName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrLeft.relativeName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::DIRECTORY:
return gridDataView->getFolderPair(row).leftDirectory.c_str();
case xmlAccess::SIZE: //file size
@@ -289,6 +293,17 @@ public:
return wxEmptyString;
}
+
+ virtual Zstring getFileName(const unsigned int row) const
+ {
+ const FileCompareLine* gridLine = getRawData(row);
+ if (gridLine)
+ return Zstring(gridLine->fileDescrLeft.fullName);
+ else
+ return Zstring();
+ }
+
+
private:
virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
{
@@ -340,11 +355,11 @@ public:
switch (getTypeAtPos(col))
{
case xmlAccess::FULL_PATH:
- return wxString(gridLine->fileDescrRight.fullName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrRight.fullName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::FILENAME: //filename
- return wxString(gridLine->fileDescrRight.relativeName.c_str()).AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrRight.relativeName.c_str()).AfterLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::REL_PATH: //relative path
- return wxString(gridLine->fileDescrRight.relativeName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ return wxString(gridLine->fileDescrRight.relativeName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
case xmlAccess::DIRECTORY:
return gridDataView->getFolderPair(row).rightDirectory.c_str();
case xmlAccess::SIZE: //file size
@@ -358,6 +373,17 @@ public:
return wxEmptyString;
}
+
+ virtual Zstring getFileName(const unsigned int row) const
+ {
+ const FileCompareLine* gridLine = getRawData(row);
+ if (gridLine)
+ return Zstring(gridLine->fileDescrRight.fullName);
+ else
+ return Zstring();
+ }
+
+
private:
virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color
{
@@ -476,27 +502,43 @@ CustomGrid::CustomGrid(wxWindow *parent,
m_gridMiddle(NULL),
m_gridRight(NULL),
isLeading(false),
- currentSortColumn(-1),
- sortMarker(NULL)
+ m_marker(-1, ASCENDING)
{
//set color of selections
wxColour darkBlue(40, 35, 140);
SetSelectionBackground(darkBlue);
SetSelectionForeground(*wxWHITE);
+}
- //enhance grid functionality; identify leading grid by keyboard input or scroll action
- Connect(wxEVT_KEY_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
- GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+void CustomGrid::initSettings(CustomGridLeft* gridLeft,
+ CustomGridMiddle* gridMiddle,
+ CustomGridRight* gridRight,
+ const GridView* gridDataView)
+{
+ assert(this == gridLeft || this == gridRight || this == gridMiddle);
+
+ //these grids will scroll together
+ m_gridLeft = gridLeft;
+ m_gridRight = gridRight;
+ m_gridMiddle = gridMiddle;
+
+ //set underlying grid data
+ setGridDataTable(gridDataView);
+
+ //enhance grid functionality; identify leading grid by keyboard input or scroll action
+ Connect(wxEVT_KEY_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_TOP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_BOTTOM, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_LINEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_LINEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_PAGEUP, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_PAGEDOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_SCROLLWIN_THUMBRELEASE, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ Connect(wxEVT_GRID_LABEL_LEFT_CLICK, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
+ GetGridWindow()->Connect(wxEVT_RIGHT_DOWN, wxEventHandler(CustomGrid::onGridAccess), NULL, this);
GetGridWindow()->Connect(wxEVT_ENTER_WINDOW, wxEventHandler(CustomGrid::adjustGridHeights), NULL, this);
}
@@ -507,58 +549,22 @@ bool CustomGrid::isLeadGrid() const
}
-inline
-bool gridsShouldBeCleared(const wxEvent& event)
+void CustomGrid::RefreshCell(int row, int col)
{
- try
- {
- const wxMouseEvent& mouseEvent = dynamic_cast<const wxMouseEvent&> (event);
-
- if (mouseEvent.ControlDown() || mouseEvent.ShiftDown())
- return false;
-
- if (mouseEvent.ButtonDown(wxMOUSE_BTN_LEFT))
- return true;
+ wxRect rectScrolled(CellToRect(row, col));
- return false;
- }
- catch (std::bad_cast&) {}
-
- try
- {
- const wxKeyEvent& keyEvent = dynamic_cast<const wxKeyEvent&> (event);
+ CalcScrolledPosition(rectScrolled.x, rectScrolled.y, &rectScrolled.x, &rectScrolled.y);
- if (keyEvent.ControlDown() || keyEvent.ShiftDown())
- return false;
+ GetGridWindow()->RefreshRect(rectScrolled); //note: CellToRect() and YToRow work on m_gridWindow NOT on the whole grid!
+}
- switch (keyEvent.GetKeyCode())
- {
- case WXK_SPACE:
- case WXK_TAB:
- case WXK_RETURN:
- case WXK_ESCAPE:
- case WXK_NUMPAD_ENTER:
- case WXK_LEFT:
- case WXK_UP:
- case WXK_RIGHT:
- case WXK_DOWN:
- case WXK_PAGEUP:
- case WXK_PAGEDOWN:
- case WXK_NUMPAD_PAGEUP:
- case WXK_NUMPAD_PAGEDOWN:
- case WXK_HOME:
- case WXK_END:
- case WXK_NUMPAD_HOME:
- case WXK_NUMPAD_END:
- return true;
- default:
- return false;
- }
- }
- catch (std::bad_cast&) {}
+void CustomGrid::DoPrepareDC(wxDC& dc)
+{
+ wxScrollHelper::DoPrepareDC(dc);
- return false;
+ if (isLeadGrid()) //avoid back coupling
+ alignOtherGrids(m_gridLeft, m_gridMiddle, m_gridRight); //scroll other grids
}
@@ -681,29 +687,84 @@ void additionalGridCommands(wxEvent& event, wxGrid* grid)
}
+inline
+bool gridsShouldBeCleared(const wxEvent& event)
+{
+ try
+ {
+ const wxMouseEvent& mouseEvent = dynamic_cast<const wxMouseEvent&> (event);
+
+ if (mouseEvent.ControlDown() || mouseEvent.ShiftDown())
+ return false;
+
+ if (mouseEvent.ButtonDown(wxMOUSE_BTN_LEFT))
+ return true;
+
+ return false;
+ }
+ catch (std::bad_cast&) {}
+
+ try
+ {
+ const wxKeyEvent& keyEvent = dynamic_cast<const wxKeyEvent&> (event);
+
+ if (keyEvent.ControlDown() || keyEvent.ShiftDown())
+ return false;
+
+ switch (keyEvent.GetKeyCode())
+ {
+ case WXK_SPACE:
+ case WXK_TAB:
+ case WXK_RETURN:
+ case WXK_ESCAPE:
+ case WXK_NUMPAD_ENTER:
+ case WXK_LEFT:
+ case WXK_UP:
+ case WXK_RIGHT:
+ case WXK_DOWN:
+ case WXK_PAGEUP:
+ case WXK_PAGEDOWN:
+ case WXK_NUMPAD_PAGEUP:
+ case WXK_NUMPAD_PAGEDOWN:
+ case WXK_HOME:
+ case WXK_END:
+ case WXK_NUMPAD_HOME:
+ case WXK_NUMPAD_END:
+ return true;
+ }
+
+ return false;
+ }
+ catch (std::bad_cast&) {}
+
+ return false;
+}
+
+
void CustomGrid::onGridAccess(wxEvent& event)
{
if (!isLeading)
{
- isLeading = true;
-
//notify other grids of new user focus
- if (m_gridLeft != this)
- m_gridLeft->isLeading = false;
- if (m_gridMiddle != this)
- m_gridMiddle->isLeading = false;
- if (m_gridRight != this)
- m_gridRight->isLeading = false;
+ m_gridLeft->isLeading = m_gridLeft == this;
+ m_gridMiddle->isLeading = m_gridMiddle == this;
+ m_gridRight->isLeading = m_gridRight == this;
wxGrid::SetFocus();
}
+ //clear grids
if (gridsShouldBeCleared(event))
{
m_gridLeft->ClearSelection();
+ m_gridMiddle->ClearSelection();
m_gridRight->ClearSelection();
}
+ //update row labels NOW (needed when scrolling if buttons keep being pressed)
+ m_gridLeft->GetGridRowLabelWindow()->Update();
+ m_gridRight->GetGridRowLabelWindow()->Update();
+
//support for additional short-cuts
additionalGridCommands(event, this); //event.Skip is handled here!
}
@@ -712,48 +773,46 @@ void CustomGrid::onGridAccess(wxEvent& event)
//workaround: ensure that all grids are properly aligned: add some extra window space to grids that have no horizontal scrollbar
void CustomGrid::adjustGridHeights(wxEvent& event)
{
- if (m_gridLeft && m_gridRight && m_gridMiddle)
- {
- int y1 = 0;
- int y2 = 0;
- int y3 = 0;
- int dummy = 0;
+ //m_gridLeft, m_gridRight, m_gridMiddle not NULL because called after initSettings()
- m_gridLeft->GetViewStart(&dummy, &y1);
- m_gridRight->GetViewStart(&dummy, &y2);
- m_gridMiddle->GetViewStart(&dummy, &y3);
+ int y1 = 0;
+ int y2 = 0;
+ int y3 = 0;
+ int dummy = 0;
- if (y1 != y2 || y2 != y3)
- {
- int yMax = std::max(y1, std::max(y2, y3));
-
- if (m_gridLeft->isLeadGrid()) //do not handle case (y1 == yMax) here!!! Avoid back coupling!
- m_gridLeft->SetMargins(0, 0);
- else if (y1 < yMax)
- m_gridLeft->SetMargins(0, 30);
-
- if (m_gridRight->isLeadGrid())
- m_gridRight->SetMargins(0, 0);
- else if (y2 < yMax)
- m_gridRight->SetMargins(0, 30);
-
- if (m_gridMiddle->isLeadGrid())
- m_gridMiddle->SetMargins(0, 0);
- else if (y3 < yMax)
- m_gridMiddle->SetMargins(0, 30);
-
- m_gridLeft->ForceRefresh();
- m_gridRight->ForceRefresh();
- m_gridMiddle->ForceRefresh();
- }
+ m_gridLeft->GetViewStart(&dummy, &y1);
+ m_gridRight->GetViewStart(&dummy, &y2);
+ m_gridMiddle->GetViewStart(&dummy, &y3);
+
+ if (y1 != y2 || y2 != y3)
+ {
+ int yMax = std::max(y1, std::max(y2, y3));
+
+ if (m_gridLeft->isLeadGrid()) //do not handle case (y1 == yMax) here!!! Avoid back coupling!
+ m_gridLeft->SetMargins(0, 0);
+ else if (y1 < yMax)
+ m_gridLeft->SetMargins(0, 30);
+
+ if (m_gridRight->isLeadGrid())
+ m_gridRight->SetMargins(0, 0);
+ else if (y2 < yMax)
+ m_gridRight->SetMargins(0, 30);
+
+ if (m_gridMiddle->isLeadGrid())
+ m_gridMiddle->SetMargins(0, 0);
+ else if (y3 < yMax)
+ m_gridMiddle->SetMargins(0, 30);
+
+ m_gridLeft->ForceRefresh();
+ m_gridRight->ForceRefresh();
+ m_gridMiddle->ForceRefresh();
}
}
-void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap)
+void CustomGrid::setSortMarker(SortMarker marker)
{
- currentSortColumn = sortColumn;
- sortMarker = bitmap;
+ m_marker = marker;
}
@@ -761,8 +820,13 @@ void CustomGrid::DrawColLabel(wxDC& dc, int col)
{
wxGrid::DrawColLabel(dc, col);
- if (col == currentSortColumn)
- dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+ if (col == m_marker.first)
+ {
+ if (m_marker.second == ASCENDING)
+ dc.DrawBitmap(*GlobalResources::getInstance().bitmapSmallUp, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+ else
+ dc.DrawBitmap(*GlobalResources::getInstance().bitmapSmallDown, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border
+ }
}
@@ -821,118 +885,119 @@ std::set<int> CustomGrid::getAllSelectedRows() const
//############################################################################################
//CustomGrid specializations
-template <bool leftSide, bool showFileIcons>
+#ifdef FFS_WIN
+template <bool showFileIcons>
class GridCellRenderer : public wxGridCellStringRenderer
{
public:
- GridCellRenderer(CustomGridTableRim* gridDataTable) : m_gridDataTable(gridDataTable) {};
+ GridCellRenderer(CustomGridRim::LoadSuccess& loadIconSuccess, const CustomGridTableRim* gridDataTable) :
+ m_loadIconSuccess(loadIconSuccess),
+ m_gridDataTable(gridDataTable) {}
virtual void Draw(wxGrid& grid,
wxGridCellAttr& attr,
wxDC& dc,
- const wxRect& rect,
+ const wxRect& rect, //unscrolled rect
int row, int col,
bool isSelected)
{
-#ifdef FFS_WIN
//############## show windows explorer file icons ######################
if (showFileIcons) //evaluate at compile time
{
- const int ICON_SIZE = 16; //size in pixel
-
if ( m_gridDataTable->getTypeAtPos(col) == xmlAccess::FILENAME &&
- rect.GetWidth() >= ICON_SIZE)
+ rect.GetWidth() >= IconBuffer::ICON_SIZE)
{
//retrieve grid data
- const FileCompareLine* rowData = m_gridDataTable->getRawData(row);
- if (rowData) //valid row
+ const Zstring fileName = m_gridDataTable->getFileName(row);
+ if (!fileName.empty())
{
- const DefaultChar* filename;
- if (leftSide) //evaluate at compile time
- filename = rowData->fileDescrLeft.fullName.c_str();
- else
- filename = rowData->fileDescrRight.fullName.c_str();
-
- if (*filename != DefaultChar(0)) //test if filename is empty
+ // Partitioning:
+ // _____________________
+ // | 2 pix | icon | rest |
+ // ---------------------
+
+ //clear area where icon will be placed
+ wxRect rectShrinked(rect);
+ rectShrinked.SetWidth(IconBuffer::ICON_SIZE + 2); //add 2 pixel border
+ wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+
+ //try to draw icon
+ wxIcon icon;
+ const bool iconLoaded = IconBuffer::getInstance().requestIcon(fileName, &icon); //returns false if icon is not in buffer
+ if (iconLoaded)
+ dc.DrawIcon(icon, rectShrinked.GetX() + 2, rectShrinked.GetY());
+
+ //-----------------------------------------------------------------------------------------------
+ //only mark as successful if icon was drawn fully!
+ //(attention: when scrolling, rows get partially updated, which can result in the upper half being blank!)
+
+ //rect where icon was placed
+ wxRect iconRect(rect); //unscrolled
+ iconRect.x += 2;
+ iconRect.SetWidth(IconBuffer::ICON_SIZE);
+
+ //convert to scrolled coordinates
+ grid.CalcScrolledPosition(iconRect.x, iconRect.y, &iconRect.x, &iconRect.y);
+
+ bool iconDrawnFully = false;
+ wxRegionIterator regionsInv(grid.GetGridWindow()->GetUpdateRegion());
+ while (regionsInv)
{
- // Get the file icon.
- SHFILEINFO fileInfo;
- fileInfo.hIcon = 0; //initialize hIcon
-
- if (SHGetFileInfo(filename, //NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup!
- 0,
- &fileInfo,
- sizeof(fileInfo),
- SHGFI_ICON | SHGFI_SMALLICON))
+ if (regionsInv.GetRect().Contains(iconRect))
{
- //clear area where icon will be placed
- wxRect rectShrinked(rect);
- rectShrinked.SetWidth(ICON_SIZE + 2); //add 2 pixel border
- wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
-
- //draw icon
- if (fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!!
- { //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080
- wxIcon icon;
- icon.SetHICON(static_cast<WXHICON>(fileInfo.hIcon));
- icon.SetSize(ICON_SIZE, ICON_SIZE);
-
- dc.DrawIcon(icon, rectShrinked.GetX() + 2, rectShrinked.GetY());
-
- if (!DestroyIcon(fileInfo.hIcon))
- throw RuntimeException(wxString(wxT("Error deallocating Icon handle!\n\n")) + FreeFileSync::getLastErrorFormatted());
- }
-
- //draw rest
- rectShrinked.SetWidth(rect.GetWidth() - ICON_SIZE - 2);
- rectShrinked.SetX(rect.GetX() + ICON_SIZE + 2);
- wxGridCellStringRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
- return;
+ iconDrawnFully = true;
+ break;
}
+ ++regionsInv;
}
+ //-----------------------------------------------------------------------------------------------
+
+
+ //save status of last icon load -> used for async. icon loading
+ m_loadIconSuccess[row] = iconLoaded && iconDrawnFully;
+
+ //draw rest
+ wxRect rest(rect); //unscrolled
+ rest.x += IconBuffer::ICON_SIZE + 2;
+ rest.width -= IconBuffer::ICON_SIZE + 2;
+
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rest, row, col, isSelected);
+ return;
}
}
}
//default
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
-
-#elif defined FFS_LINUX
- wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
-#endif
}
private:
+ CustomGridRim::LoadSuccess& m_loadIconSuccess;
const CustomGridTableRim* const m_gridDataTable;
};
+#endif
//----------------------------------------------------------------------------------------
-void CustomGridRim::initSettings(const bool showFileIcons,
- CustomGrid* gridLeft,
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- const GridView* gridDataView)
-{
- //these grids will scroll together
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
-
- //set underlying grid data
- assert(gridDataTable);
- gridDataTable->setGridDataTable(gridDataView);
-
- enableFileIcons(showFileIcons);
-}
+CustomGridRim::CustomGridRim(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxString& name) :
+ CustomGrid(parent, id, pos, size, style, name)
+#ifdef FFS_WIN
+ , fileIconsAreEnabled(false)
+#endif
+{}
void CustomGridRim::updateGridSizes()
{
- assert(gridDataTable);
- gridDataTable->updateGridSizes();
+ assert(getGridDataTable());
+ getGridDataTable()->updateGridSizes();
}
@@ -1046,8 +1111,8 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr)
newPositions.push_back(columnSettings[i].type);
//set column positions
- assert(gridDataTable);
- gridDataTable->setupColumns(newPositions);
+ assert(getGridDataTable());
+ getGridDataTable()->setupColumns(newPositions);
//set column width (set them after setupColumns!)
for (unsigned int i = 0; i < newPositions.size(); ++i)
@@ -1071,8 +1136,8 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr)
xmlAccess::ColumnTypes CustomGridRim::getTypeAtPos(unsigned pos) const
{
- assert(gridDataTable);
- return gridDataTable->getTypeAtPos(pos);
+ assert(getGridDataTable());
+ return getGridDataTable()->getTypeAtPos(pos);
}
@@ -1097,6 +1162,132 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType)
return wxEmptyString; //dummy
}
+
+CustomGridTableRim* CustomGridRim::getGridDataTable()
+{ //let the non-const call the const version: see Meyers Effective C++
+ return const_cast<CustomGridTableRim*>(static_cast<const CustomGridRim*>(this)->getGridDataTable());
+}
+
+
+#ifdef FFS_WIN
+void CustomGridRim::enableFileIcons(const bool value)
+{
+ fileIconsAreEnabled = value;
+
+ if (value)
+ SetDefaultRenderer(new GridCellRenderer<true>(loadIconSuccess, getGridDataTable())); //SetDefaultRenderer takes ownership!
+ else
+ SetDefaultRenderer(new GridCellRenderer<false>(loadIconSuccess, getGridDataTable()));
+
+ Refresh();
+}
+
+
+CustomGridRim::VisibleRowRange CustomGridRim::getVisibleRows()
+{
+ int dummy = -1;
+ int height = -1;
+ GetGridWindow()->GetClientSize(&dummy, &height);
+
+ if (height >= 0)
+ {
+ int topRowY = -1;
+ CalcUnscrolledPosition(0, 0, &dummy, &topRowY);
+
+ if (topRowY >= 0)
+ {
+ const int topRow = YToRow(topRowY);
+ const int rowCount = static_cast<int>(ceil(height / static_cast<double>(GetDefaultRowSize()))); // = height / rowHeight rounded up
+ const int bottomRow = topRow + rowCount - 1;
+
+ return VisibleRowRange(topRow, bottomRow); //"top" means here top of the screen: => smaller value
+ }
+ }
+
+ return VisibleRowRange(0, 0);
+}
+
+
+void CustomGridRim::getIconsToBeLoaded(std::vector<Zstring>& newLoad) //loads all (not yet) drawn icons
+{
+ newLoad.clear();
+
+ if (fileIconsAreEnabled) //don't check too often! give worker thread some time to fetch data
+ {
+ const CustomGridTableRim* gridDataTable = getGridDataTable();
+ const VisibleRowRange rowsOnScreen = getVisibleRows();
+ const int totalCols = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberCols();
+ const int totalRows = const_cast<CustomGridTableRim*>(gridDataTable)->GetNumberRows();
+
+ //loop over all visible rows
+ const int firstRow = rowsOnScreen.first;
+ const int lastRow = std::min(int(rowsOnScreen.second), totalRows - 1);
+ const int rowNo = lastRow - firstRow + 1;
+
+ for (int i = 0; i < rowNo; ++i)
+ {
+ //alternate when adding rows: first, last, first + 1, last - 1 ...
+ const int currentRow = i % 2 == 0 ?
+ firstRow + i / 2 :
+ lastRow - (i - 1) / 2;
+
+ LoadSuccess::const_iterator j = loadIconSuccess.find(currentRow);
+ if (j != loadIconSuccess.end() && j->second == false) //find failed attempts to load icon
+ {
+ const Zstring fileName = gridDataTable->getFileName(currentRow);
+ if (!fileName.empty())
+ {
+ //test if they are already loaded in buffer:
+ if (FreeFileSync::IconBuffer::getInstance().requestIcon(fileName))
+ {
+ //exists in buffer: refresh Row
+ for (int k = 0; k < totalCols; ++k)
+ if (gridDataTable->getTypeAtPos(k) == xmlAccess::FILENAME)
+ {
+ RefreshCell(currentRow, k);
+ break;
+ }
+ }
+ else //not yet in buffer: mark for async. loading
+ {
+ newLoad.push_back(fileName);
+ }
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+
+
+//update file icons periodically: use SINGLE instance to coordinate left and right grid at once
+IconUpdater::IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid) :
+ m_leftGrid(leftGrid),
+ m_rightGrid(rightGrid),
+ m_timer(new wxTimer) //connect timer event for async. icon loading
+{
+ m_timer->Connect(wxEVT_TIMER, wxEventHandler(IconUpdater::loadIconsAsynchronously), NULL, this);
+ m_timer->Start(50); //timer interval
+}
+
+
+void IconUpdater::loadIconsAsynchronously(wxEvent& event) //loads all (not yet) drawn icons
+{
+ std::vector<Zstring> iconsLeft;
+ m_leftGrid->getIconsToBeLoaded(iconsLeft);
+
+ std::vector<Zstring> newLoad;
+ m_rightGrid->getIconsToBeLoaded(newLoad);
+
+ globalFunctions::mergeVectors(iconsLeft, newLoad);
+
+ FreeFileSync::IconBuffer::getInstance().setWorkload(newLoad); //attention: newLoad is invalidated after this call!!!
+
+ //event.Skip();
+}
+#endif
+
//----------------------------------------------------------------------------------------
@@ -1106,7 +1297,8 @@ CustomGridLeft::CustomGridLeft(wxWindow *parent,
const wxSize& size,
long style,
const wxString& name) :
- CustomGridRim(parent, id, pos, size, style, name) {}
+ CustomGridRim(parent, id, pos, size, style, name),
+ gridDataTable(NULL) {}
bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
@@ -1120,29 +1312,28 @@ bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectio
}
-void CustomGridLeft::enableFileIcons(const bool value)
+void CustomGridLeft::setGridDataTable(const GridView* gridDataView)
{
- if (value)
- SetDefaultRenderer(new GridCellRenderer<true, true>(gridDataTable)); //SetDefaultRenderer takes ownership!
- else
- SetDefaultRenderer(new GridCellRenderer<true, false>(gridDataTable));
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridDataView);
+}
- Refresh();
+
+const CustomGridTableRim* CustomGridLeft::getGridDataTable() const
+{
+ return gridDataTable;
}
//this method is called when grid view changes: useful for parallel updating of multiple grids
-void CustomGridLeft::DoPrepareDC(wxDC& dc)
+void CustomGridLeft::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight)
{
- wxScrollHelper::DoPrepareDC(dc);
-
- int x, y = 0;
- if (isLeadGrid()) //avoid back coupling
- {
- GetViewStart(&x, &y);
- m_gridMiddle->Scroll(-1, y); //scroll in y-direction only
- m_gridRight->Scroll(x, y);
- }
+ int x = 0;
+ int y = 0;
+ GetViewStart(&x, &y);
+ gridMiddle->Scroll(-1, y); //scroll in y-direction only
+ gridRight->Scroll(x, y);
}
@@ -1153,7 +1344,8 @@ CustomGridRight::CustomGridRight(wxWindow *parent,
const wxSize& size,
long style,
const wxString& name) :
- CustomGridRim(parent, id, pos, size, style, name) {}
+ CustomGridRim(parent, id, pos, size, style, name),
+ gridDataTable(NULL) {}
bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
@@ -1165,33 +1357,49 @@ bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelecti
}
-void CustomGridRight::enableFileIcons(const bool value)
+void CustomGridRight::setGridDataTable(const GridView* gridDataView)
{
- if (value)
- SetDefaultRenderer(new GridCellRenderer<false, true>(gridDataTable)); //SetDefaultRenderer takes ownership!
- else
- SetDefaultRenderer(new GridCellRenderer<false, false>(gridDataTable));
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridDataView);
+}
- Refresh();
+
+const CustomGridTableRim* CustomGridRight::getGridDataTable() const
+{
+ return gridDataTable;
}
//this method is called when grid view changes: useful for parallel updating of multiple grids
-void CustomGridRight::DoPrepareDC(wxDC& dc)
+void CustomGridRight::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight)
{
- wxScrollHelper::DoPrepareDC(dc);
-
- int x, y = 0;
- if (isLeadGrid()) //avoid back coupling
- {
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(x, y);
- m_gridMiddle->Scroll(-1, y);
- }
+ int x = 0;
+ int y = 0;
+ GetViewStart(&x, &y);
+ gridLeft->Scroll(x, y);
+ gridMiddle->Scroll(-1, y);
}
//----------------------------------------------------------------------------------------
+class GridCellRendererMiddle : public wxGridCellStringRenderer
+{
+public:
+ GridCellRendererMiddle(const CustomGridMiddle* middleGrid) : m_gridMiddle(middleGrid) {};
+
+ virtual void Draw(wxGrid& grid,
+ wxGridCellAttr& attr,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected);
+
+private:
+ const CustomGridMiddle* const m_gridMiddle;
+};
+
+
//define new event types
const wxEventType FFS_CHECK_ROWS_EVENT = wxNewEventType(); //attention! do NOT place in header to keep (generated) id unique!
const wxEventType FFS_SYNC_DIRECTION_EVENT = wxNewEventType();
@@ -1220,13 +1428,46 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent,
{
//connect events for dynamic selection of sync direction
GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridMiddle::OnMouseMovement), NULL, this);
-
GetGridWindow()->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(CustomGridMiddle::OnLeaveWindow), NULL, this);
GetGridWindow()->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseUp), NULL, this);
GetGridWindow()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(CustomGridMiddle::OnLeftMouseDown), NULL, this);
}
+bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+{
+ gridDataTable = new CustomGridTableMiddle;
+ SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
+
+ //display checkboxes (representing bool values) if row is enabled for synchronization
+ SetDefaultRenderer(new GridCellRendererMiddle(this)); //SetDefaultRenderer takes ownership!
+
+ return true;
+}
+
+
+#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method
+void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh)
+{
+ wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh);
+}
+#endif
+
+
+void CustomGridMiddle::setGridDataTable(const GridView* gridDataView) //called once on startup
+{
+ //set underlying grid data
+ assert(gridDataTable);
+ gridDataTable->setGridDataTable(gridDataView);
+
+#ifdef FFS_LINUX //get rid of scrollbars; Linux: change policy for GtkScrolledWindow
+ GtkWidget* gridWidget = wxWindow::m_widget;
+ GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget);
+ gtk_scrolled_window_set_policy(scrolledWindow, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+#endif
+}
+
+
void CustomGridMiddle::OnMouseMovement(wxMouseEvent& event)
{
const int highlightedRowOld = highlightedRow;
@@ -1234,25 +1475,17 @@ void CustomGridMiddle::OnMouseMovement(wxMouseEvent& event)
if (selectionRowBegin == -1) //change highlightning only if currently not dragging mouse
{
highlightedRow = mousePosToRow(event.GetPosition(), &highlightedPos);
- if (highlightedRow >= 0) RefreshRow(highlightedRow);
+ if (highlightedRow >= 0)
+ RefreshCell(highlightedRow, 0);
if ( highlightedRowOld >= 0 &&
highlightedRow != highlightedRowOld)
- RefreshRow(highlightedRowOld);
+ RefreshCell(highlightedRowOld, 0);
}
event.Skip();
}
-void CustomGridMiddle::RefreshRow(int row)
-{
- wxRect rectScrolled(CellToRect(row, 0));
- CalcScrolledPosition(rectScrolled.x, rectScrolled.y, &rectScrolled.x, &rectScrolled.y);
-
- GetGridWindow()->Refresh(false, &rectScrolled); //note: CellToRect() and YToRow work on m_gridWindow NOT on the whole grid!
-}
-
-
void CustomGridMiddle::OnLeaveWindow(wxMouseEvent& event)
{
highlightedRow = -1;
@@ -1357,36 +1590,6 @@ int CustomGridMiddle::mousePosToRow(const wxPoint pos, BlockPosition* block)
}
-void CustomGridMiddle::initSettings(CustomGrid* gridLeft,
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- const FreeFileSync::GridView* gridDataView)
-{
- //these grids will scroll together
- m_gridLeft = gridLeft;
- m_gridRight = gridRight;
- m_gridMiddle = gridMiddle;
-
- //set underlying grid data
- assert(gridDataTable);
- gridDataTable->setGridDataTable(gridDataView);
-
-#ifdef FFS_LINUX //get rid of scrollbars; Linux: change policy for GtkScrolledWindow
- GtkWidget* gridWidget = wxWindow::m_widget;
- GtkScrolledWindow* scrolledWindow = GTK_SCROLLED_WINDOW(gridWidget);
- gtk_scrolled_window_set_policy(scrolledWindow, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
-#endif
-}
-
-
-#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method
-void CustomGridMiddle::SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh)
-{
- wxWindow::SetScrollbar(orientation, 0, 0, 0, refresh);
-}
-#endif
-
-
void CustomGridMiddle::enableSyncPreview(bool value)
{
assert(gridDataTable);
@@ -1427,152 +1630,128 @@ void CustomGridMiddle::updateGridSizes()
}
-class GridCellRendererMiddle : public wxGridCellStringRenderer
+void GridCellRendererMiddle::Draw(wxGrid& grid,
+ wxGridCellAttr& attr,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected)
{
-public:
- GridCellRendererMiddle(const CustomGridMiddle* middleGrid) : m_gridMiddle(middleGrid) {};
-
-
- virtual void Draw(wxGrid& grid,
- wxGridCellAttr& attr,
- wxDC& dc,
- const wxRect& rect,
- int row, int col,
- bool isSelected)
+ //retrieve grid data
+ const FileCompareLine* const rowData = m_gridMiddle->gridDataTable->getRawData(row);
+ if (rowData != NULL) //if valid row...
{
- //retrieve grid data
- const FileCompareLine* const rowData = m_gridMiddle->gridDataTable->getRawData(row);
- if (rowData) //no valid row
+ if (rect.GetWidth() > CHECK_BOX_WIDTH)
{
- if (rect.GetWidth() > CHECK_BOX_WIDTH)
- {
- wxRect rectShrinked(rect);
+ wxRect rectShrinked(rect);
- //clean first block of rect that will receive image of checkbox
- rectShrinked.SetWidth(CHECK_BOX_WIDTH);
- wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+ //clean first block of rect that will receive image of checkbox
+ rectShrinked.SetWidth(CHECK_BOX_WIDTH);
+ wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
- //print image into first block
- rectShrinked.SetX(rect.GetX() + 1);
- bool selected = rowData->selectedForSynchronization;
+ //print image into first block
+ rectShrinked.SetX(rect.GetX() + 1);
+ bool selected = rowData->selectedForSynchronization;
- //HIGHLIGHTNING:
- if ( row == m_gridMiddle->highlightedRow &&
- m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX)
- selected = !selected;
-
- if (selected)
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
- else
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
-
- //clean remaining block of rect that will receive image of checkbox/directions
- rectShrinked.SetWidth(rect.GetWidth() - CHECK_BOX_WIDTH);
- rectShrinked.SetX(rect.GetX() + CHECK_BOX_WIDTH);
- wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
-
- //print remaining block
- if (m_gridMiddle->gridDataTable->syncPreviewIsActive()) //synchronization preview
- {
- //print sync direction into second block
+ //HIGHLIGHTNING:
+ if ( row == m_gridMiddle->highlightedRow &&
+ m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX)
+ selected = !selected;
- //HIGHLIGHTNING:
- if (row == m_gridMiddle->highlightedRow && m_gridMiddle->highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX)
- switch (m_gridMiddle->highlightedPos)
- {
- case CustomGridMiddle::BLOCKPOS_CHECK_BOX:
- break;
- case CustomGridMiddle::BLOCKPOS_LEFT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirLeftSmall, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
- break;
- case CustomGridMiddle::BLOCKPOS_MIDDLE:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirNoneSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case CustomGridMiddle::BLOCKPOS_RIGHT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirRightSmall, rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
- break;
- }
- else //default
- switch (rowData->direction)
- {
- case SYNC_DIR_LEFT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirLeftSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case SYNC_DIR_RIGHT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirRightSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case SYNC_DIR_NONE:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapSyncDirNoneSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case SYNC_UNRESOLVED_CONFLICT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapConflictSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- }
- }
- else //comparison results view
- {
- switch (rowData->cmpResult)
+ if (selected)
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ else
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+
+ //clean remaining block of rect that will receive image of checkbox/directions
+ rectShrinked.SetWidth(rect.GetWidth() - CHECK_BOX_WIDTH);
+ rectShrinked.SetX(rect.GetX() + CHECK_BOX_WIDTH);
+ wxGridCellRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected);
+
+ //print remaining block
+ if (m_gridMiddle->gridDataTable->syncPreviewIsActive()) //synchronization preview
+ {
+ //print sync direction into second block
+
+ //HIGHLIGHTNING:
+ if (row == m_gridMiddle->highlightedRow && m_gridMiddle->highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX)
+ switch (m_gridMiddle->highlightedPos)
{
- case FILE_LEFT_SIDE_ONLY:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapLeftOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case FILE_RIGHT_SIDE_ONLY:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapRightOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case FILE_LEFT_NEWER:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapLeftNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ case CustomGridMiddle::BLOCKPOS_CHECK_BOX:
break;
- case FILE_RIGHT_NEWER:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapRightNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ case CustomGridMiddle::BLOCKPOS_LEFT:
+ dc.DrawLabel(wxEmptyString, getSyncOpImage(rowData->cmpResult, true, SYNC_DIR_LEFT), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
break;
- case FILE_DIFFERENT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapDifferentSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ case CustomGridMiddle::BLOCKPOS_MIDDLE:
+ dc.DrawLabel(wxEmptyString, getSyncOpImage(rowData->cmpResult, true, SYNC_DIR_NONE), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
break;
- case FILE_EQUAL:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapEqualSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- break;
- case FILE_CONFLICT:
- dc.DrawLabel(wxEmptyString, *globalResource.bitmapConflictSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ case CustomGridMiddle::BLOCKPOS_RIGHT:
+ dc.DrawLabel(wxEmptyString, getSyncOpImage(rowData->cmpResult, true, SYNC_DIR_RIGHT), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL);
break;
}
+ else //default
+ {
+ const wxBitmap& syncOpIcon = getSyncOpImage(rowData->cmpResult, rowData->selectedForSynchronization, rowData->direction);
+ dc.DrawLabel(wxEmptyString, syncOpIcon, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ }
+ }
+ else //comparison results view
+ {
+ switch (rowData->cmpResult)
+ {
+ case FILE_LEFT_SIDE_ONLY:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapLeftOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_RIGHT_SIDE_ONLY:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapRightOnlySmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_LEFT_NEWER:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapLeftNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_RIGHT_NEWER:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapRightNewerSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_DIFFERENT:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapDifferentSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_EQUAL:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapEqualSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
+ case FILE_CONFLICT:
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapConflictSmall, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ break;
}
-
- return;
}
- }
- //fallback
- wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+ return;
+ }
}
-private:
- const CustomGridMiddle* const m_gridMiddle;
-};
+ //fallback
+ wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
+}
-bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode)
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+void CustomGridMiddle::alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight)
{
- gridDataTable = new CustomGridTableMiddle;
- SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor
-
- //display checkboxes (representing bool values) if row is enabled for synchronization
- SetDefaultRenderer(new GridCellRendererMiddle(this)); //SetDefaultRenderer takes ownership!
-
- return true;
+ int x = 0;
+ int y = 0;
+ GetViewStart(&x, &y);
+ gridLeft->Scroll(-1, y);
+ gridRight->Scroll(-1, y);
}
-//this method is called when grid view changes: useful for parallel updating of multiple grids
-void CustomGridMiddle::DoPrepareDC(wxDC& dc)
+void CustomGridMiddle::DrawColLabel(wxDC& dc, int col)
{
- wxScrollHelper::DoPrepareDC(dc);
+ CustomGrid::DrawColLabel(dc, col);
- int x, y = 0;
- if (isLeadGrid()) //avoid back coupling
- {
- GetViewStart(&x, &y);
- m_gridLeft->Scroll(-1, y);
- m_gridRight->Scroll(-1, y);
- }
+ const wxRect rect(GetColLeft(col), 0, GetColWidth(col), GetColLabelSize());
+
+ if (gridDataTable->syncPreviewIsActive())
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapSyncViewSmall, rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
+ else
+ dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCmpViewSmall, rect, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
}
diff --git a/library/CustomGrid.h b/library/CustomGrid.h
index 89ec39d0..98e86e11 100644
--- a/library/CustomGrid.h
+++ b/library/CustomGrid.h
@@ -5,12 +5,19 @@
#include <wx/grid.h>
#include "../structures.h"
#include "processXml.h"
+#include <map>
+#include <memory>
-
-class CustomGridTable;
class CustomGridTableRim;
+class CustomGridTableLeft;
+class CustomGridTableRight;
class CustomGridTableMiddle;
class GridCellRendererMiddle;
+class wxTimer;
+class CustomGridRim;
+class CustomGridLeft;
+class CustomGridMiddle;
+class CustomGridRight;
namespace FreeFileSync
{
@@ -43,50 +50,89 @@ public:
virtual ~CustomGrid() {}
- virtual void DrawColLabel(wxDC& dc, int col);
+ void initSettings(CustomGridLeft* gridLeft,
+ CustomGridMiddle* gridMiddle,
+ CustomGridRight* gridRight,
+ const FreeFileSync::GridView* gridDataView);
std::set<int> getAllSelectedRows() const;
//set sort direction indicator on UI
- void setSortMarker(const int sortColumn, const wxBitmap* bitmap = &wxNullBitmap);
+ typedef int SortColumn;
+
+ enum SortDirection
+ {
+ ASCENDING,
+ DESCENDING,
+ };
+
+ typedef std::pair<SortColumn, SortDirection> SortMarker;
+ void setSortMarker(SortMarker marker);
bool isLeadGrid() const;
protected:
- CustomGrid* m_gridLeft;
- CustomGrid* m_gridMiddle;
- CustomGrid* m_gridRight;
+ void RefreshCell(int row, int col);
+
+ virtual void DrawColLabel(wxDC& dc, int col);
private:
+ virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView) = 0;
+
+//this method is called when grid view changes: useful for parallel updating of multiple grids
+ virtual void DoPrepareDC(wxDC& dc);
+
+ virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight) = 0;
+
void onGridAccess(wxEvent& event);
void adjustGridHeights(wxEvent& event);
+ CustomGrid* m_gridLeft;
+ CustomGrid* m_gridMiddle;
+ CustomGrid* m_gridRight;
+
bool isLeading; //identify grid that has user focus
- int currentSortColumn;
- const wxBitmap* sortMarker;
+
+ SortMarker m_marker;
+};
+
+
+template <bool showFileIcons>
+class GridCellRenderer;
+
+
+//-----------------------------------------------------------
+#ifdef FFS_WIN
+class IconUpdater : public wxEvtHandler //update file icons periodically: use SINGLE instance to coordinate left and right grid at once
+{
+public:
+ IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid);
+
+private:
+ void loadIconsAsynchronously(wxEvent& event); //loads all (not yet) drawn icons
+
+ CustomGridRim* m_leftGrid;
+ CustomGridRim* m_rightGrid;
+
+ std::auto_ptr<wxTimer> m_timer; //user timer event to periodically update icons: better than idle event because also active when scrolling! :)
};
+#endif
//############## SPECIALIZATIONS ###################
class CustomGridRim : public CustomGrid
{
+ friend class IconUpdater;
+ template <bool showFileIcons>
+ friend class GridCellRenderer;
+
public:
CustomGridRim(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
- const wxString& name) :
- CustomGrid(parent, id, pos, size, style, name),
- gridDataTable(NULL) {}
-
- ~CustomGridRim() {}
-
- void initSettings(const bool showFileIcons, //workaround: though this coding better belongs into a constructor
- CustomGrid* gridLeft, //this is not possible due to source code generation (information not available at time of construction)
- CustomGrid* gridRight,
- CustomGrid* gridMiddle,
- const FreeFileSync::GridView* gridDataView);
+ const wxString& name);
//notify wxGrid that underlying table size has changed
void updateGridSizes();
@@ -99,12 +145,32 @@ public:
xmlAccess::ColumnTypes getTypeAtPos(unsigned pos) const;
static wxString getTypeName(xmlAccess::ColumnTypes colType);
- virtual void enableFileIcons(const bool value) = 0;
-
-protected:
- CustomGridTableRim* gridDataTable;
+#ifdef FFS_WIN
+ void enableFileIcons(const bool value);
+#endif
private:
+ CustomGridTableRim* getGridDataTable();
+ virtual const CustomGridTableRim* getGridDataTable() const = 0;
+
+#ifdef FFS_WIN
+ //asynchronous icon loading
+ void getIconsToBeLoaded(std::vector<Zstring>& newLoad); //loads all (not yet) drawn icons
+
+ typedef unsigned int FromRow;
+ typedef unsigned int ToRow;
+ typedef std::pair<FromRow, ToRow> VisibleRowRange;
+ VisibleRowRange getVisibleRows();
+
+
+ typedef unsigned int RowNumber;
+ typedef bool IconLoaded;
+ typedef std::map<RowNumber, IconLoaded> LoadSuccess;
+ LoadSuccess loadIconSuccess; //save status of last icon load when drawing on GUI
+
+ bool fileIconsAreEnabled;
+#endif
+
xmlAccess::ColumnAttributes columnSettings; //set visibility, position and width of columns
};
@@ -119,14 +185,16 @@ public:
long style = wxWANTS_CHARS,
const wxString& name = wxGridNameStr);
- ~CustomGridLeft() {}
-
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
- virtual void enableFileIcons(const bool value);
+private:
+ virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+ virtual const CustomGridTableRim* getGridDataTable() const;
//this method is called when grid view changes: useful for parallel updating of multiple grids
- virtual void DoPrepareDC(wxDC& dc);
+ virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight);
+
+ CustomGridTableLeft* gridDataTable;
};
@@ -140,14 +208,16 @@ public:
long style = wxWANTS_CHARS,
const wxString& name = wxGridNameStr);
- ~CustomGridRight() {}
-
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
- virtual void enableFileIcons(const bool value);
+private:
+ virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+ virtual const CustomGridTableRim* getGridDataTable() const;
//this method is called when grid view changes: useful for parallel updating of multiple grids
- virtual void DoPrepareDC(wxDC& dc);
+ virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight);
+
+ CustomGridTableRight* gridDataTable;
};
@@ -163,35 +233,31 @@ public:
long style = wxWANTS_CHARS,
const wxString& name = wxGridNameStr);
- ~CustomGridMiddle() {}
-
virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells);
- void initSettings(CustomGrid* gridLeft, //workaround: though this coding better belongs into a constructor
- CustomGrid* gridRight, //this is not possible due to source code generation (information not available at time of construction)
- CustomGrid* gridMiddle,
- const FreeFileSync::GridView* gridDataView);
-
void enableSyncPreview(bool value);
//notify wxGrid that underlying table size has changed
void updateGridSizes();
+private:
#ifdef FFS_WIN //get rid of scrollbars; Windows: overwrite virtual method
virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true);
#endif
+ virtual void setGridDataTable(const FreeFileSync::GridView* gridDataView);
+
//this method is called when grid view changes: useful for parallel updating of multiple grids
- virtual void DoPrepareDC(wxDC& dc);
+ virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight);
+
+ virtual void DrawColLabel(wxDC& dc, int col);
-private:
void OnMouseMovement(wxMouseEvent& event);
void OnLeaveWindow(wxMouseEvent& event);
void OnLeftMouseDown(wxMouseEvent& event);
void OnLeftMouseUp(wxMouseEvent& event);
//small helper methods
- void RefreshRow(int row);
enum BlockPosition //each cell can be divided into four blocks concerning mouse selections
{
BLOCKPOS_CHECK_BOX,
diff --git a/library/ShadowCopy/ShadowDll.vcproj b/library/ShadowCopy/ShadowDll.vcproj
new file mode 100644
index 00000000..637aad0c
--- /dev/null
+++ b/library/ShadowCopy/ShadowDll.vcproj
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="ShadowDll"
+ ProjectGUID="{70394AEF-5897-4911-AFA1-82EAF0581EFA}"
+ RootNamespace="ShadowDll"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="obj\$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="obj\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="Shadow.dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="obj\$(ConfigurationName)"
+ IntermediateDirectory="obj\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="Shadow.dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\dllmain.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAsManaged="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ CompileAsManaged="0"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\shadow.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\shadow.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\lib\vssapi.lib"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/library/ShadowCopy/dllmain.cpp b/library/ShadowCopy/dllmain.cpp
new file mode 100644
index 00000000..834b4f88
--- /dev/null
+++ b/library/ShadowCopy/dllmain.cpp
@@ -0,0 +1,22 @@
+// dllmain.cpp : Definiert den Einstiegspunkt fr die DLL-Anwendung.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
diff --git a/library/ShadowCopy/shadow.cpp b/library/ShadowCopy/shadow.cpp
new file mode 100644
index 00000000..e10a4eb8
--- /dev/null
+++ b/library/ShadowCopy/shadow.cpp
@@ -0,0 +1,178 @@
+#include "shadow.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+#include "inc/vss.h"
+#include "inc/vswriter.h"
+#include "inc/vsbackup.h"
+#include <algorithm>
+#include <string>
+#include <cstdio>
+#include <comdef.h>
+
+//typedef GUID VSS_ID;
+
+
+void writeString(const wchar_t* input, wchar_t* output, unsigned int outputBufferLen)
+{
+ const unsigned int newSize = min(wcslen(input) + 1, outputBufferLen); //including null-termination
+ memcpy(output, input, newSize * sizeof(wchar_t));
+}
+
+
+std::wstring numberToHexString(const long number)
+{
+ wchar_t result[100];
+ swprintf(result, 100, L"0x%08x", number);
+ return std::wstring(result);
+}
+
+
+void writeErrorMsg(const wchar_t* input, HRESULT hr, wchar_t* output, unsigned int outputBufferLen)
+{
+ std::wstring formattedMsg(input);
+ formattedMsg += L" (";
+ formattedMsg += numberToHexString(hr);
+ formattedMsg += L": ";
+ formattedMsg += _com_error(hr).ErrorMessage();
+ formattedMsg += L")";
+
+ writeString(formattedMsg.c_str(), output, outputBufferLen);
+}
+
+
+bool shadow::createShadowCopy(const wchar_t* volumeName,
+ wchar_t* shadowVolName,
+ unsigned int shadowBufferLen,
+ void** backupHandle,
+ wchar_t* errorMessage,
+ unsigned int errorBufferLen)
+{
+ //MessageBox(0, L"backup err", L"", 0); */
+ *backupHandle = NULL;
+ HRESULT hr = NULL;
+
+ IVssBackupComponents* pBackupComponents = NULL;
+ if (FAILED(hr = CreateVssBackupComponents(&pBackupComponents)))
+ {
+ if (hr == E_ACCESSDENIED)
+ writeErrorMsg(L"The caller does not have sufficient backup privileges or is not an administrator.", hr, errorMessage, errorBufferLen);
+ else
+ writeErrorMsg(L"Error calling \"CreateVssBackupComponents\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ if (FAILED(hr = pBackupComponents->InitializeForBackup()))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"InitializeForBackup\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ IVssAsync* pWriteMetaData = NULL;
+ if (FAILED(hr = pBackupComponents->GatherWriterMetadata( &pWriteMetaData )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"\"Shadow.dll\" might be incompatible with this Operating System!\n\
+ Error calling \"GatherWriterMetadata\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+ //wait for shadow copy writers to complete
+ hr = pWriteMetaData->Wait();
+ pWriteMetaData->Release();
+ if (FAILED(hr))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"ppWriteMetaData->Wait\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ VSS_ID snapshotSetId = {0};
+ if (FAILED(hr = pBackupComponents->StartSnapshotSet( &snapshotSetId )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"StartSnapshotSet\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ VSS_ID SnapShotId = {0};
+ if (FAILED(hr = pBackupComponents->AddToSnapshotSet(const_cast<wchar_t*>(volumeName), GUID_NULL, &SnapShotId)))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"AddToSnapshotSet\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ if (FAILED(hr = pBackupComponents->SetBackupState( false, false, VSS_BT_FULL )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"SetBackupState\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ IVssAsync* pPrepare = NULL;
+ if (FAILED(hr = pBackupComponents->PrepareForBackup( &pPrepare )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"PrepareForBackup\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+ hr = pPrepare->Wait();
+ pPrepare->Release();
+ if (FAILED(hr))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+
+ IVssAsync* pDoShadowCopy = NULL;
+ if (FAILED(hr = pBackupComponents->DoSnapshotSet( &pDoShadowCopy )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"DoSnapshotSet\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+ hr = pDoShadowCopy->Wait();
+ pDoShadowCopy->Release();
+ if (FAILED(hr))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"pPrepare->Wait\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+ VSS_SNAPSHOT_PROP props;
+ if (FAILED(hr = pBackupComponents->GetSnapshotProperties( SnapShotId, &props )))
+ {
+ releaseShadowCopy(pBackupComponents);
+ writeErrorMsg(L"Error calling \"GetSnapshotProperties\".", hr, errorMessage, errorBufferLen);
+ return false;
+ }
+
+ //finally: write volume name of newly created shadow copy
+ writeString(props.m_pwszSnapshotDeviceObject, shadowVolName, shadowBufferLen);
+
+ VssFreeSnapshotProperties(&props);
+
+ *backupHandle = pBackupComponents;
+
+ return true;
+}
+
+
+void shadow::releaseShadowCopy(void* backupHandle)
+{
+ if (backupHandle != NULL)
+ static_cast<IVssBackupComponents*>(backupHandle)->Release();
+}
diff --git a/library/ShadowCopy/shadow.h b/library/ShadowCopy/shadow.h
new file mode 100644
index 00000000..e25c6a32
--- /dev/null
+++ b/library/ShadowCopy/shadow.h
@@ -0,0 +1,33 @@
+#ifndef SHADOWCOPY_H
+#define SHADOWCOPY_H
+
+#ifdef SHADOWDLL_EXPORTS
+#define SHADOWDLL_API extern "C" __declspec(dllexport)
+#else
+#define SHADOWDLL_API extern "C" __declspec(dllimport)
+#endif
+
+
+namespace shadow
+{
+ //COM needs to be initialized before calling any of these functions! CoInitializeEx/CoUninitialize
+
+
+ //volumeName must end with "\", while shadowVolName does not end with "\"
+ SHADOWDLL_API
+ bool createShadowCopy(const wchar_t* volumeName,
+ wchar_t* shadowVolName,
+ unsigned int shadowBufferLen,
+ void** backupHandle,
+ wchar_t* errorMessage,
+ unsigned int errorBufferLen);
+
+
+ //don't forget to release the backupHandle after shadow copy is not needed anymore!
+ SHADOWDLL_API
+ void releaseShadowCopy(void* backupHandle);
+}
+
+
+
+#endif //SHADOWCOPY_H
diff --git a/library/fileError.h b/library/fileError.h
new file mode 100644
index 00000000..214cdecb
--- /dev/null
+++ b/library/fileError.h
@@ -0,0 +1,25 @@
+#ifndef FILEERROR_H_INCLUDED
+#define FILEERROR_H_INCLUDED
+
+#include "zstring.h"
+#include "fileError.h"
+
+namespace FreeFileSync
+{
+ class FileError //Exception class used to notify file/directory copy/delete errors
+ {
+ public:
+ FileError(const Zstring& message) :
+ errorMessage(message) {}
+
+ const Zstring& show() const
+ {
+ return errorMessage;
+ }
+
+ private:
+ Zstring errorMessage;
+ };
+}
+
+#endif // FILEERROR_H_INCLUDED
diff --git a/library/fileHandling.cpp b/library/fileHandling.cpp
index b6d3d9d7..06431b81 100644
--- a/library/fileHandling.cpp
+++ b/library/fileHandling.cpp
@@ -7,6 +7,7 @@
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include "shadow.h"
#elif defined FFS_LINUX
#include <sys/stat.h>
@@ -18,75 +19,76 @@
#include <errno.h>
#endif
+using FreeFileSync::FileError;
+
class RecycleBin
{
public:
- RecycleBin() :
- recycleBinAvailable(false)
+ static const RecycleBin& getInstance()
{
-#ifdef FFS_WIN
- recycleBinAvailable = true;
-#endif // FFS_WIN
+ static RecycleBin instance; //lazy creation of RecycleBin
+ return instance;
}
- ~RecycleBin() {}
-
- bool recycleBinExists()
+ bool recycleBinExists() const
{
return recycleBinAvailable;
}
- bool moveToRecycleBin(const Zstring& filename)
- {
- if (!recycleBinAvailable) //this method should ONLY be called if recycle bin is available
- throw RuntimeException(_("Initialization of Recycle Bin failed!"));
+ bool moveToRecycleBin(const Zstring& filename) const;
+private:
+ RecycleBin() :
+ recycleBinAvailable(false)
+ {
#ifdef FFS_WIN
- Zstring filenameDoubleNull = filename + wxChar(0);
-
- SHFILEOPSTRUCT fileOp;
- fileOp.hwnd = NULL;
- fileOp.wFunc = FO_DELETE;
- fileOp.pFrom = filenameDoubleNull.c_str();
- fileOp.pTo = NULL;
- fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
- fileOp.fAnyOperationsAborted = false;
- fileOp.hNameMappings = NULL;
- fileOp.lpszProgressTitle = NULL;
-
- if (SHFileOperation(&fileOp //pointer to an SHFILEOPSTRUCT structure that contains information the function needs to carry out
- ) != 0 || fileOp.fAnyOperationsAborted) return false;
-#else
- assert(false);
-#endif
-
- return true;
+ recycleBinAvailable = true;
+#endif // FFS_WIN
}
+ ~RecycleBin() {}
+
private:
bool recycleBinAvailable;
};
-inline
-RecycleBin& getRecycleBin()
+bool RecycleBin::moveToRecycleBin(const Zstring& filename) const
{
- static RecycleBin instance; //lazy creation of RecycleBin
- return instance;
+ if (!recycleBinAvailable) //this method should ONLY be called if recycle bin is available
+ throw RuntimeException(_("Initialization of Recycle Bin failed!"));
+
+#ifdef FFS_WIN
+ Zstring filenameDoubleNull = filename + wxChar(0);
+
+ SHFILEOPSTRUCT fileOp;
+ fileOp.hwnd = NULL;
+ fileOp.wFunc = FO_DELETE;
+ fileOp.pFrom = filenameDoubleNull.c_str();
+ fileOp.pTo = NULL;
+ fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
+ fileOp.fAnyOperationsAborted = false;
+ fileOp.hNameMappings = NULL;
+ fileOp.lpszProgressTitle = NULL;
+
+ if (SHFileOperation(&fileOp) != 0 || fileOp.fAnyOperationsAborted) return false;
+#endif
+
+ return true;
}
bool FreeFileSync::recycleBinExists()
{
- return getRecycleBin().recycleBinExists();
+ return RecycleBin::getInstance().recycleBinExists();
}
inline
bool moveToRecycleBin(const Zstring& filename) throw(RuntimeException)
{
- return getRecycleBin().moveToRecycleBin(filename);
+ return RecycleBin::getInstance().moveToRecycleBin(filename);
}
@@ -286,7 +288,7 @@ private:
class KernelDllHandler //dynamically load windows API functions
{
- typedef DWORD WINAPI (*GetFinalPath)(
+ typedef DWORD (WINAPI *GetFinalPath)(
HANDLE hFile,
LPTSTR lpszFilePath,
DWORD cchFilePath,
@@ -365,11 +367,11 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
return;
//try to create parent folders first
- const Zstring dirParent = directory.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring dirParent = directory.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (!dirParent.empty() && !wxDirExists(dirParent))
{
//call function recursively
- const Zstring templateParent = templateDir.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring templateParent = templateDir.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
createDirectoryRecursively(dirParent, templateParent, false, level + 1); //don't create symbolic links in recursion!
}
@@ -488,13 +490,13 @@ void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& temp
//remove trailing separator
Zstring dirFormatted;
if (FreeFileSync::endsWithPathSeparator(directory))
- dirFormatted = directory.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ dirFormatted = directory.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
else
dirFormatted = directory;
Zstring templateFormatted;
if (FreeFileSync::endsWithPathSeparator(templateDir))
- templateFormatted = templateDir.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ templateFormatted = templateDir.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
else
templateFormatted = templateDir;
@@ -502,7 +504,95 @@ void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& temp
}
-#ifdef FFS_LINUX
+#ifdef FFS_WIN
+
+#ifndef COPY_FILE_COPY_SYMLINK
+const DWORD COPY_FILE_COPY_SYMLINK = 0x00000800;
+#endif
+
+DWORD CALLBACK copyCallbackInternal(
+ LARGE_INTEGER totalFileSize,
+ LARGE_INTEGER totalBytesTransferred,
+ LARGE_INTEGER streamSize,
+ LARGE_INTEGER streamBytesTransferred,
+ DWORD dwStreamNumber,
+ DWORD dwCallbackReason,
+ HANDLE hSourceFile,
+ HANDLE hDestinationFile,
+ LPVOID lpData)
+{
+ using FreeFileSync::CopyFileCallback;
+
+ //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size).
+ static unsigned int callNr = 0;
+ if (++callNr % 50 == 0) //reduce by factor of 50 =^ 10-20 calls/sec
+ {
+ if (lpData != NULL)
+ {
+ //some odd check for some possible(?) error condition
+ if (totalBytesTransferred.HighPart < 0) //let's see if someone answers the call...
+ wxMessageBox(wxT("You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\
+ Please write a mail to the author of FreeFileSync at zhnmju123@gmx.de and simply state that\n\
+ \"totalBytesTransferred.HighPart can be below zero\"!\n\n\
+ This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu"), wxT("Warning"));
+
+
+ CopyFileCallback* callback = static_cast<CopyFileCallback*>(lpData);
+
+ switch (callback->updateCopyStatus(wxULongLong(totalBytesTransferred.HighPart, totalBytesTransferred.LowPart)))
+ {
+ case CopyFileCallback::CONTINUE:
+ break;
+ case CopyFileCallback::CANCEL:
+ return PROGRESS_CANCEL;
+ }
+ }
+ }
+
+ return PROGRESS_CONTINUE;
+}
+
+
+void FreeFileSync::copyFile(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const bool copyFileSymLinks,
+ ShadowCopy* shadowCopyHandler,
+ CopyFileCallback* callback)
+{
+ DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
+
+ if (copyFileSymLinks) //copy symbolic links instead of the files pointed at
+ copyFlags |= COPY_FILE_COPY_SYMLINK;
+
+ if (!::CopyFileEx( //same performance as CopyFile()
+ sourceFile.c_str(),
+ targetFile.c_str(),
+ copyCallbackInternal,
+ callback,
+ NULL,
+ copyFlags))
+ {
+ const DWORD lastError = ::GetLastError();
+
+ //if file is locked (try to) use Windows Volume Shadow Copy Service
+ if (lastError == ERROR_SHARING_VIOLATION && shadowCopyHandler != NULL)
+ {
+ const Zstring shadowFilename(shadowCopyHandler->makeShadowCopy(sourceFile));
+ FreeFileSync::copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied
+ targetFile,
+ copyFileSymLinks,
+ shadowCopyHandler,
+ callback);
+ return;
+ }
+
+ const Zstring errorMessage = Zstring(_("Error copying file:")) + wxT("\n\"") + sourceFile + wxT("\" -> \"") + targetFile + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError));
+ }
+}
+
+
+#elif defined FFS_LINUX
struct MemoryAllocator
{
MemoryAllocator()
@@ -523,9 +613,10 @@ struct MemoryAllocator
void FreeFileSync::copyFile(const Zstring& sourceFile,
const Zstring& targetFile,
const bool copyFileSymLinks,
- CopyFileCallback callback,
- void* data)
+ CopyFileCallback* callback)
{
+ using FreeFileSync::CopyFileCallback;
+
try
{
if (FreeFileSync::fileExists(targetFile.c_str()))
@@ -609,8 +700,18 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
totalBytesTransferred += memory.bufferSize;
//invoke callback method to update progress indicators
- if (callback)
- callback(totalBytesTransferred, data);
+ if (callback != NULL)
+ {
+ switch (callback->updateCopyStatus(totalBytesTransferred))
+ {
+ case CopyFileCallback::CONTINUE:
+ break;
+ case CopyFileCallback::CANCEL:
+ fileOut.close();
+ wxRemoveFile(targetFile.c_str()); //don't handle error situations!
+ return;
+ }
+ }
}
//close streams before changing attributes
@@ -741,7 +842,7 @@ public:
//ensure directoryFormatted ends with backslash
const Zstring directoryFormatted = FreeFileSync::endsWithPathSeparator(directory) ?
directory :
- directory + GlobalResources::FILE_NAME_SEPARATOR;
+ directory + FreeFileSync::FILE_NAME_SEPARATOR;
WIN32_FIND_DATA fileMetaData;
HANDLE searchHandle = FindFirstFile((directoryFormatted + DefaultChar('*')).c_str(), //pointer to name of file to search for
@@ -847,7 +948,7 @@ public:
const Zstring fullName = FreeFileSync::endsWithPathSeparator(directory) ? //e.g. "/"
directory + name :
- directory + GlobalResources::FILE_NAME_SEPARATOR + name;
+ directory + FreeFileSync::FILE_NAME_SEPARATOR + name;
struct stat fileInfo;
if (lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks
@@ -929,7 +1030,7 @@ void FreeFileSync::traverseInDetail(const Zstring& directory,
Zstring directoryFormatted = directory;
#ifdef FFS_LINUX //remove trailing slash
if (directoryFormatted.size() > 1 && FreeFileSync::endsWithPathSeparator(directoryFormatted))
- directoryFormatted = directoryFormatted.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ directoryFormatted = directoryFormatted.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
#endif
if (traverseDirectorySymlinks)
@@ -954,7 +1055,7 @@ Zstring getDriveName(const Zstring& directoryName) //GetVolume() doesn't work un
if (volumeName.empty())
return Zstring();
- return volumeName + wxFileName::GetVolumeSeparator().c_str() + GlobalResources::FILE_NAME_SEPARATOR;
+ return volumeName + wxFileName::GetVolumeSeparator().c_str() + FreeFileSync::FILE_NAME_SEPARATOR;
}
diff --git a/library/fileHandling.h b/library/fileHandling.h
index de068d1f..3abdbe07 100644
--- a/library/fileHandling.h
+++ b/library/fileHandling.h
@@ -3,21 +3,7 @@
#include <wx/dir.h>
#include "zstring.h"
-
-class FileError //Exception class used to notify file/directory copy/delete errors
-{
-public:
- FileError(const Zstring& message) :
- errorMessage(message) {}
-
- const Zstring& show() const
- {
- return errorMessage;
- }
-
-private:
- Zstring errorMessage;
-};
+#include "fileError.h"
namespace FreeFileSync
@@ -50,15 +36,34 @@ namespace FreeFileSync
void removeDirectory(const Zstring& directory, const bool useRecycleBin);
void removeFile(const Zstring& filename, const bool useRecycleBin);
void createDirectory(const Zstring& directory, const Zstring& templateDir, const bool copyDirectorySymLinks);
-#ifdef FFS_LINUX
- //callback function for status updates whily copying
- typedef void (*CopyFileCallback)(const wxULongLong& totalBytesTransferred, void* data);
+
+ class CopyFileCallback //callback functionality
+ {
+ public:
+ virtual ~CopyFileCallback() {}
+
+ enum Response
+ {
+ CONTINUE,
+ CANCEL
+ };
+ virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0;
+ };
+
+ class ShadowCopy;
+#ifdef FFS_WIN
void copyFile(const Zstring& sourceFile,
const Zstring& targetFile,
const bool copyFileSymLinks,
- CopyFileCallback callback = NULL,
- void* data = NULL);
+ ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies
+ CopyFileCallback* callback = NULL);
+
+#elif defined FFS_LINUX
+ void copyFile(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const bool copyFileSymLinks,
+ CopyFileCallback* callback);
#endif
}
diff --git a/library/filter.cpp b/library/filter.cpp
index d9ba8c5f..65513630 100644
--- a/library/filter.cpp
+++ b/library/filter.cpp
@@ -4,6 +4,7 @@
#include <set>
#include <vector>
#include "resources.h"
+#include "globalFunctions.h"
using FreeFileSync::FilterProcess;
@@ -36,14 +37,6 @@ void compoundStringToTable(const Zstring& compoundInput, const DefaultChar* deli
}
-inline
-void mergeVectors(std::vector<Zstring>& changing, const std::vector<Zstring>& input)
-{
- for (std::vector<Zstring>::const_iterator i = input.begin(); i != input.end(); ++i)
- changing.push_back(*i);
-}
-
-
std::vector<Zstring> compoundStringToFilter(const Zstring& filterString)
{
//delimiters may be ';' or '\n'
@@ -55,7 +48,8 @@ std::vector<Zstring> compoundStringToFilter(const Zstring& filterString)
{
std::vector<Zstring> newEntries;
compoundStringToTable(*i, wxT("\n"), newEntries);
- mergeVectors(filterList, newEntries);
+
+ globalFunctions::mergeVectors(newEntries, filterList);
}
return filterList;
@@ -76,12 +70,12 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
#endif
//remove leading separators (keep BEFORE test for Zstring::empty()!)
- if (filterFormatted.length() > 0 && *filterFormatted.c_str() == GlobalResources::FILE_NAME_SEPARATOR)
+ if (filterFormatted.length() > 0 && *filterFormatted.c_str() == FreeFileSync::FILE_NAME_SEPARATOR)
filterFormatted = Zstring(filterFormatted.c_str() + 1);
if (!filterFormatted.empty())
{
- //Test if filterFormatted ends with GlobalResources::FILE_NAME_SEPARATOR, ignoring '*' and '?'.
+ //Test if filterFormatted ends with FreeFileSync::FILE_NAME_SEPARATOR, ignoring '*' and '?'.
//If so, treat as filter for directory and add to directoryFilter.
const DefaultChar* filter = filterFormatted.c_str();
int i = filterFormatted.length() - 1;
@@ -93,7 +87,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st
break;
}
- if (i >= 0 && filter[i] == GlobalResources::FILE_NAME_SEPARATOR) //last FILE_NAME_SEPARATOR found
+ if (i >= 0 && filter[i] == FreeFileSync::FILE_NAME_SEPARATOR) //last FILE_NAME_SEPARATOR found
{
if (i != int(filterFormatted.length()) - 1) // "name\*"
{
@@ -124,7 +118,7 @@ bool matchesFilter(const DefaultChar* name, const std::set<Zstring>& filter)
const DefaultChar* const nameFormatted = name; //nothing to do here
#endif
- for (std::set<Zstring>::iterator j = filter.begin(); j != filter.end(); ++j)
+ for (std::set<Zstring>::const_iterator j = filter.begin(); j != filter.end(); ++j)
if (Zstring::Matches(nameFormatted, *j))
return true;
@@ -140,39 +134,43 @@ FilterProcess::FilterProcess(const wxString& includeFilter, const wxString& excl
//load filter into vectors of strings
//delimiters may be ';' or '\n'
- std::vector<Zstring> includeList = compoundStringToFilter(includeFilter.c_str());
- std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter.c_str());
+ const std::vector<Zstring> includeList = compoundStringToFilter(includeFilter.c_str());
+ const std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter.c_str());
//setup include/exclude filters for files and directories
- for (std::vector<Zstring>::iterator i = includeList.begin(); i != includeList.end(); ++i)
+ for (std::vector<Zstring>::const_iterator i = includeList.begin(); i != includeList.end(); ++i)
addFilterEntry(*i, filterFileIn, filterFolderIn);
- for (std::vector<Zstring>::iterator i = excludeList.begin(); i != excludeList.end(); ++i)
+ for (std::vector<Zstring>::const_iterator i = excludeList.begin(); i != excludeList.end(); ++i)
addFilterEntry(*i, filterFileEx, filterFolderEx);
}
-bool FilterProcess::matchesFileFilter(const DefaultChar* relFilename) const
+bool FilterProcess::matchesFileFilterIncl(const DefaultChar* relFilename) const
+{
+ return matchesFilter(relFilename, filterFileIn); //process include filters
+}
+
+
+bool FilterProcess::matchesFileFilterExcl(const DefaultChar* relFilename) const
+{
+ return matchesFilter(relFilename, filterFileEx); //process exclude filters
+}
+
+
+bool FilterProcess::matchesDirFilterIncl(const DefaultChar* relDirname) const
{
- if ( matchesFilter(relFilename, filterFileIn) && //process include filters
- !matchesFilter(relFilename, filterFileEx)) //process exclude filters
- return true;
- else
- return false;
+ return matchesFilter(relDirname, filterFolderIn); //process include filters
}
-bool FilterProcess::matchesDirFilter(const DefaultChar* relDirname) const
+bool FilterProcess::matchesDirFilterExcl(const DefaultChar* relDirname) const
{
- if ( matchesFilter(relDirname, filterFolderIn) && //process include filters
- !matchesFilter(relDirname, filterFolderEx)) //process exclude filters
- return true;
- else
- return false;
+ return matchesFilter(relDirname, filterFolderEx); //process exclude filters
}
-void FilterProcess::filterGridData(FolderComparison& folderCmp) const
+void FilterProcess::filterGridData(FreeFileSync::FolderComparison& folderCmp) const
{
//execute filtering...
for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
@@ -181,40 +179,31 @@ void FilterProcess::filterGridData(FolderComparison& folderCmp) const
for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
{
- //left hand side
- if (i->fileDescrLeft.objType == FileDescrLine::TYPE_FILE)
- {
- if (!matchesFileFilter(i->fileDescrLeft.relativeName.c_str()))
- {
- i->selectedForSynchronization = false;
- continue;
- }
- }
- else if (i->fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY)
- {
- if (!matchesDirFilter(i->fileDescrLeft.relativeName.c_str()))
- {
- i->selectedForSynchronization = false;
- continue;
- }
- }
- //right hand side
- else if (i->fileDescrRight.objType == FileDescrLine::TYPE_FILE)
+
+ const FileDescrLine& fileDescr = i->fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING ?
+ i->fileDescrLeft :
+ i->fileDescrRight;
+
+ if (fileDescr.objType == FileDescrLine::TYPE_FILE)
{
- if (!matchesFileFilter(i->fileDescrRight.relativeName.c_str()))
+ if ( !matchesFileFilterIncl(fileDescr.relativeName.c_str()) ||
+ matchesFileFilterExcl(fileDescr.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
}
}
- else if (i->fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY)
+ else if (fileDescr.objType == FileDescrLine::TYPE_DIRECTORY)
{
- if (!matchesDirFilter(i->fileDescrRight.relativeName.c_str()))
+ if ( !matchesDirFilterIncl(fileDescr.relativeName.c_str()) ||
+ matchesDirFilterExcl(fileDescr.relativeName.c_str()))
{
i->selectedForSynchronization = false;
continue;
}
}
+ else
+ assert(false);
i->selectedForSynchronization = true;
}
@@ -236,14 +225,14 @@ void inOrExcludeAllRows(FreeFileSync::FolderComparison& folderCmp)
}
-void FilterProcess::includeAllRowsOnGrid(FolderComparison& folderCmp)
+void FilterProcess::includeAllRowsOnGrid(FreeFileSync::FolderComparison& folderCmp)
{
//remove all filters on currentGridData
inOrExcludeAllRows<true>(folderCmp);
}
-void FilterProcess::excludeAllRowsOnGrid(FolderComparison& folderCmp)
+void FilterProcess::excludeAllRowsOnGrid(FreeFileSync::FolderComparison& folderCmp)
{
//exclude all rows on currentGridData
inOrExcludeAllRows<false>(folderCmp);
diff --git a/library/filter.h b/library/filter.h
index dd716680..85df591c 100644
--- a/library/filter.h
+++ b/library/filter.h
@@ -11,8 +11,10 @@ namespace FreeFileSync
public:
FilterProcess(const wxString& includeFilter, const wxString& excludeFilter);
- bool matchesFileFilter(const DefaultChar* relFilename) const;
- bool matchesDirFilter(const DefaultChar* relDirname) const;
+ bool matchesFileFilterIncl(const DefaultChar* relFilename) const;
+ bool matchesFileFilterExcl(const DefaultChar* relFilename) const;
+ bool matchesDirFilterIncl(const DefaultChar* relDirname) const;
+ bool matchesDirFilterExcl(const DefaultChar* relDirname) const;
void filterGridData(FolderComparison& folderCmp) const;
diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp
index 7c4a1b92..33932d67 100644
--- a/library/globalFunctions.cpp
+++ b/library/globalFunctions.cpp
@@ -1,40 +1,10 @@
#include "globalFunctions.h"
-#include "resources.h"
#include <wx/msgdlg.h>
#include <wx/file.h>
#include <fstream>
-
-
-std::string globalFunctions::numberToString(const unsigned int number)
-{
- char result[100];
- sprintf(result, "%u", number);
- return std::string(result);
-}
-
-
-std::string globalFunctions::numberToString(const int number)
-{
- char result[100];
- sprintf(result, "%d", number);
- return std::string(result);
-}
-
-
-std::string globalFunctions::numberToString(const long number)
-{
- char result[100];
- sprintf(result, "%ld", number);
- return std::string(result);
-}
-
-
-std::string globalFunctions::numberToString(const float number)
-{
- char result[100];
- sprintf(result, "%f", number);
- return std::string(result);
-}
+#include "../structures.h"
+#include <wx/stream.h>
+#include <wx/stopwatch.h>
wxString globalFunctions::numberToWxString(const unsigned int number)
@@ -97,7 +67,7 @@ wxString globalFunctions::includeNumberSeparator(const wxString& number)
{
wxString output(number);
for (int i = output.size() - 3; i > 0; i -= 3)
- output.insert(i, GlobalResources::THOUSANDS_SEPARATOR);
+ output.insert(i, FreeFileSync::THOUSANDS_SEPARATOR);
return output;
}
@@ -136,9 +106,10 @@ void globalFunctions::writeInt(wxOutputStream& stream, const int number)
//############################################################################
Performance::Performance() :
- resultWasShown(false)
+ resultWasShown(false),
+ timer(new wxStopWatch)
{
- timer.Start();
+ timer->Start();
}
@@ -152,8 +123,8 @@ Performance::~Performance()
void Performance::showResult()
{
resultWasShown = true;
- wxMessageBox(globalFunctions::numberToWxString(unsigned(timer.Time())) + wxT(" ms"));
- timer.Start(); //reset timer
+ wxMessageBox(globalFunctions::numberToWxString(unsigned(timer->Time())) + wxT(" ms"));
+ timer->Start(); //reset timer
}
@@ -203,5 +174,5 @@ void DebugLog::write(const wxString& logText)
wxString getCodeLocation(const wxString file, const int line)
{
- return wxString(file).AfterLast(GlobalResources::FILE_NAME_SEPARATOR) + wxT(", LINE ") + globalFunctions::numberToWxString(line) + wxT(" | ");
+ return wxString(file).AfterLast(FreeFileSync::FILE_NAME_SEPARATOR) + wxT(", LINE ") + globalFunctions::numberToWxString(line) + wxT(" | ");
}
diff --git a/library/globalFunctions.h b/library/globalFunctions.h
index 622babcb..689fa5f1 100644
--- a/library/globalFunctions.h
+++ b/library/globalFunctions.h
@@ -6,9 +6,14 @@
#include <vector>
#include <set>
#include <wx/string.h>
-#include <wx/stream.h>
-#include <wx/stopwatch.h>
#include <wx/longlong.h>
+#include <memory>
+#include <sstream>
+
+class wxInputStream;
+class wxOutputStream;
+class wxStopWatch;
+
namespace globalFunctions
{
@@ -25,10 +30,13 @@ namespace globalFunctions
return(d < 0 ? -d : d);
}
- std::string numberToString(const unsigned int number); //convert number to string
- std::string numberToString(const int number); //convert number to string
- std::string numberToString(const long number); //convert number to string
- std::string numberToString(const float number); //convert number to string
+ template <class T>
+ inline std::string numberToString(const T& number) //convert number to string the C++ way
+ {
+ std::stringstream ss;
+ ss << number;
+ return ss.str();
+ }
wxString numberToWxString(const unsigned int number); //convert number to wxString
wxString numberToWxString(const int number); //convert number to wxString
@@ -54,6 +62,43 @@ namespace globalFunctions
{
return wxLongLong(number.GetHi(), number.GetLo());
}
+
+
+ //Note: the following lines are a performance optimization for deleting elements from a vector. It is incredibly faster to create a new
+//vector and leave specific elements out than to delete row by row and force recopying of most elements for each single deletion (linear vs quadratic runtime)
+ template <class T>
+ void removeRowsFromVector(const std::set<int>& rowsToRemove, std::vector<T>& grid)
+ {
+ if (rowsToRemove.size() > 0)
+ {
+ std::vector<T> temp;
+
+ std::set<int>::const_iterator rowToSkipIndex = rowsToRemove.begin();
+ int rowToSkip = *rowToSkipIndex;
+
+ for (int i = 0; i < int(grid.size()); ++i)
+ {
+ if (i != rowToSkip)
+ temp.push_back(grid[i]);
+ else
+ {
+ ++rowToSkipIndex;
+ if (rowToSkipIndex != rowsToRemove.end())
+ rowToSkip = *rowToSkipIndex;
+ }
+ }
+ grid.swap(temp);
+ }
+ }
+
+
+ template <class T>
+ inline
+ void mergeVectors(const std::vector<T>& input, std::vector<T>& changing)
+ {
+ for (typename std::vector<T>::const_iterator i = input.begin(); i != input.end(); ++i) //nested dependent typename: see Meyers effective C++
+ changing.push_back(*i);
+ }
}
@@ -67,7 +112,7 @@ public:
private:
bool resultWasShown;
- wxStopWatch timer;
+ std::auto_ptr<wxStopWatch> timer;
};
//two macros for quick performance measurements
@@ -106,7 +151,6 @@ public:
wxString show() const
{
-
return errorMessage;
}
@@ -115,32 +159,4 @@ private:
};
-//Note: the following lines are a performance optimization for deleting elements from a vector. It is incredibly faster to create a new
-//vector and leave specific elements out than to delete row by row and force recopying of most elements for each single deletion (linear vs quadratic runtime)
-template <class T>
-void removeRowsFromVector(std::vector<T>& grid, const std::set<int>& rowsToRemove)
-{
- if (rowsToRemove.size() > 0)
- {
- std::vector<T> temp;
-
- std::set<int>::iterator rowToSkipIndex = rowsToRemove.begin();
- int rowToSkip = *rowToSkipIndex;
-
- for (int i = 0; i < int(grid.size()); ++i)
- {
- if (i != rowToSkip)
- temp.push_back(grid[i]);
- else
- {
- ++rowToSkipIndex;
- if (rowToSkipIndex != rowsToRemove.end())
- rowToSkip = *rowToSkipIndex;
- }
- }
- grid.swap(temp);
- }
-}
-
-
#endif // GLOBALFUNCTIONS_H_INCLUDED
diff --git a/library/iconBuffer.cpp b/library/iconBuffer.cpp
new file mode 100644
index 00000000..a969f689
--- /dev/null
+++ b/library/iconBuffer.cpp
@@ -0,0 +1,298 @@
+#include "iconBuffer.h"
+#include <wx/thread.h>
+#include "globalFunctions.h"
+#include <wx/utils.h>
+#include <wx/bitmap.h>
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include <wx/msgdlg.h>
+#include "../algorithm.h"
+#include <wx/icon.h>
+#include <map>
+#include <queue>
+
+using FreeFileSync::IconBuffer;
+
+
+class BasicString //simple thread safe string class
+{
+public:
+ BasicString()
+ {
+ data = new DefaultChar[1]; //compliance with delete []
+ *data = 0; //compliance with c_str()
+ }
+
+ BasicString(const Zstring& other) //make DEEP COPY from Zstring!
+ {
+ data = new DefaultChar[other.length() + 1];
+ memcpy(data, other.c_str(), (other.length() + 1) * sizeof(DefaultChar));
+ }
+
+ BasicString(const BasicString& other)
+ {
+ const size_t otherLen = defaultLength(other.c_str());
+ data = new DefaultChar[otherLen + 1];
+ memcpy(data, other.c_str(), (otherLen + 1) * sizeof(DefaultChar));
+ }
+
+ ~BasicString()
+ {
+ delete [] data;
+ }
+
+ BasicString& operator=(const BasicString& other)
+ { //exception safety; handle self-assignment implicitly
+ const size_t otherLen = defaultLength(other.c_str());
+ DefaultChar* dataNew = new DefaultChar[otherLen + 1];
+ memcpy(dataNew, other.c_str(), (otherLen + 1) * sizeof(DefaultChar));
+
+ delete data;
+ data = dataNew;
+
+ return *this;
+ }
+
+ const DefaultChar* c_str() const
+ {
+ return data;
+ }
+
+private:
+ DefaultChar* data;
+};
+
+
+class WorkerThread : public wxThread
+{
+public:
+ WorkerThread(IconBuffer* iconBuff);
+
+ void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved
+ void quitThread();
+
+ virtual ExitCode Entry();
+
+private:
+ void doWork();
+
+//---------------------- Shared Data -------------------------
+ typedef BasicString FileName;
+
+ wxCriticalSection lockWorkload; //use for locking shared data
+ std::vector<FileName> workload; //processes last elements of vector first!
+ bool threadHasMutex;
+ bool threadExitIsRequested;
+//------------------------------------------------------------
+
+ //event: icon buffer -> woker thread
+ wxMutex threadIsListening;
+ wxCondition continueWork; //wake up thread
+
+ IconBuffer* iconBuffer;
+};
+
+
+WorkerThread::WorkerThread(IconBuffer* iconBuff) :
+ wxThread(wxTHREAD_JOINABLE),
+ threadHasMutex(false),
+ threadExitIsRequested(false),
+ threadIsListening(),
+ continueWork(threadIsListening),
+ iconBuffer(iconBuff)
+{
+ if (Create() != wxTHREAD_NO_ERROR)
+ throw RuntimeException(wxString(wxT("Error creating icon buffer worker thread!")));
+
+ if (Run() != wxTHREAD_NO_ERROR)
+ throw RuntimeException(wxString(wxT("Error starting icon buffer worker thread!")));
+
+ //wait until thread has aquired mutex
+ bool hasMutex = false;
+ while (!hasMutex)
+ {
+ wxMilliSleep(5);
+ wxCriticalSectionLocker dummy(lockWorkload);
+ hasMutex = threadHasMutex;
+ } //polling -> it's not nice, but works and is no issue
+}
+
+
+void WorkerThread::setWorkload(const std::vector<Zstring>& load) //(re-)set new workload of icons to be retrieved
+{
+ wxCriticalSectionLocker dummy(lockWorkload);
+
+ workload.clear();
+ for (std::vector<Zstring>::const_iterator i = load.begin(); i != load.end(); ++i)
+ workload.push_back(*i); //make DEEP COPY from Zstring!
+
+ if (!workload.empty())
+ continueWork.Signal(); //wake thread IF he is waiting
+}
+
+
+void WorkerThread::quitThread()
+{
+ wxMutexLocker dummy(threadIsListening); //wait until thread is in waiting state
+ threadExitIsRequested = true; //no sharing conflicts in this situation
+ continueWork.Signal(); //exit thread
+}
+
+
+wxThread::ExitCode WorkerThread::Entry()
+{
+ try
+ {
+ wxMutexLocker dummy(threadIsListening); //this lock needs to be called from WITHIN the thread => calling it from constructor(Main thread) would be useless
+ { //this mutex STAYS locked all the time except of continueWork.Wait()!
+ wxCriticalSectionLocker dummy(lockWorkload);
+ threadHasMutex = true;
+ }
+
+ while (true)
+ {
+ continueWork.Wait(); //waiting for continueWork.Signal(); unlocks Mutex "threadIsListening"
+
+ //no mutex needed in this context
+ if (threadExitIsRequested) //no mutex here: atomicity is not prob for a bool, but visibility (e.g. caching in registers)
+ return 0; //shouldn't be a problem nevertheless because of implicit memory barrier caused by mutex.Lock() in .Wait()
+
+ //do work: get the file icon.
+ doWork();
+ }
+ }
+ catch (RuntimeException& e) //exceptions must be catched per thread
+ {
+ wxMessageBox(e.show());
+ return 0;
+ }
+}
+
+
+void WorkerThread::doWork()
+{
+ BasicString fileName; //don't use Zstring: reference-counted objects are NOT THREADSAFE!!! e.g. double deletion might happen
+
+ //do work: get the file icon.
+ while (true)
+ {
+ {
+ wxCriticalSectionLocker dummy(lockWorkload);
+ if (workload.empty())
+ break; //enter waiting state
+ fileName = workload.back();
+ workload.pop_back();
+ }
+
+ if (iconBuffer->requestIcon(Zstring(fileName.c_str()))) //thread safety: Zstring okay, won't be reference-counted in requestIcon()
+ break; //icon already in buffer: enter waiting state
+
+ //load icon
+ SHFILEINFO fileInfo;
+ fileInfo.hIcon = 0; //initialize hIcon
+
+ if (SHGetFileInfo(fileName.c_str(), //NOTE: CoInitializeEx()/CoUninitialize() implicitly called by wxWidgets on program startup!
+ 0,
+ &fileInfo,
+ sizeof(fileInfo),
+ SHGFI_ICON | SHGFI_SMALLICON) &&
+
+ fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!!
+ { //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080
+
+ wxIcon newIcon; //attention: wxIcon uses reference counting!
+ newIcon.SetHICON(fileInfo.hIcon);
+ newIcon.SetSize(IconBuffer::ICON_SIZE, IconBuffer::ICON_SIZE);
+
+ iconBuffer->insertIntoBuffer(fileName.c_str(), newIcon); //thread safety: icon may be deleted only within insertIntoBuffer()
+
+ //freeing of icon handle seems to happen somewhere beyond wxIcon destructor
+ //if (!DestroyIcon(fileInfo.hIcon))
+ // throw RuntimeException(wxString(wxT("Error deallocating Icon handle!\n\n")) + FreeFileSync::getLastErrorFormatted());
+
+ }
+ else
+ {
+ //if loading of icon fails for whatever reason, just save a dummy icon to avoid re-loading
+ iconBuffer->insertIntoBuffer(fileName.c_str(), wxNullIcon);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------------------------------
+
+typedef Zstring FileName;
+class IconDB : public std::map<FileName, wxIcon> {};
+class IconDbSequence : public std::queue<FileName> {};
+
+//---------------------------------------------------------------------------------------------------
+
+
+IconBuffer& IconBuffer::getInstance()
+{
+ static IconBuffer instance;
+ return instance;
+}
+
+
+IconBuffer::IconBuffer() :
+ lockIconDB( new wxCriticalSection),
+ buffer( new IconDB),
+ bufSequence(new IconDbSequence),
+ worker( new WorkerThread(this)) //might throw exceptions!
+{}
+
+
+IconBuffer::~IconBuffer()
+{
+ worker->quitThread();
+ worker->Wait(); //wait until thread has exitted
+}
+
+
+bool IconBuffer::requestIcon(const Zstring& fileName, wxIcon* icon)
+{
+ wxCriticalSectionLocker dummy(*lockIconDB);
+ IconDB::const_iterator i = buffer->find(fileName);
+
+ if (i != buffer->end())
+ {
+ if (icon != NULL)
+ *icon = i->second;
+ return true;
+ }
+
+ return false;
+}
+
+
+void IconBuffer::setWorkload(const std::vector<Zstring>& load)
+{
+ worker->setWorkload(load);
+}
+
+
+void IconBuffer::insertIntoBuffer(const DefaultChar* fileName, const wxIcon& icon) //called by worker thread
+{
+ if (icon.IsOk()) //this check won't hurt
+ {
+ wxCriticalSectionLocker dummy(*lockIconDB);
+
+ const Zstring fileNameZ = fileName;
+
+ const std::pair<IconDB::iterator, bool> rc = buffer->insert(IconDB::value_type(fileNameZ, icon));
+
+ if (rc.second) //if insertion took place
+ bufSequence->push(fileNameZ);
+
+ assert(buffer->size() == bufSequence->size());
+
+ //remove elements if buffer becomes too big:
+ if (buffer->size() > 1000) //limit buffer size: critical because large buffers seem to cause various wxIcon/wxBitmap issues!
+ {
+ //remove oldest element
+ buffer->erase(bufSequence->front());
+ bufSequence->pop();
+ }
+ }
+}
+
diff --git a/library/iconBuffer.h b/library/iconBuffer.h
new file mode 100644
index 00000000..ba905d22
--- /dev/null
+++ b/library/iconBuffer.h
@@ -0,0 +1,51 @@
+#ifndef ICONBUFFER_H_INCLUDED
+#define ICONBUFFER_H_INCLUDED
+
+#ifndef FFS_WIN
+#warning //this header should be used in the windows build only!
+#endif
+
+#include <vector>
+#include "zstring.h"
+#include <memory>
+
+class wxCriticalSection;
+class WorkerThread;
+class IconDB;
+class IconDbSequence;
+class wxIcon;
+
+
+namespace FreeFileSync
+{
+ class IconBuffer
+ {
+ friend class ::WorkerThread;
+
+ public:
+ static IconBuffer& getInstance();
+
+ bool requestIcon(const Zstring& fileName, wxIcon* icon = NULL); //returns false if icon is not in buffer
+ void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved;
+
+ static const int ICON_SIZE = 16; //size in pixel
+
+ private:
+ IconBuffer();
+ ~IconBuffer();
+
+ //methods used by worker thread
+ void insertIntoBuffer(const DefaultChar* fileName, const wxIcon& icon);
+
+//---------------------- Shared Data -------------------------
+ std::auto_ptr<wxCriticalSection> lockIconDB;
+ std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this!
+//------------------------------------------------------------
+
+ std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delte olderst elements
+
+ std::auto_ptr<WorkerThread> worker;
+ };
+}
+
+#endif // ICONBUFFER_H_INCLUDED
diff --git a/library/localization.cpp b/library/localization.cpp
index ef433012..9b5918a8 100644
--- a/library/localization.cpp
+++ b/library/localization.cpp
@@ -1,25 +1,134 @@
-#include "localization.h"
+#include "localization.h"
#include <wx/msgdlg.h>
-#include "resources.h"
+#include "../structures.h"
#include "globalFunctions.h"
#include <fstream>
#include <set>
+#include <map>
+#include "resources.h"
+
+using FreeFileSync::CustomLocale;
+using FreeFileSync::LocalizationInfo;
//_("Browse") <- dummy string for wxDirPickerCtrl to be recognized by automatic text extraction!
-struct TranslationLine
+const std::vector<FreeFileSync::LocInfoLine>& LocalizationInfo::getMapping()
{
- wxString original;
- wxString translation;
+ static LocalizationInfo instance;
+ return instance.locMapping;
+}
- bool operator<(const TranslationLine& b) const
- {
- return (original < b.original);
- }
-};
-class Translation : public std::set<TranslationLine> {};
+LocalizationInfo::LocalizationInfo()
+{
+ FreeFileSync::LocInfoLine newEntry;
+
+ newEntry.languageID = wxLANGUAGE_GERMAN;
+ newEntry.languageName = wxT("Deutsch");
+ newEntry.languageFile = "Languages/german.lng";
+ newEntry.translatorName = wxT("ZenJu");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapGermany;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_ENGLISH;
+ newEntry.languageName = wxT("English");
+ newEntry.languageFile = "";
+ newEntry.translatorName = wxT("ZenJu");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapEngland;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_SPANISH;
+ newEntry.languageName = wxT("Español");
+ newEntry.languageFile = "Languages/spanish.lng";
+ newEntry.translatorName = wxT("David Rodríguez");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapSpain;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_FRENCH;
+ newEntry.languageName = wxT("Français");
+ newEntry.languageFile = "Languages/french.lng";
+ newEntry.translatorName = wxT("Jean-François Hartmann");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapFrance;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_ITALIAN;
+ newEntry.languageName = wxT("Italiano");
+ newEntry.languageFile = "Languages/italian.lng";
+ newEntry.translatorName = wxT("Emmo");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapItaly;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_HUNGARIAN;
+ newEntry.languageName = wxT("Magyar");
+ newEntry.languageFile = "Languages/hungarian.lng";
+ newEntry.translatorName = wxT("Demon");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapHungary;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_DUTCH;
+ newEntry.languageName = wxT("Nederlands");
+ newEntry.languageFile = "Languages/dutch.lng";
+ newEntry.translatorName = wxT("M.D. Vrakking");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapHolland;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_RUSSIAN;
+ newEntry.languageName = wxT("Pусский язык");
+ newEntry.languageFile = "Languages/russian.lng";
+ newEntry.translatorName = wxT("Svobodniy");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapRussia;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_POLISH;
+ newEntry.languageName = wxT("Polski");
+ newEntry.languageFile = "Languages/polish.lng";
+ newEntry.translatorName = wxT("Wojtek Pietruszewski");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapPoland;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_PORTUGUESE;
+ newEntry.languageName = wxT("Português");
+ newEntry.languageFile = "Languages/portuguese.lng";
+ newEntry.translatorName = wxT("QuestMark");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapPortugal;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_PORTUGUESE_BRAZILIAN;
+ newEntry.languageName = wxT("Português do Brasil");
+ newEntry.languageFile = "Languages/portuguese_br.lng";
+ newEntry.translatorName = wxT("Edison Aranha");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapBrazil;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_SLOVENIAN;
+ newEntry.languageName = wxT("Slovenščina");
+ newEntry.languageFile = "Languages/slovenian.lng";
+ newEntry.translatorName = wxT("Matej Badalic");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapSlovakia;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_JAPANESE;
+ newEntry.languageName = wxT("日本語");
+ newEntry.languageFile = "Languages/japanese.lng";
+ newEntry.translatorName = wxT("Tilt");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapJapan;
+ locMapping.push_back(newEntry);
+
+ newEntry.languageID = wxLANGUAGE_CHINESE_SIMPLIFIED;
+ newEntry.languageName = wxT("简体中文");
+ newEntry.languageFile = "Languages/chinese_simple.lng";
+ newEntry.translatorName = wxT("Misty Wu");
+ newEntry.languageFlag = GlobalResources::getInstance().bitmapChina;
+ locMapping.push_back(newEntry);
+}
+
+
+
+typedef wxString TextOriginal;
+typedef wxString TextTranslation;
+
+class Translation : public std::map<TextOriginal, TextTranslation> {};
CustomLocale::CustomLocale() :
@@ -83,51 +192,19 @@ void exchangeEscapeChars(wxString& data)
void CustomLocale::setLanguage(const int language)
{
- currentLanguage = language;
-
+ //default: english
std::string languageFile;
- switch (language)
- {
- case wxLANGUAGE_CHINESE_SIMPLIFIED:
- languageFile = "Languages/chinese_simple.lng";
- break;
- case wxLANGUAGE_DUTCH:
- languageFile = "Languages/dutch.lng";
- break;
- case wxLANGUAGE_FRENCH:
- languageFile = "Languages/french.lng";
- break;
- case wxLANGUAGE_GERMAN:
- languageFile = "Languages/german.lng";
- break;
- case wxLANGUAGE_HUNGARIAN:
- languageFile = "Languages/hungarian.lng";
- break;
- case wxLANGUAGE_ITALIAN:
- languageFile = "Languages/italian.lng";
- break;
- case wxLANGUAGE_JAPANESE:
- languageFile = "Languages/japanese.lng";
- break;
- case wxLANGUAGE_POLISH:
- languageFile = "Languages/polish.lng";
- break;
- case wxLANGUAGE_PORTUGUESE:
- languageFile = "Languages/portuguese.lng";
- break;
- case wxLANGUAGE_PORTUGUESE_BRAZILIAN:
- languageFile = "Languages/portuguese_br.lng";
- break;
- case wxLANGUAGE_SLOVENIAN:
- languageFile = "Languages/slovenian.lng";
- break;
- case wxLANGUAGE_SPANISH:
- languageFile = "Languages/spanish.lng";
- break;
- default:
- languageFile.clear();
- currentLanguage = wxLANGUAGE_ENGLISH;
- }
+ currentLanguage = wxLANGUAGE_ENGLISH;
+
+ //(try to) retrieve language filename
+ for (std::vector<LocInfoLine>::const_iterator i = LocalizationInfo::getMapping().begin(); i != LocalizationInfo::getMapping().end(); ++i)
+ if (language == i->languageID)
+ {
+ languageFile = i->languageFile;
+ currentLanguage = i->languageID;
+ break;
+ }
+
static bool initialized = false; //wxLocale is a static global too!
if (!initialized)
@@ -145,7 +222,7 @@ void CustomLocale::setLanguage(const int language)
std::ifstream langFile(languageFile.c_str(), std::ios::binary);
if (langFile)
{
- TranslationLine currentLine;
+ wxString original;
//Delimiter:
//----------
@@ -162,39 +239,36 @@ void CustomLocale::setLanguage(const int language)
exchangeEscapeChars(formattedString);
if (rowNumber%2 == 0)
- currentLine.original = formattedString;
+ original = formattedString;
else
{
if (!formattedString.empty())
{
- currentLine.translation = formattedString;
- translationDB->insert(currentLine);
+ const wxString translation = formattedString;
+ translationDB->insert(std::pair<TextOriginal, TextTranslation>(original, translation));
}
}
}
langFile.close();
}
else
- wxMessageBox(wxString(_("Error reading file:")) + wxT(" \"") + wxString(languageFile.c_str(), wxConvUTF8) + wxT("\""), _("An exception occured!"), wxOK | wxICON_ERROR);
+ wxMessageBox(wxString(_("Error reading file:")) + wxT(" \"") + wxString(languageFile.c_str(), wxConvUTF8) + wxT("\""), _("Error"), wxOK | wxICON_ERROR);
}
else
; //if languageFile is empty texts will be english per default
//these global variables need to be redetermined on language selection
- GlobalResources::DECIMAL_POINT = _(".");
- GlobalResources::THOUSANDS_SEPARATOR = _(",");
+ FreeFileSync::DECIMAL_POINT = _(".");
+ FreeFileSync::THOUSANDS_SEPARATOR = _(",");
}
const wxChar* CustomLocale::GetString(const wxChar* szOrigString, const wxChar* szDomain) const
{
- TranslationLine currentLine;
- currentLine.original = szOrigString;
-
//look for translation in buffer table
- const Translation::iterator i = translationDB->find(currentLine);
+ const Translation::const_iterator i = translationDB->find(szOrigString);
if (i != translationDB->end())
- return i->translation.c_str();
+ return i->second.c_str();
//fallback
return szOrigString;
diff --git a/library/localization.h b/library/localization.h
index cf29d06d..7a63fd9c 100644
--- a/library/localization.h
+++ b/library/localization.h
@@ -2,31 +2,55 @@
#define MISC_H_INCLUDED
#include <wx/intl.h>
+#include <wx/bitmap.h>
+#include <vector>
class Translation;
-class CustomLocale : public wxLocale
+namespace FreeFileSync
{
-public:
- CustomLocale();
- ~CustomLocale();
+ struct LocInfoLine
+ {
+ int languageID;
+ wxString languageName;
+ std::string languageFile;
+ wxString translatorName;
+ wxBitmap* languageFlag;
+ };
+
+
+ class LocalizationInfo
+ {
+ public:
+ static const std::vector<LocInfoLine>& getMapping();
+
+ private:
+ LocalizationInfo();
+
+ std::vector<LocInfoLine> locMapping;
+ };
- void setLanguage(const int language);
- int getLanguage() const
+ class CustomLocale : public wxLocale
{
- return currentLanguage;
- }
+ public:
+ CustomLocale();
+ ~CustomLocale();
- const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const;
+ void setLanguage(const int language);
- static const std::string FfsLanguageDat;
+ int getLanguage() const
+ {
+ return currentLanguage;
+ }
-private:
- Translation* translationDB;
- int currentLanguage;
-};
+ const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const;
+ private:
+ Translation* translationDB;
+ int currentLanguage;
+ };
+}
#endif // MISC_H_INCLUDED
diff --git a/library/pch.h b/library/pch.h
index 50f9fda3..b561d448 100644
--- a/library/pch.h
+++ b/library/pch.h
@@ -1,8 +1,10 @@
#ifndef FFS_PRECOMPILED_HEADER
#define FFS_PRECOMPILED_HEADER
-DO NOT USE THIS FILE:
-FOR SOME REASON IT CORRUPTS COMPILATION!!!
+//pay attention when using this file: might cause issues!
+#ifndef __WXDEBUG__
+do NOT use in release build!
+#endif
//#####################################################
// basic wxWidgets headers
@@ -12,22 +14,17 @@ FOR SOME REASON IT CORRUPTS COMPILATION!!!
#include <wx/wxprec.h>
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
//#####################################################
// #include other rarely changing headers here
//STL headers
-#include <vector>
-#include <set>
#include <string>
-#include <stack>
#include <algorithm>
+#include <vector>
+#include <queue>
+#include <stack>
+#include <set>
#include <map>
-
-//C headers
#include <fstream>
#ifdef FFS_LINUX
@@ -36,7 +33,6 @@ FOR SOME REASON IT CORRUPTS COMPILATION!!!
//other wxWidgets headers
#include <wx/grid.h>
-#include <sys/stat.h>
#include <wx/animate.h>
#include <wx/app.h>
#include <wx/arrstr.h>
@@ -90,9 +86,10 @@ FOR SOME REASON IT CORRUPTS COMPILATION!!!
//other
#include "tinyxml/tinyxml.h"
+#include <sys/stat.h>
#ifdef FFS_WIN
-#include <windows.h>
+#include <wx/msw/wrapwin.h> //includes "windows.h"
#endif //FFS_WIN
//#####################################################
diff --git a/library/processXml.cpp b/library/processXml.cpp
index 750bd879..4b8ffe27 100644
--- a/library/processXml.cpp
+++ b/library/processXml.cpp
@@ -11,15 +11,12 @@
using namespace FreeFileSync;
-const wxString xmlAccess::LAST_CONFIG_FILE = wxT("LastRun.ffs_gui");
-const wxString xmlAccess::GLOBAL_CONFIG_FILE = wxT("GlobalSettings.xml");
-
//small helper functions
bool readXmlElementValue(std::string& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(int& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const std::string& name);
-bool readXmlElementValue(SyncDirection& output, const TiXmlElement* parent, const std::string& name);
+bool readXmlElementValue(SyncDirection& output, const TiXmlElement* parent, const std::string& name);
bool readXmlElementValue(bool& output, const TiXmlElement* parent, const std::string& name);
void addXmlElement(TiXmlElement* parent, const std::string& name, const std::string& value);
@@ -158,18 +155,18 @@ xmlAccess::XmlBatchConfig xmlAccess::readBatchConfig(const wxString& filename)
xmlAccess::XmlGlobalSettings xmlAccess::readGlobalSettings()
{
//load XML
- if (!wxFileExists(xmlAccess::GLOBAL_CONFIG_FILE))
- throw FileError(Zstring(_("File does not exist:")) + wxT(" \"") + xmlAccess::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
+ if (!wxFileExists(FreeFileSync::getGlobalConfigFile()))
+ throw FileError(Zstring(_("File does not exist:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile().c_str() + wxT("\""));
- XmlConfigInput inputFile(xmlAccess::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS);
+ XmlConfigInput inputFile(FreeFileSync::getGlobalConfigFile(), XML_GLOBAL_SETTINGS);
XmlGlobalSettings outputCfg;
if (!inputFile.loadedSuccessfully())
- throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + xmlAccess::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile().c_str() + wxT("\""));
if (!inputFile.readXmlGlobalSettings(outputCfg))
- throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + xmlAccess::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile().c_str() + wxT("\""));
return outputCfg;
}
@@ -201,12 +198,12 @@ void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig&
void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg)
{
- XmlConfigOutput outputFile(xmlAccess::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS);
+ XmlConfigOutput outputFile(FreeFileSync::getGlobalConfigFile(), XML_GLOBAL_SETTINGS);
//populate and write XML tree
if ( !outputFile.writeXmlGlobalSettings(outputCfg) || //add GUI layout configuration settings
!outputFile.writeToFile()) //save XML
- throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + xmlAccess::GLOBAL_CONFIG_FILE.c_str() + wxT("\""));
+ throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + FreeFileSync::getGlobalConfigFile().c_str() + wxT("\""));
return;
}
@@ -509,43 +506,49 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
if (global)
{
//try to read program language setting
- readXmlElementValue(outputCfg.shared.programLanguage, global, "Language");
+ readXmlElementValue(outputCfg.programLanguage, global, "Language");
//max. allowed file time deviation
int dummy = 0;
if (readXmlElementValue(dummy, global, "FileTimeTolerance"))
- outputCfg.shared.fileTimeTolerance = dummy;
+ outputCfg.fileTimeTolerance = dummy;
//ignore +/- 1 hour due to DST change
- readXmlElementValue(outputCfg.shared.ignoreOneHourDiff, global, "IgnoreOneHourDifference");
+ readXmlElementValue(outputCfg.ignoreOneHourDiff, global, "IgnoreOneHourDifference");
//traverse into symbolic links (to folders)
- readXmlElementValue(outputCfg.shared.traverseDirectorySymlinks, global, "TraverseDirectorySymlinks");
+ readXmlElementValue(outputCfg.traverseDirectorySymlinks, global, "TraverseDirectorySymlinks");
//copy symbolic links to files
- readXmlElementValue(outputCfg.shared.copyFileSymlinks, global, "CopyFileSymlinks");
+ readXmlElementValue(outputCfg.copyFileSymlinks, global, "CopyFileSymlinks");
//last update check
- readXmlElementValue(outputCfg.shared.lastUpdateCheck, global, "LastCheckForUpdates");
+ readXmlElementValue(outputCfg.lastUpdateCheck, global, "LastCheckForUpdates");
}
TiXmlElement* warnings = hRoot.FirstChild("Shared").FirstChild("Warnings").ToElement();
if (warnings)
{
//folder dependency check
- readXmlElementValue(outputCfg.shared.warningDependentFolders, warnings, "CheckForDependentFolders");
+ readXmlElementValue(outputCfg.warnings.warningDependentFolders, warnings, "CheckForDependentFolders");
//significant difference check
- readXmlElementValue(outputCfg.shared.warningSignificantDifference, warnings, "CheckForSignificantDifference");
+ readXmlElementValue(outputCfg.warnings.warningSignificantDifference, warnings, "CheckForSignificantDifference");
//check free disk space
- readXmlElementValue(outputCfg.shared.warningNotEnoughDiskSpace, warnings, "CheckForFreeDiskSpace");
+ readXmlElementValue(outputCfg.warnings.warningNotEnoughDiskSpace, warnings, "CheckForFreeDiskSpace");
//check for unresolved conflicts
- readXmlElementValue(outputCfg.shared.warningUnresolvedConflicts, warnings, "CheckForUnresolvedConflicts");
+ readXmlElementValue(outputCfg.warnings.warningUnresolvedConflicts, warnings, "CheckForUnresolvedConflicts");
+
+ //check for very old dates or dates in the future
+ readXmlElementValue(outputCfg.warnings.warningInvalidDate, warnings, "CheckForInvalidFileDate");
+
+ //check for changed files with same modification date
+ readXmlElementValue(outputCfg.warnings.warningSameDateDiffSize, warnings, "SameDateDifferentFileSize");
- //small reminder that synchronization will be starting immediately
- readXmlElementValue(outputCfg.shared.warningSynchronizationStarting, warnings, "SynchronizationStarting");
+ //check for files that have a difference in file modification date below 1 hour when DST check is active
+ readXmlElementValue(outputCfg.warnings.warningDSTChangeWithinHour, warnings, "FileChangeWithinHour");
}
//gui specific global settings (optional)
@@ -553,16 +556,18 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
if (mainWindow)
{
//read application window size and position
- readXmlElementValue(outputCfg.gui.widthNotMaximized, mainWindow, "Width");
+ readXmlElementValue(outputCfg.gui.widthNotMaximized, mainWindow, "Width");
readXmlElementValue(outputCfg.gui.heightNotMaximized, mainWindow, "Height");
- readXmlElementValue(outputCfg.gui.posXNotMaximized, mainWindow, "PosX");
- readXmlElementValue(outputCfg.gui.posYNotMaximized, mainWindow, "PosY");
- readXmlElementValue(outputCfg.gui.isMaximized, mainWindow, "Maximized");
+ readXmlElementValue(outputCfg.gui.posXNotMaximized, mainWindow, "PosX");
+ readXmlElementValue(outputCfg.gui.posYNotMaximized, mainWindow, "PosY");
+ readXmlElementValue(outputCfg.gui.isMaximized, mainWindow, "Maximized");
- readXmlElementValue(outputCfg.gui.deleteOnBothSides, mainWindow, "ManualDeletionOnBothSides");
+ readXmlElementValue(outputCfg.gui.deleteOnBothSides, mainWindow, "ManualDeletionOnBothSides");
readXmlElementValue(outputCfg.gui.useRecyclerForManualDeletion, mainWindow, "ManualDeletionUseRecycler");
- readXmlElementValue(outputCfg.gui.showFileIcons, mainWindow, "ShowFileIcons");
- readXmlElementValue(outputCfg.gui.popupOnConfigChange, mainWindow, "PopupOnConfigChange");
+ readXmlElementValue(outputCfg.gui.showFileIconsLeft, mainWindow, "ShowFileIconsLeft");
+ readXmlElementValue(outputCfg.gui.showFileIconsRight, mainWindow, "ShowFileIconsRight");
+ readXmlElementValue(outputCfg.gui.popupOnConfigChange, mainWindow, "PopupOnConfigChange");
+ readXmlElementValue(outputCfg.gui.showSummaryBeforeSync, mainWindow, "SummaryBeforeSync");
//###########################################################
//read column attributes
@@ -638,6 +643,8 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
//load config history elements
readXmlElementTable(outputCfg.gui.folderHistoryRight, historyRight, "Folder");
}
+
+ readXmlElementValue(outputCfg.gui.selectedTabBottomLeft, mainWindow, "SelectedTabBottomLeft");
}
TiXmlElement* gui = hRoot.FirstChild("Gui").ToElement();
@@ -667,9 +674,6 @@ bool XmlConfigInput::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputC
TiXmlElement* batch = hRoot.FirstChild("Batch").ToElement();
if (!batch) return false;
-
-// if (!readXmlElementValue(outputCfg.dummy, global, "Language")) return false;
-
return true;
}
@@ -889,41 +893,47 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
root->LinkEndChild(global);
//program language
- addXmlElement(global, "Language", inputCfg.shared.programLanguage);
+ addXmlElement(global, "Language", inputCfg.programLanguage);
//max. allowed file time deviation
- addXmlElement(global, "FileTimeTolerance", int(inputCfg.shared.fileTimeTolerance));
+ addXmlElement(global, "FileTimeTolerance", int(inputCfg.fileTimeTolerance));
//ignore +/- 1 hour due to DST change
- addXmlElement(global, "IgnoreOneHourDifference", inputCfg.shared.ignoreOneHourDiff);
+ addXmlElement(global, "IgnoreOneHourDifference", inputCfg.ignoreOneHourDiff);
//traverse into symbolic links (to folders)
- addXmlElement(global, "TraverseDirectorySymlinks", inputCfg.shared.traverseDirectorySymlinks);
+ addXmlElement(global, "TraverseDirectorySymlinks", inputCfg.traverseDirectorySymlinks);
//copy symbolic links to files
- addXmlElement(global, "CopyFileSymlinks", inputCfg.shared.copyFileSymlinks);
+ addXmlElement(global, "CopyFileSymlinks", inputCfg.copyFileSymlinks);
//last update check
- addXmlElement(global, "LastCheckForUpdates", inputCfg.shared.lastUpdateCheck);
+ addXmlElement(global, "LastCheckForUpdates", inputCfg.lastUpdateCheck);
//warnings
TiXmlElement* warnings = new TiXmlElement("Warnings");
global->LinkEndChild(warnings);
//warning: dependent folders
- addXmlElement(warnings, "CheckForDependentFolders", inputCfg.shared.warningDependentFolders);
+ addXmlElement(warnings, "CheckForDependentFolders", inputCfg.warnings.warningDependentFolders);
//significant difference check
- addXmlElement(warnings, "CheckForSignificantDifference", inputCfg.shared.warningSignificantDifference);
+ addXmlElement(warnings, "CheckForSignificantDifference", inputCfg.warnings.warningSignificantDifference);
//check free disk space
- addXmlElement(warnings, "CheckForFreeDiskSpace", inputCfg.shared.warningNotEnoughDiskSpace);
+ addXmlElement(warnings, "CheckForFreeDiskSpace", inputCfg.warnings.warningNotEnoughDiskSpace);
//check for unresolved conflicts
- addXmlElement(warnings, "CheckForUnresolvedConflicts", inputCfg.shared.warningUnresolvedConflicts);
+ addXmlElement(warnings, "CheckForUnresolvedConflicts", inputCfg.warnings.warningUnresolvedConflicts);
+
+ //check for very old dates or dates in the future
+ addXmlElement(warnings, "CheckForInvalidFileDate", inputCfg.warnings.warningInvalidDate);
- //small reminder that synchronization will be starting immediately
- addXmlElement(warnings, "SynchronizationStarting", inputCfg.shared.warningSynchronizationStarting);
+ //check for changed files with same modification date
+ addXmlElement(warnings, "SameDateDifferentFileSize", inputCfg.warnings.warningSameDateDiffSize);
+
+ //check for files that have a difference in file modification date below 1 hour when DST check is active
+ addXmlElement(warnings, "FileChangeWithinHour", inputCfg.warnings.warningDSTChangeWithinHour);
//###################################################################
@@ -948,8 +958,10 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
addXmlElement(mainWindow, "ManualDeletionOnBothSides", inputCfg.gui.deleteOnBothSides);
addXmlElement(mainWindow, "ManualDeletionUseRecycler", inputCfg.gui.useRecyclerForManualDeletion);
- addXmlElement(mainWindow, "ShowFileIcons" , inputCfg.gui.showFileIcons);
- addXmlElement(mainWindow, "PopupOnConfigChange" , inputCfg.gui.popupOnConfigChange);
+ addXmlElement(mainWindow, "ShowFileIconsLeft", inputCfg.gui.showFileIconsLeft);
+ addXmlElement(mainWindow, "ShowFileIconsRight", inputCfg.gui.showFileIconsRight);
+ addXmlElement(mainWindow, "PopupOnConfigChange", inputCfg.gui.popupOnConfigChange);
+ addXmlElement(mainWindow, "SummaryBeforeSync", inputCfg.gui.showSummaryBeforeSync);
//write column attributes
TiXmlElement* leftColumn = new TiXmlElement("LeftColumns");
@@ -996,6 +1008,7 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings&
historyRight->SetAttribute("MaximumSize", globalFunctions::numberToString(inputCfg.gui.folderHistRightMax));
addXmlElementTable(historyRight, "Folder", inputCfg.gui.folderHistoryRight);
+ addXmlElement(mainWindow, "SelectedTabBottomLeft", inputCfg.gui.selectedTabBottomLeft);
//commandline for file manager integration
addXmlElement(gui, "FileManager", std::string((inputCfg.gui.commandLineFileManager).ToUTF8()));
@@ -1056,6 +1069,10 @@ int xmlAccess::retrieveSystemLanguage()
case wxLANGUAGE_CHINESE_TAIWAN:
return wxLANGUAGE_CHINESE_SIMPLIFIED;
+ //variants of wxLANGUAGE_RUSSIAN
+ case wxLANGUAGE_RUSSIAN_UKRAINE:
+ return wxLANGUAGE_RUSSIAN;
+
//variants of wxLANGUAGE_SPANISH
case wxLANGUAGE_SPANISH_ARGENTINA:
case wxLANGUAGE_SPANISH_BOLIVIA:
@@ -1110,11 +1127,13 @@ bool xmlAccess::supportForSymbolicLinks()
}
-void xmlAccess::XmlGlobalSettings::_Shared::resetWarnings()
+void xmlAccess::WarningMessages::resetWarnings()
{
warningDependentFolders = true;
warningSignificantDifference = true;
warningNotEnoughDiskSpace = true;
warningUnresolvedConflicts = true;
- warningSynchronizationStarting = true;
+ warningInvalidDate = true;
+ warningSameDateDiffSize = true;
+ warningDSTChangeWithinHour = true;
}
diff --git a/library/processXml.h b/library/processXml.h
index 313fbfae..15972289 100644
--- a/library/processXml.h
+++ b/library/processXml.h
@@ -6,9 +6,6 @@
namespace xmlAccess
{
- extern const wxString LAST_CONFIG_FILE;
- extern const wxString GLOBAL_CONFIG_FILE;
-
enum OnError
{
ON_ERROR_POPUP,
@@ -93,38 +90,45 @@ namespace xmlAccess
bool supportForSymbolicLinks();
+ struct WarningMessages
+ {
+ WarningMessages()
+ {
+ resetWarnings();
+ }
+
+ void resetWarnings();
+
+ bool warningDependentFolders;
+ bool warningSignificantDifference;
+ bool warningNotEnoughDiskSpace;
+ bool warningUnresolvedConflicts;
+ bool warningInvalidDate;
+ bool warningSameDateDiffSize;
+ bool warningDSTChangeWithinHour;
+ };
+
+
struct XmlGlobalSettings
{
//---------------------------------------------------------------------
- struct _Shared
- {
- _Shared() :
- programLanguage(retrieveSystemLanguage()),
- fileTimeTolerance(2), //default 2s: FAT vs NTFS
- ignoreOneHourDiff(true),
- traverseDirectorySymlinks(false),
- copyFileSymlinks(supportForSymbolicLinks()),
- lastUpdateCheck(0)
- {
- resetWarnings();
- }
-
- int programLanguage;
- unsigned int fileTimeTolerance; //max. allowed file time deviation
- bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change
- bool traverseDirectorySymlinks;
- bool copyFileSymlinks; //copy symbolic link instead of target file
- long lastUpdateCheck; //time of last update check
-
- //warnings
- void resetWarnings();
-
- bool warningDependentFolders;
- bool warningSignificantDifference;
- bool warningNotEnoughDiskSpace;
- bool warningUnresolvedConflicts;
- bool warningSynchronizationStarting;
- } shared;
+ //Shared (GUI/BATCH) settings
+ XmlGlobalSettings() :
+ programLanguage(retrieveSystemLanguage()),
+ fileTimeTolerance(2), //default 2s: FAT vs NTFS
+ ignoreOneHourDiff(true),
+ traverseDirectorySymlinks(false),
+ copyFileSymlinks(supportForSymbolicLinks()),
+ lastUpdateCheck(0) {}
+
+ int programLanguage;
+ unsigned int fileTimeTolerance; //max. allowed file time deviation
+ bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change
+ bool traverseDirectorySymlinks;
+ bool copyFileSymlinks; //copy symbolic link instead of target file
+ long lastUpdateCheck; //time of last update check
+
+ WarningMessages warnings;
//---------------------------------------------------------------------
struct _Gui
@@ -143,10 +147,13 @@ namespace xmlAccess
cfgHistoryMax(10),
folderHistLeftMax(12),
folderHistRightMax(12),
+ selectedTabBottomLeft(0),
deleteOnBothSides(false),
useRecyclerForManualDeletion(FreeFileSync::recycleBinExists()), //enable if OS supports it; else user will have to activate first and then get an error message
- showFileIcons(true),
- popupOnConfigChange(true) {}
+ showFileIconsLeft(true),
+ showFileIconsRight(true),
+ popupOnConfigChange(true),
+ showSummaryBeforeSync(true) {}
int widthNotMaximized;
int heightNotMaximized;
@@ -168,10 +175,14 @@ namespace xmlAccess
std::vector<wxString> folderHistoryRight;
unsigned int folderHistRightMax;
+ int selectedTabBottomLeft;
+
bool deleteOnBothSides;
bool useRecyclerForManualDeletion;
- bool showFileIcons;
+ bool showFileIconsLeft;
+ bool showFileIconsRight;
bool popupOnConfigChange;
+ bool showSummaryBeforeSync;
} gui;
//---------------------------------------------------------------------
diff --git a/library/resources.cpp b/library/resources.cpp
index 9e43a78a..38f2a051 100644
--- a/library/resources.cpp
+++ b/library/resources.cpp
@@ -5,20 +5,15 @@
#include <wx/icon.h>
#include <wx/mstream.h>
#include "globalFunctions.h"
+#include "../structures.h"
-#ifdef FFS_WIN
-const wxChar GlobalResources::FILE_NAME_SEPARATOR = '\\';
-#elif defined FFS_LINUX
-const wxChar GlobalResources::FILE_NAME_SEPARATOR = '/';
-#else
-assert(false);
-#endif
-//these two global variables are language-dependent => cannot be set statically! See CustomLocale
-const wxChar* GlobalResources::DECIMAL_POINT = wxEmptyString;
-const wxChar* GlobalResources::THOUSANDS_SEPARATOR = wxEmptyString;
+const GlobalResources& GlobalResources::getInstance()
+{
+ static GlobalResources instance;
+ return instance;
+}
-GlobalResources globalResource; //init resources on program startup
GlobalResources::GlobalResources()
{
@@ -42,6 +37,7 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("sync.png")] = (bitmapSync = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("sync disabled.png")] = (bitmapSyncDisabled = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("swap.png")] = (bitmapSwap = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("swapSmall.png")] = (bitmapSwapSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("help.png")] = (bitmapHelp = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnly.png")] = (bitmapLeftOnly = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnlyAct.png")] = (bitmapLeftOnlyAct = new wxBitmap(wxNullBitmap));
@@ -67,6 +63,7 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("exclude.png")] = (bitmapExclude = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("filter active.png")] = (bitmapFilterOn = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("filter not active.png")] = (bitmapFilterOff = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("filter_small.png")] = (bitmapFilterSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("warning.png")] = (bitmapWarning = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("warningSmall.png")] = (bitmapWarningSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("error.png")] = (bitmapError = new wxBitmap(wxNullBitmap));
@@ -124,6 +121,7 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("brazil.png")] = (bitmapBrazil = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("slovakia.png")] = (bitmapSlovakia = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("spain.png")] = (bitmapSpain = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("russia.png")] = (bitmapRussia = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("syncDirLeftAct.png")] = (bitmapSyncDirLeftAct = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("syncDirLeftDeact.png")] = (bitmapSyncDirLeftDeact = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("syncDirRightAct.png")] = (bitmapSyncDirRightAct = new wxBitmap(wxNullBitmap));
@@ -133,6 +131,10 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("syncDirLeftSmall.png")] = (bitmapSyncDirLeftSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("syncDirRightSmall.png")] = (bitmapSyncDirRightSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("syncDirNoneSmall.png")] = (bitmapSyncDirNoneSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("createLeftSmall.png")] = (bitmapCreateLeftSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("createRightSmall.png")] = (bitmapCreateRightSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("deleteLeftSmall.png")] = (bitmapDeleteLeftSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("deleteRightSmall.png")] = (bitmapDeleteRightSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftOnlySmall.png")] = (bitmapLeftOnlySmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("rightOnlySmall.png")] = (bitmapRightOnlySmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("leftNewerSmall.png")] = (bitmapLeftNewerSmall = new wxBitmap(wxNullBitmap));
@@ -144,8 +146,8 @@ GlobalResources::GlobalResources()
bitmapResource[wxT("update.png")] = (bitmapUpdate = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("delete.png")] = (bitmapDelete = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("data.png")] = (bitmapData = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("cmpView.png")] = (bitmapCmpView = new wxBitmap(wxNullBitmap));
- bitmapResource[wxT("syncView.png")] = (bitmapSyncView = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("cmpViewSmall.png")] = (bitmapCmpViewSmall = new wxBitmap(wxNullBitmap));
+ bitmapResource[wxT("syncViewSmall.png")] = (bitmapSyncViewSmall = new wxBitmap(wxNullBitmap));
bitmapResource[wxT("toggleViewSmall.png")] = (bitmapSwitchViewSmall = new wxBitmap(wxNullBitmap));
@@ -187,9 +189,9 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation)
}
-void GlobalResources::load()
+void GlobalResources::load() const
{
- wxFileInputStream input(wxT("Resources.dat"));
+ wxFileInputStream input(FreeFileSync::getInstallationDir() + FreeFileSync::FILE_NAME_SEPARATOR + wxT("Resources.dat"));
if (input.IsOk()) //if not... we don't want to react too harsh here
{
//activate support for .png files
@@ -214,7 +216,7 @@ void GlobalResources::load()
}
#ifdef FFS_WIN
- *programIcon = wxIcon(wxT("ffsIcon1"));
+ *programIcon = wxIcon(wxT("A_PROGRAM_ICON"));
#else
#include "FreeFileSync.xpm"
*programIcon = wxIcon(FreeFileSync_xpm);
diff --git a/library/resources.h b/library/resources.h
index 60b4ab48..1ce7d20e 100644
--- a/library/resources.h
+++ b/library/resources.h
@@ -10,16 +10,7 @@
class GlobalResources
{
public:
- GlobalResources();
- ~GlobalResources();
-
- void load();
-
- static const wxChar FILE_NAME_SEPARATOR;
-
- //language dependent global variables: need to be initialized by CustomLocale on program startup and language switch
- static const wxChar* DECIMAL_POINT;
- static const wxChar* THOUSANDS_SEPARATOR;
+ static const GlobalResources& getInstance();
//image resource objects
wxBitmap* bitmapArrowLeft;
@@ -41,6 +32,7 @@ public:
wxBitmap* bitmapSync;
wxBitmap* bitmapSyncDisabled;
wxBitmap* bitmapSwap;
+ wxBitmap* bitmapSwapSmall;
wxBitmap* bitmapHelp;
wxBitmap* bitmapLeftOnly;
wxBitmap* bitmapLeftOnlyAct;
@@ -66,6 +58,7 @@ public:
wxBitmap* bitmapExclude;
wxBitmap* bitmapFilterOn;
wxBitmap* bitmapFilterOff;
+ wxBitmap* bitmapFilterSmall;
wxBitmap* bitmapWarning;
wxBitmap* bitmapWarningSmall;
wxBitmap* bitmapError;
@@ -123,6 +116,7 @@ public:
wxBitmap* bitmapBrazil;
wxBitmap* bitmapSlovakia;
wxBitmap* bitmapSpain;
+ wxBitmap* bitmapRussia;
wxBitmap* bitmapSyncDirLeftAct;
wxBitmap* bitmapSyncDirLeftDeact;
wxBitmap* bitmapSyncDirRightAct;
@@ -132,6 +126,10 @@ public:
wxBitmap* bitmapSyncDirLeftSmall;
wxBitmap* bitmapSyncDirRightSmall;
wxBitmap* bitmapSyncDirNoneSmall;
+ wxBitmap* bitmapCreateLeftSmall;
+ wxBitmap* bitmapCreateRightSmall;
+ wxBitmap* bitmapDeleteLeftSmall;
+ wxBitmap* bitmapDeleteRightSmall;
wxBitmap* bitmapLeftOnlySmall;
wxBitmap* bitmapRightOnlySmall;
wxBitmap* bitmapLeftNewerSmall;
@@ -143,8 +141,8 @@ public:
wxBitmap* bitmapUpdate;
wxBitmap* bitmapDelete;
wxBitmap* bitmapData;
- wxBitmap* bitmapCmpView;
- wxBitmap* bitmapSyncView;
+ wxBitmap* bitmapCmpViewSmall;
+ wxBitmap* bitmapSyncViewSmall;
wxBitmap* bitmapSwitchViewSmall;
wxAnimation* animationMoney;
@@ -152,12 +150,14 @@ public:
wxIcon* programIcon;
+ void load() const; //loads bitmap resources on program startup: logical const!
+
private:
+ GlobalResources();
+ ~GlobalResources();
+
//resource mapping
- std::map<wxString, wxBitmap*> bitmapResource;
+ mutable std::map<wxString, wxBitmap*> bitmapResource;
};
-
-extern GlobalResources globalResource; //loads bitmap resources on program startup
-
#endif // RESOURCES_H_INCLUDED
diff --git a/library/shadow.cpp b/library/shadow.cpp
new file mode 100644
index 00000000..c353bcb2
--- /dev/null
+++ b/library/shadow.cpp
@@ -0,0 +1,148 @@
+#include "shadow.h"
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include <wx/intl.h>
+#include "../structures.h"
+
+using FreeFileSync::ShadowCopy;
+
+
+class ShadowlDllHandler //dynamically load windows API functions
+{
+ typedef bool (*CreateShadowCopyFct)( //volumeName must end with "\", while shadowVolName does not end with "\"
+ const wchar_t* volumeName,
+ wchar_t* shadowVolName,
+ unsigned int shadowBufferLen,
+ void** backupHandle,
+ wchar_t* errorMessage,
+ unsigned int errorBufferLen);
+
+ typedef void (*ReleaseShadowCopyFct)(void* backupHandle);
+
+public:
+ static const ShadowlDllHandler& getInstance()
+ {
+ static ShadowlDllHandler instance;
+ return instance;
+ }
+
+ CreateShadowCopyFct createShadowCopy;
+ ReleaseShadowCopyFct releaseShadowCopy;
+
+private:
+ ShadowlDllHandler() :
+ createShadowCopy(NULL),
+ releaseShadowCopy(NULL),
+ hShadow(NULL)
+ {
+ //get a handle to the DLL module containing the required functionality
+ hShadow = ::LoadLibrary(L"Shadow.dll");
+ if (hShadow)
+ {
+ createShadowCopy = reinterpret_cast<CreateShadowCopyFct>(::GetProcAddress(hShadow, "createShadowCopy"));
+ releaseShadowCopy = reinterpret_cast<ReleaseShadowCopyFct>(::GetProcAddress(hShadow, "releaseShadowCopy"));
+ }
+ }
+
+ ~ShadowlDllHandler()
+ {
+ if (hShadow) ::FreeLibrary(hShadow);
+ }
+
+ HINSTANCE hShadow;
+};
+
+
+ShadowCopy::ShadowCopy() :
+ backupHandle(NULL) {}
+
+
+ShadowCopy::~ShadowCopy()
+{
+ if (backupHandle != NULL)
+ ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle);
+}
+
+
+bool ShadowCopy::isOkay()
+{
+ //check that all functions could be loaded
+ return ShadowlDllHandler::getInstance().createShadowCopy != NULL &&
+ ShadowlDllHandler::getInstance().releaseShadowCopy != NULL;
+}
+
+
+Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile) throw(FreeFileSync::FileError)
+{
+ //check if shadow copy dll was loaded correctly
+ if (!isOkay())
+ throw FileError(Zstring(_("Error copying locked file %x!")).Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")) + wxT("\n\n") +
+ _("Error starting Volume Shadow Copy Service!") + wxT("\n") +
+ _("Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature."));
+
+
+ wchar_t volumeNameRaw[1000];
+
+ if (!GetVolumePathName(inputFile.c_str(), //__in LPCTSTR lpszFileName,
+ volumeNameRaw, //__out LPTSTR lpszVolumePathName,
+ 1000)) //__in DWORD cchBufferLength
+ throw FileError(Zstring(_("Error copying locked file %x!")).Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")) + wxT("\n\n") +
+ _("Could not determine volume name for file:") + wxT("\n\"") + inputFile + wxT("\""));
+
+ Zstring volumeNameFormatted = volumeNameRaw;
+ if (!volumeNameFormatted.EndsWith(FreeFileSync::FILE_NAME_SEPARATOR))
+ volumeNameFormatted += FreeFileSync::FILE_NAME_SEPARATOR;
+
+ if (volumeNameFormatted != realVolumeLast)
+ {
+ //release old shadow copy
+ if (backupHandle != NULL)
+ {
+ ShadowlDllHandler::getInstance().releaseShadowCopy(backupHandle);
+ backupHandle = NULL;
+ }
+ realVolumeLast.clear(); //...if next call fails...
+ shadowVolumeLast.clear(); //...if next call fails...
+
+ //start shadow volume copy service:
+ wchar_t shadowVolName[1000];
+ void* backupHandleTmp = NULL;
+ wchar_t errorMessage[1000];
+
+ if (!ShadowlDllHandler::getInstance().createShadowCopy(
+ volumeNameFormatted.c_str(),
+ shadowVolName,
+ 1000,
+ &backupHandleTmp,
+ errorMessage,
+ 1000))
+ throw FileError(Zstring(_("Error copying locked file %x!")).Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")) + wxT("\n\n") +
+ _("Error starting Volume Shadow Copy Service!") + wxT("\n") +
+ wxT("(") + errorMessage + wxT(")"));
+
+ realVolumeLast = volumeNameFormatted;
+ shadowVolumeLast = Zstring(shadowVolName) + FreeFileSync::FILE_NAME_SEPARATOR; //shadowVolName NEVER has a trailing backslash
+ backupHandle = backupHandleTmp;
+ }
+
+ const size_t pos = inputFile.find(volumeNameFormatted);
+ if (pos == Zstring::npos)
+ {
+ Zstring msg = _("Volume name %x not part of filename %y!");
+ msg.Replace(wxT("%x"), Zstring(wxT("\"")) + volumeNameFormatted + wxT("\""), false);
+ msg.Replace(wxT("%y"), Zstring(wxT("\"")) + inputFile + wxT("\""), false);
+ throw FileError(Zstring(_("Error copying locked file %x!")).Replace(wxT("%x"), Zstring(wxT("\"")) + inputFile + wxT("\"")) + wxT("\n\n") +
+ msg);
+ }
+
+ //return filename alias on shadow copy volume
+ return shadowVolumeLast + Zstring(inputFile.c_str() + pos + volumeNameFormatted.length());
+}
+
+
+
+
+
+
+
+
+
diff --git a/library/shadow.h b/library/shadow.h
new file mode 100644
index 00000000..ded9d746
--- /dev/null
+++ b/library/shadow.h
@@ -0,0 +1,31 @@
+#ifndef SHADOW_H_INCLUDED
+#define SHADOW_H_INCLUDED
+
+#ifndef FFS_WIN
+#warning //this header should be used in the windows build only!
+#endif
+
+#include "zstring.h"
+#include "fileError.h"
+
+
+namespace FreeFileSync
+{
+ class ShadowCopy //buffer access to Windows Volume Shadow Copy Service
+ {
+ public:
+ ShadowCopy();
+ ~ShadowCopy();
+
+ Zstring makeShadowCopy(const Zstring& inputFile) throw(FileError); //returns filename on shadow copy
+
+ private:
+ bool isOkay();
+
+ Zstring realVolumeLast; //buffer last volume name
+ Zstring shadowVolumeLast; //buffer last created shadow volume
+ void* backupHandle;
+ };
+}
+
+#endif // SHADOW_H_INCLUDED
diff --git a/library/statistics.cpp b/library/statistics.cpp
index ec03c59e..f2506da8 100644
--- a/library/statistics.cpp
+++ b/library/statistics.cpp
@@ -5,6 +5,11 @@
#include "statusHandler.h"
#include "../algorithm.h"
#include <limits>
+#include <wx/stopwatch.h>
+
+
+RetrieveStatistics::RetrieveStatistics() :
+ timer(new wxStopWatch) {}
RetrieveStatistics::~RetrieveStatistics()
@@ -30,7 +35,7 @@ void RetrieveStatistics::writeEntry(const double value, const int objects)
statEntry newEntry;
newEntry.value = value;
newEntry.objects = objects;
- newEntry.time = timer.Time();
+ newEntry.time = timer->Time();
data.push_back(newEntry);
}
@@ -102,8 +107,8 @@ Statistics::Statistics(const int totalObjectCount,
windowSizeRemTime(windowSizeRemainingTime),
windowSizeBPS(windowSizeBytesPerSecond),
windowMax(std::max(windowSizeRemainingTime, windowSizeBytesPerSecond)),
- remainingTimeLast(256*256*256*100) //something "big"
-{}
+ remainingTimeLast(256*256*256*100), //something "big"
+ timer(new wxStopWatch) {}
void Statistics::addMeasurement(const int objectsCurrent, const double dataCurrent)
@@ -111,7 +116,7 @@ void Statistics::addMeasurement(const int objectsCurrent, const double dataCurre
record newEntry;
newEntry.objects = objectsCurrent;
newEntry.data = dataCurrent;
- newEntry.time = timer.Time();
+ newEntry.time = timer->Time();
//insert new record
measurements.push_back(newEntry);
@@ -176,13 +181,13 @@ wxString Statistics::getBytesPerSecond() const
void Statistics::pauseTimer()
{
- timer.Pause();
+ timer->Pause();
}
void Statistics::resumeTimer()
{
- timer.Resume();
+ timer->Resume();
}
/*
diff --git a/library/statistics.h b/library/statistics.h
index 3d4179db..f0eafad8 100644
--- a/library/statistics.h
+++ b/library/statistics.h
@@ -2,13 +2,18 @@
#define STATISTICS_H_INCLUDED
#include <vector>
-#include <wx/stopwatch.h>
#include <list>
+#include <memory>
+#include <wx/defs.h>
+
+class wxStopWatch;
+class wxString;
+
class RetrieveStatistics
{
public:
- wxDEPRECATED(RetrieveStatistics() {}) //generate compiler warnings as a reminder to remove code after measurements
+ wxDEPRECATED( RetrieveStatistics() ); //generate compiler warnings as a reminder to remove code after measurements
~RetrieveStatistics();
void writeEntry(const double value, const int objects);
@@ -22,7 +27,7 @@ private:
};
std::vector<statEntry> data;
- wxStopWatch timer;
+ std::auto_ptr<wxStopWatch> timer;
};
@@ -61,7 +66,7 @@ private:
};
std::list<record> measurements;
- wxStopWatch timer;
+ std::auto_ptr<wxStopWatch> timer;
};
#endif // STATISTICS_H_INCLUDED
diff --git a/library/zstring.cpp b/library/zstring.cpp
index ddf1fc73..b26ee451 100644
--- a/library/zstring.cpp
+++ b/library/zstring.cpp
@@ -19,7 +19,7 @@ AllocationCount::~AllocationCount()
}
-AllocationCount& AllocationCount::getGlobal()
+AllocationCount& AllocationCount::getInstance()
{
static AllocationCount global;
return global;
@@ -260,7 +260,7 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t
}
const size_t newLen = oldLen - n1 + n2;
- if (n1 < n2 || descr->refCount > 1)
+ if (newLen > oldLen || descr->refCount > 1)
{ //allocate a new string
StringDescriptor* newDescr;
DefaultChar* newData;
@@ -279,7 +279,7 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t
else //overwrite current string: case "n2 == 0" is handled implicitly
{
memcpy(data + pos1, str, n2 * sizeof(DefaultChar));
- if (n1 > n2)
+ if (newLen < oldLen)
{
memmove(data + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(DefaultChar));
data[newLen] = 0;
diff --git a/library/zstring.h b/library/zstring.h
index 007922d8..bca50862 100644
--- a/library/zstring.h
+++ b/library/zstring.h
@@ -11,7 +11,6 @@
#include <cctype>
#include <assert.h>
#include <new>
-#include <cstdlib>
namespace FreeFileSync
@@ -23,18 +22,10 @@ namespace FreeFileSync
}
-#ifdef FFS_WIN
-#define ZSTRING_WIDE_CHAR //use wide character strings
-
-#elif defined FFS_LINUX
-#define ZSTRING_CHAR //use char strings
-#endif
-
-
#ifdef ZSTRING_CHAR
-typedef char DefaultChar;
+typedef char DefaultChar; //use char strings
#elif defined ZSTRING_WIDE_CHAR
-typedef wchar_t DefaultChar;
+typedef wchar_t DefaultChar; //use wide character strings
#endif
class Zsubstr;
@@ -54,6 +45,7 @@ public:
bool StartsWith(const DefaultChar* begin) const;
bool StartsWith(const Zstring& begin) const;
bool EndsWith(const DefaultChar* end) const;
+ bool EndsWith(const DefaultChar end) const;
bool EndsWith(const Zstring& end) const;
#ifdef FFS_WIN
int CmpNoCase(const DefaultChar* other) const;
@@ -76,6 +68,7 @@ public:
Zstring substr(size_t pos = 0, size_t len = npos) const; //allocate new string
Zsubstr zsubstr(size_t pos = 0) const; //use ref-counting!
bool empty() const;
+ void clear();
int compare(const DefaultChar* other) const;
int compare(const Zstring& other) const;
int compare(const size_t pos1, const size_t n1, const DefaultChar* other) const;
@@ -119,7 +112,7 @@ private:
size_t length;
size_t capacity; //allocated length without null-termination
};
- static void allocate(const size_t newLength, Zstring::StringDescriptor*& newDescr, DefaultChar*& newData);
+ static void allocate(const size_t newLength, StringDescriptor*& newDescr, DefaultChar*& newData);
StringDescriptor* descr;
DefaultChar* data;
@@ -211,13 +204,13 @@ int defaultCompare(const wchar_t* str1, const wchar_t* str2, const size_t count)
}
inline
-wchar_t* defaultStrFind(const wchar_t* str1, const wchar_t* str2)
+const wchar_t* defaultStrFind(const wchar_t* str1, const wchar_t* str2)
{
return wcsstr(str1, str2);
}
inline
-wchar_t* defaultStrFind(const wchar_t* str1, int ch)
+const wchar_t* defaultStrFind(const wchar_t* str1, int ch)
{
return wcschr(str1, ch);
}
@@ -251,7 +244,7 @@ public:
--count;
}
- static AllocationCount& getGlobal();
+ static AllocationCount& getInstance();
private:
AllocationCount() : count(0) {}
@@ -277,17 +270,15 @@ void Zstring::allocate(const size_t newLength,
const size_t newCapacity = getCapacityToAllocate(newLength);
assert(newCapacity);
- newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar));
- if (newDescr == NULL)
- throw std::bad_alloc();
- newData = (DefaultChar*)(newDescr + 1);
+ newDescr = static_cast<StringDescriptor*>(operator new [] (sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar)));
+ newData = reinterpret_cast<DefaultChar*>(newDescr + 1);
newDescr->refCount = 1;
newDescr->length = newLength;
newDescr->capacity = newCapacity;
#ifdef __WXDEBUG__
- AllocationCount::getGlobal().inc(); //test Zstring for memory leaks
+ AllocationCount::getInstance().inc(); //test Zstring for memory leaks
#endif
}
@@ -361,10 +352,10 @@ void Zstring::decRef()
assert(descr && descr->refCount >= 1); //descr points to the begin of the allocated memory block
if (--descr->refCount == 0)
{
- free(descr); //this must NEVER be changed!! E.g. Trim() relies on descr being start of allocated memory block
+ operator delete [] (descr); //this must NEVER be changed!! E.g. Trim() relies on descr being start of allocated memory block
descr = NULL;
#ifdef __WXDEBUG__
- AllocationCount::getGlobal().dec(); //test Zstring for memory leaks
+ AllocationCount::getInstance().dec(); //test Zstring for memory leaks
#endif
}
}
@@ -474,6 +465,16 @@ bool Zstring::EndsWith(const DefaultChar* end) const
inline
+bool Zstring::EndsWith(const DefaultChar end) const
+{
+ const size_t thisLength = length();
+ if (thisLength < 1)
+ return false;
+ return *(c_str() + thisLength - 1) == end;
+}
+
+
+inline
bool Zstring::EndsWith(const Zstring& end) const
{
const size_t thisLength = length();
@@ -611,6 +612,13 @@ bool Zstring::empty() const
inline
+void Zstring::clear()
+{
+ *this = Zstring();
+}
+
+
+inline
DefaultChar Zstring::operator[](const size_t pos) const
{
assert(pos < length());
@@ -690,16 +698,12 @@ bool Zsubstr::StartsWith(const Zstring& begin) const
inline
size_t Zsubstr::findFromEnd(const DefaultChar ch) const
{
- if (length() == 0)
- return Zstring::npos;
-
- size_t pos = length() - 1;
- do //pos points to last char of the string
+ size_t pos = length();
+ while (--pos != static_cast<size_t>(-1))
{
if (m_data[pos] == ch)
return pos;
}
- while (--pos != static_cast<size_t>(-1));
return Zstring::npos;
}
diff --git a/mingwm10.dll b/mingwm10.dll
deleted file mode 100644
index 9e704958..00000000
--- a/mingwm10.dll
+++ /dev/null
Binary files differ
diff --git a/resource.rc b/resource.rc
index efc75705..6699cf44 100644
--- a/resource.rc
+++ b/resource.rc
@@ -1,5 +1,5 @@
#include "wx/msw/wx.rc"
//naming convention to set icon sequence in executable file
-ffsIcon1 ICON DISCARDABLE "library/FreeFileSync.ico"
-ffsIcon2 ICON DISCARDABLE "library/Batch.ico"
+A_PROGRAM_ICON ICON DISCARDABLE "library/FreeFileSync.ico"
+B_BATCH_ICON ICON DISCARDABLE "library/Batch.ico"
diff --git a/structures.cpp b/structures.cpp
index e90ffe58..6744a263 100644
--- a/structures.cpp
+++ b/structures.cpp
@@ -1,8 +1,87 @@
#include "structures.h"
#include "library/fileHandling.h"
+#include <wx/intl.h>
+#include <wx/stdpaths.h>
+#include <wx/filename.h>
using namespace FreeFileSync;
+
+#ifdef FFS_WIN
+const wxChar FreeFileSync::FILE_NAME_SEPARATOR = '\\';
+#elif defined FFS_LINUX
+const wxChar FreeFileSync::FILE_NAME_SEPARATOR = '/';
+#else
+assert(false);
+#endif
+
+//these two global variables are language-dependent => cannot be set constant! See CustomLocale
+const wxChar* FreeFileSync::DECIMAL_POINT = wxEmptyString;
+const wxChar* FreeFileSync::THOUSANDS_SEPARATOR = wxEmptyString;
+
+
+wxString assembleFileForUserData(const wxString fileName)
+{
+ static const bool isPortableVersion = !wxFileExists(wxT("uninstall.exe")); //this check is a bit lame...
+
+ if (isPortableVersion) //use same directory as executable
+ return getInstallationDir() + FILE_NAME_SEPARATOR + fileName;
+ else //usen OS' standard paths
+ {
+ wxString userDirectory = wxStandardPathsBase::Get().GetUserDataDir();
+
+ if (!userDirectory.EndsWith(wxString(FreeFileSync::FILE_NAME_SEPARATOR)))
+ userDirectory += FreeFileSync::FILE_NAME_SEPARATOR;
+
+ if (!wxDirExists(userDirectory))
+ try
+ {
+ FreeFileSync::createDirectory(userDirectory.c_str(), wxEmptyString, false);
+ }
+ catch (FreeFileSync::FileError&)
+ {}
+
+ return userDirectory + fileName;
+ }
+}
+
+
+//save user configuration in OS' standard application folders
+const wxString& FreeFileSync::getLastConfigFile()
+{
+ static wxString instance = assembleFileForUserData(wxT("LastRun.ffs_gui"));
+ return instance;
+}
+
+
+const wxString& FreeFileSync::getGlobalConfigFile()
+{
+ static wxString instance = assembleFileForUserData(wxT("GlobalSettings.xml"));
+ return instance;
+}
+
+
+const wxString& FreeFileSync::getDefaultLogDirectory()
+{
+ static wxString instance = assembleFileForUserData(wxT("Logs"));
+ return instance;
+}
+
+
+const wxString& FreeFileSync::getLastErrorTxtFile()
+{
+ static wxString instance = assembleFileForUserData(wxT("LastError.txt"));
+ return instance;
+}
+
+
+const wxString& FreeFileSync::getInstallationDir()
+{
+ static wxString instance = wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath();
+ return instance;
+}
+
+
MainConfiguration::MainConfiguration() :
compareVar(CMP_BY_TIME_SIZE),
filterIsActive(false), //do not filter by default
@@ -10,3 +89,79 @@ MainConfiguration::MainConfiguration() :
excludeFilter(wxEmptyString), //exclude nothing
useRecycleBin(FreeFileSync::recycleBinExists()) {} //enable if OS supports it; else user will have to activate first and then get an error message
+
+SyncConfiguration::Variant SyncConfiguration::getVariant()
+{
+ if ( exLeftSideOnly == SYNC_DIR_RIGHT &&
+ exRightSideOnly == SYNC_DIR_RIGHT &&
+ leftNewer == SYNC_DIR_RIGHT &&
+ rightNewer == SYNC_DIR_RIGHT &&
+ different == SYNC_DIR_RIGHT)
+ return MIRROR; //one way ->
+
+ else if (exLeftSideOnly == SYNC_DIR_RIGHT &&
+ exRightSideOnly == SYNC_DIR_NONE &&
+ leftNewer == SYNC_DIR_RIGHT &&
+ rightNewer == SYNC_DIR_NONE &&
+ different == SYNC_DIR_NONE)
+ return UPDATE; //Update ->
+
+ else if (exLeftSideOnly == SYNC_DIR_RIGHT &&
+ exRightSideOnly == SYNC_DIR_LEFT &&
+ leftNewer == SYNC_DIR_RIGHT &&
+ rightNewer == SYNC_DIR_LEFT &&
+ different == SYNC_DIR_NONE)
+ return TWOWAY; //two way <->
+ else
+ return CUSTOM; //other
+}
+
+
+wxString SyncConfiguration::getVariantName()
+{
+ switch (getVariant())
+ {
+ case MIRROR:
+ return _("Mirror ->>");
+ case UPDATE:
+ return _("Update ->");
+ case TWOWAY:
+ return _("Two way <->");
+ case CUSTOM:
+ return _("Custom");
+ }
+
+ return _("Error");
+}
+
+
+void SyncConfiguration::setVariant(const Variant var)
+{
+ switch (var)
+ {
+ case MIRROR:
+ exLeftSideOnly = SYNC_DIR_RIGHT;
+ exRightSideOnly = SYNC_DIR_RIGHT;
+ leftNewer = SYNC_DIR_RIGHT;
+ rightNewer = SYNC_DIR_RIGHT;
+ different = SYNC_DIR_RIGHT;
+ break;
+ case UPDATE:
+ exLeftSideOnly = SYNC_DIR_RIGHT;
+ exRightSideOnly = SYNC_DIR_NONE;
+ leftNewer = SYNC_DIR_RIGHT;
+ rightNewer = SYNC_DIR_NONE;
+ different = SYNC_DIR_NONE;
+ break;
+ case TWOWAY:
+ exLeftSideOnly = SYNC_DIR_RIGHT;
+ exRightSideOnly = SYNC_DIR_LEFT;
+ leftNewer = SYNC_DIR_RIGHT;
+ rightNewer = SYNC_DIR_LEFT;
+ different = SYNC_DIR_NONE;
+ break;
+ case CUSTOM:
+ assert(false);
+ break;
+ }
+}
diff --git a/structures.h b/structures.h
index 00efb624..9c53eecd 100644
--- a/structures.h
+++ b/structures.h
@@ -10,6 +10,22 @@
namespace FreeFileSync
{
+//------------------------------------------------------------------------------
+//global variables
+//------------------------------------------------------------------------------
+ extern const wxChar FILE_NAME_SEPARATOR;
+
+ //language dependent global variables: need to be initialized by CustomLocale on program startup and language switch
+ extern const wxChar* DECIMAL_POINT;
+ extern const wxChar* THOUSANDS_SEPARATOR;
+
+ const wxString& getLastConfigFile();
+ const wxString& getGlobalConfigFile();
+ const wxString& getDefaultLogDirectory();
+ const wxString& getLastErrorTxtFile();
+ const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator
+//------------------------------------------------------------------------------
+
enum CompareVariant
{
CMP_BY_CONTENT,
@@ -22,6 +38,7 @@ namespace FreeFileSync
SYNC_DIR_LEFT,
SYNC_DIR_RIGHT,
SYNC_DIR_NONE,
+
SYNC_UNRESOLVED_CONFLICT
};
@@ -49,6 +66,18 @@ namespace FreeFileSync
rightNewer == other.rightNewer &&
different == other.different;
}
+
+ //get/set default configuration variants
+ enum Variant
+ {
+ MIRROR,
+ UPDATE,
+ TWOWAY,
+ CUSTOM
+ };
+ Variant getVariant();
+ wxString getVariantName();
+ void setVariant(const Variant var);
};
@@ -158,6 +187,10 @@ namespace FreeFileSync
direction(defaultDirection),
selectedForSynchronization(selected) {}
+ typedef unsigned int FolderPairNr;
+
+ FolderPairNr folderPairRef;
+
FileDescrLine fileDescrLeft;
FileDescrLine fileDescrRight;
@@ -168,6 +201,17 @@ namespace FreeFileSync
typedef std::vector<FileCompareLine> FileComparison;
+ struct FileComparison2
+ {
+
+ std::vector<FolderPair> directoryPairs; //directoryPairs - cmpLines 1:n
+
+ std::vector<FileCompareLine> cmpLines;
+ };
+
+
+
+
struct FolderCompareLine //support for multiple folder pairs
{
FolderPair syncPair; //directories to be synced (ending with separator)
diff --git a/synchronization.cpp b/synchronization.cpp
index 43bf22a6..0c49c3a1 100644
--- a/synchronization.cpp
+++ b/synchronization.cpp
@@ -9,10 +9,6 @@
#include "library/fileHandling.h"
#include <utility>
-#ifdef FFS_WIN
-#include <wx/msw/wrapwin.h> //includes "windows.h"
-#endif
-
using namespace FreeFileSync;
@@ -31,79 +27,43 @@ bool getBytesToTransfer(const FileCompareLine& fileCmpLine,
conflicts = 0;
dataToProcess = 0;
- //do not add filtered entries
- if (!fileCmpLine.selectedForSynchronization)
- return false;
+ switch (FreeFileSync::getSyncOperation(fileCmpLine.cmpResult, fileCmpLine.selectedForSynchronization, fileCmpLine.direction)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ dataToProcess = fileCmpLine.fileDescrRight.fileSize;
+ objectsToCreate = 1;
+ return true;
+ case SO_CREATE_NEW_RIGHT:
+ dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
+ objectsToCreate = 1;
+ return true;
- switch (fileCmpLine.cmpResult)
- {
- case FILE_LEFT_SIDE_ONLY:
- //get data to process
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //delete file on left
- dataToProcess = 0;
- objectsToDelete = 1;
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
- objectsToCreate = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- assert(false); //conflicts have files on both sides
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_DELETE_LEFT:
+ case SO_DELETE_RIGHT:
+ dataToProcess = 0;
+ objectsToDelete = 1;
+ return true;
- case FILE_RIGHT_SIDE_ONLY:
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //copy from right to left
- dataToProcess = fileCmpLine.fileDescrRight.fileSize;
- objectsToCreate = 1;
- return true;
- case SYNC_DIR_RIGHT: //delete file on right
- dataToProcess = 0;
- objectsToDelete = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- assert(false); //conflicts have files on both sides
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_OVERWRITE_RIGHT:
+ dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
+ objectsToOverwrite = 1;
+ return true;
- case FILE_LEFT_NEWER:
- case FILE_RIGHT_NEWER:
- case FILE_DIFFERENT:
- case FILE_CONFLICT:
- //get data to process
- switch (fileCmpLine.direction)
- {
- case SYNC_DIR_LEFT: //copy from right to left
- dataToProcess = fileCmpLine.fileDescrRight.fileSize;
- objectsToOverwrite = 1;
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- dataToProcess = fileCmpLine.fileDescrLeft.fileSize;
- objectsToOverwrite = 1;
- return true;
- case SYNC_UNRESOLVED_CONFLICT:
- conflicts = 1;
- return true;
- case SYNC_DIR_NONE:
- return false;
- }
+ case SO_OVERWRITE_LEFT:
+ dataToProcess = fileCmpLine.fileDescrRight.fileSize;
+ objectsToOverwrite = 1;
+ return true;
- case FILE_EQUAL:
+ case SO_DO_NOTHING:
return false;
- };
- return true; //dummy
+ case SO_UNRESOLVED_CONFLICT:
+ conflicts = 1;
+ return true;
+ }
+
+ return false; //dummy
}
@@ -253,50 +213,6 @@ bool FreeFileSync::synchronizationNeeded(const FolderComparison& folderCmp)
}
-void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, FolderComparison& folderCmp)
-{
- //do not handle i->selectedForSynchronization in this method! handled in synchronizeFile(), synchronizeFolder()!
-
-
- for (FolderComparison::iterator j = folderCmp.begin(); j != folderCmp.end(); ++j)
- {
- FileComparison& fileCmp = j->fileCmp;
- for (FileComparison::iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
- {
- switch (i->cmpResult)
- {
- case FILE_LEFT_SIDE_ONLY:
- i->direction = config.exLeftSideOnly;
- break;
-
- case FILE_RIGHT_SIDE_ONLY:
- i->direction = config.exRightSideOnly;
- break;
-
- case FILE_RIGHT_NEWER:
- i->direction = config.rightNewer;
- break;
-
- case FILE_LEFT_NEWER:
- i->direction = config.leftNewer;
- break;
-
- case FILE_DIFFERENT:
- i->direction = config.different;
- break;
-
- case FILE_CONFLICT:
- i->direction = SYNC_UNRESOLVED_CONFLICT;
- break;
-
- case FILE_EQUAL:
- i->direction = SYNC_DIR_NONE;
- }
- }
- }
-}
-
-
//test if more then 50% of files will be deleted/overwritten
bool significantDifferenceDetected(const FileComparison& fileCmp)
{
@@ -319,119 +235,188 @@ bool significantDifferenceDetected(const FileComparison& fileCmp)
}
-SyncProcess::SyncProcess(const bool useRecycler,
- const bool copyFileSymLinks,
- const bool traverseDirSymLinks,
- bool& warningSignificantDifference,
- bool& warningNotEnoughDiskSpace,
- bool& warningUnresolvedConflict,
- StatusHandler* handler) :
- m_useRecycleBin(useRecycler),
- m_copyFileSymLinks(copyFileSymLinks),
- m_traverseDirSymLinks(traverseDirSymLinks),
- m_warningSignificantDifference(warningSignificantDifference),
- m_warningNotEnoughDiskSpace(warningNotEnoughDiskSpace),
- m_warningUnresolvedConflict(warningUnresolvedConflict),
- statusUpdater(handler),
- txtCopyingFile(Zstring(_("Copying file %x to %y")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
- txtOverwritingFile(Zstring(_("Copying file %x to %y overwriting target")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
- txtCreatingFolder(Zstring(_("Creating folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)),
- txtDeletingFile(Zstring(_("Deleting file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)),
- txtDeletingFolder(Zstring(_("Deleting folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)) {}
-
-
-inline
-bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const FolderPair& folderPair)
-{ //return false if nothing had to be done
-
- if (!cmpLine.selectedForSynchronization) return false;
-
- Zstring statusText;
- Zstring target;
+SyncOperation FreeFileSync::getSyncOperation( //evaluate comparison result and sync direction
+ const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir)
+{
+ if (!selectedForSynchronization) return SO_DO_NOTHING;
- //synchronize file:
- switch (cmpLine.cmpResult)
+ switch (cmpResult)
{
case FILE_LEFT_SIDE_ONLY:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //delete files on left
- statusText = txtDeletingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_RIGHT: //copy files to right
- target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
-
- statusText = txtCopyingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- copyFileUpdating(cmpLine.fileDescrLeft.fullName, target, cmpLine.fileDescrLeft.fileSize);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_DELETE_LEFT; //delete files on left
+ case SYNC_DIR_RIGHT:
+ return SO_CREATE_NEW_RIGHT; //copy files to right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ assert(false);
}
+ break;
case FILE_RIGHT_SIDE_ONLY:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //copy files to left
- target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
-
- statusText = txtCopyingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- copyFileUpdating(cmpLine.fileDescrRight.fullName, target, cmpLine.fileDescrRight.fileSize);
- return true;
- case SYNC_DIR_RIGHT: //delete files on right
- statusText = txtDeletingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_CREATE_NEW_LEFT; //copy files to left
+ case SYNC_DIR_RIGHT:
+ return SO_DELETE_RIGHT; //delete files on right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ assert(false);
}
+ break;
case FILE_LEFT_NEWER:
case FILE_RIGHT_NEWER:
case FILE_DIFFERENT:
case FILE_CONFLICT:
- switch (cmpLine.direction)
+ switch (syncDir)
{
- case SYNC_DIR_LEFT: //copy from right to left
- statusText = txtOverwritingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), cmpLine.fileDescrLeft.fullName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
- copyFileUpdating(cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fileSize);
- return true;
- case SYNC_DIR_RIGHT: //copy from left to right
- statusText = txtOverwritingFile;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusText.Replace(wxT("%y"), cmpLine.fileDescrRight.fullName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR), false);
- statusUpdater->updateStatusText(statusText);
-
- removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
- copyFileUpdating(cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fileSize);
- return true;
+ case SYNC_DIR_LEFT:
+ return SO_OVERWRITE_LEFT; //copy from right to left
+ case SYNC_DIR_RIGHT:
+ return SO_OVERWRITE_RIGHT; //copy from left to right
case SYNC_DIR_NONE:
+ return SO_DO_NOTHING;
case SYNC_UNRESOLVED_CONFLICT:
- return false;
+ return SO_UNRESOLVED_CONFLICT;
}
+ break;
case FILE_EQUAL:
+ assert(syncDir == SYNC_DIR_NONE);
+ return SO_DO_NOTHING;
+ }
+
+ return SO_DO_NOTHING; //dummy
+}
+
+
+const wxBitmap& FreeFileSync::getSyncOpImage(const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir)
+{
+ switch (getSyncOperation(cmpResult, selectedForSynchronization, syncDir)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ return *GlobalResources::getInstance().bitmapCreateLeftSmall;
+ case SO_CREATE_NEW_RIGHT:
+ return *GlobalResources::getInstance().bitmapCreateRightSmall;
+ case SO_DELETE_LEFT:
+ return *GlobalResources::getInstance().bitmapDeleteLeftSmall;
+ case SO_DELETE_RIGHT:
+ return *GlobalResources::getInstance().bitmapDeleteRightSmall;
+ case SO_OVERWRITE_RIGHT:
+ return *GlobalResources::getInstance().bitmapSyncDirRightSmall;
+ case SO_OVERWRITE_LEFT:
+ return *GlobalResources::getInstance().bitmapSyncDirLeftSmall;
+ case SO_DO_NOTHING:
+ return *GlobalResources::getInstance().bitmapSyncDirNoneSmall;
+ case SO_UNRESOLVED_CONFLICT:
+ return *GlobalResources::getInstance().bitmapConflictSmall;
+ }
+
+ return wxNullBitmap; //dummy
+}
+
+
+SyncProcess::SyncProcess(const bool useRecycler,
+ const bool copyFileSymLinks,
+ const bool traverseDirSymLinks,
+ xmlAccess::WarningMessages& warnings,
+ StatusHandler* handler) :
+ m_useRecycleBin(useRecycler),
+ m_copyFileSymLinks(copyFileSymLinks),
+ m_traverseDirSymLinks(traverseDirSymLinks),
+ m_warnings(warnings),
+#ifdef FFS_WIN
+ shadowCopyHandler(new ShadowCopy),
+#endif
+ statusUpdater(handler),
+ txtCopyingFile(Zstring(_("Copying file %x to %y")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
+ txtOverwritingFile(Zstring(_("Copying file %x to %y overwriting target")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)),
+ txtCreatingFolder(Zstring(_("Creating folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)),
+ txtDeletingFile(useRecycler ? Zstring(_("Moving %x to Recycle Bin")).Replace(wxT("%x"), wxT("\"%x\""), false) :
+ Zstring(_("Deleting file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)),
+ txtDeletingFolder(useRecycler ? Zstring(_("Moving %x to Recycle Bin")).Replace( wxT("%x"), wxT("\"%x\""), false) :
+ Zstring(_("Deleting folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)) {}
+
+
+inline
+bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const FolderPair& folderPair)
+{ //return false if nothing had to be done
+
+ Zstring statusText;
+ Zstring target;
+
+ switch (getSyncOperation(cmpLine.cmpResult, cmpLine.selectedForSynchronization, cmpLine.direction)) //evaluate comparison result and sync direction
+ {
+ case SO_CREATE_NEW_LEFT:
+ target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
+
+ statusText = txtCopyingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ copyFileUpdating(cmpLine.fileDescrRight.fullName, target, cmpLine.fileDescrRight.fileSize);
+ return true;
+
+ case SO_CREATE_NEW_RIGHT:
+ target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
+
+ statusText = txtCopyingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ copyFileUpdating(cmpLine.fileDescrLeft.fullName, target, cmpLine.fileDescrLeft.fileSize);
+ return true;
+
+ case SO_DELETE_LEFT:
+ statusText = txtDeletingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_DELETE_RIGHT:
+ statusText = txtDeletingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_OVERWRITE_RIGHT:
+ statusText = txtOverwritingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), cmpLine.fileDescrRight.fullName.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrRight.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
+ copyFileUpdating(cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fileSize);
+ return true;
+
+ case SO_OVERWRITE_LEFT:
+ statusText = txtOverwritingFile;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusText.Replace(wxT("%y"), cmpLine.fileDescrLeft.fullName.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR), false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeFile(cmpLine.fileDescrLeft.fullName, m_useRecycleBin); //only used if switch activated by user, else file is simply deleted
+ copyFileUpdating(cmpLine.fileDescrRight.fullName, cmpLine.fileDescrLeft.fullName, cmpLine.fileDescrRight.fileSize);
+ return true;
+
+ case SO_DO_NOTHING:
+ case SO_UNRESOLVED_CONFLICT:
return false;
}
@@ -443,76 +428,59 @@ inline
bool SyncProcess::synchronizeFolder(const FileCompareLine& cmpLine, const FolderPair& folderPair)
{ //return false if nothing had to be done
- if (!cmpLine.selectedForSynchronization) return false;
-
Zstring statusText;
Zstring target;
//synchronize folders:
- switch (cmpLine.cmpResult)
+ switch (getSyncOperation(cmpLine.cmpResult, cmpLine.selectedForSynchronization, cmpLine.direction)) //evaluate comparison result and sync direction
{
- case FILE_LEFT_SIDE_ONLY:
- switch (cmpLine.direction)
- {
- case SYNC_DIR_LEFT: //delete folders on left
- statusText = txtDeletingFolder;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeDirectory(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_RIGHT: //create folders on right
- target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
-
- statusText = txtCreatingFolder;
- statusText.Replace(wxT("%x"), target, false);
- statusUpdater->updateStatusText(statusText);
-
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!wxDirExists(cmpLine.fileDescrLeft.fullName))
- throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrLeft.fullName + wxT("\""));
- createDirectory(target, cmpLine.fileDescrLeft.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
- return true;
- case SYNC_DIR_NONE:
- case SYNC_UNRESOLVED_CONFLICT:
- return false;
- }
+ case SO_CREATE_NEW_LEFT:
+ target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
- case FILE_RIGHT_SIDE_ONLY:
- switch (cmpLine.direction)
- {
- case SYNC_DIR_LEFT: //create folders on left
- target = folderPair.leftDirectory + cmpLine.fileDescrRight.relativeName.c_str();
-
- statusText = txtCreatingFolder;
- statusText.Replace(wxT("%x"), target, false);
- statusUpdater->updateStatusText(statusText);
-
- //some check to catch the error that directory on source has been deleted externally after "compare"...
- if (!wxDirExists(cmpLine.fileDescrRight.fullName))
- throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrRight.fullName + wxT("\""));
- createDirectory(target, cmpLine.fileDescrRight.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
- return true;
- case SYNC_DIR_RIGHT: //delete folders on right
- statusText = txtDeletingFolder;
- statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
- statusUpdater->updateStatusText(statusText);
-
- removeDirectory(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
- return true;
- case SYNC_DIR_NONE:
- case SYNC_UNRESOLVED_CONFLICT:
- return false;
- }
+ statusText = txtCreatingFolder;
+ statusText.Replace(wxT("%x"), target, false);
+ statusUpdater->updateStatusText(statusText);
- case FILE_EQUAL:
- return false;
+ //some check to catch the error that directory on source has been deleted externally after "compare"...
+ if (!wxDirExists(cmpLine.fileDescrRight.fullName))
+ throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrRight.fullName + wxT("\""));
+ createDirectory(target, cmpLine.fileDescrRight.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
+ return true;
- case FILE_RIGHT_NEWER:
- case FILE_LEFT_NEWER:
- case FILE_DIFFERENT:
- case FILE_CONFLICT:
- assert (false);
+ case SO_CREATE_NEW_RIGHT:
+ target = folderPair.rightDirectory + cmpLine.fileDescrLeft.relativeName.c_str();
+
+ statusText = txtCreatingFolder;
+ statusText.Replace(wxT("%x"), target, false);
+ statusUpdater->updateStatusText(statusText);
+
+ //some check to catch the error that directory on source has been deleted externally after "compare"...
+ if (!wxDirExists(cmpLine.fileDescrLeft.fullName))
+ throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + cmpLine.fileDescrLeft.fullName + wxT("\""));
+ createDirectory(target, cmpLine.fileDescrLeft.fullName, !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks
+ return true;
+
+ case SO_DELETE_LEFT:
+ statusText = txtDeletingFolder;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeDirectory(cmpLine.fileDescrLeft.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_DELETE_RIGHT:
+ statusText = txtDeletingFolder;
+ statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false);
+ statusUpdater->updateStatusText(statusText);
+
+ removeDirectory(cmpLine.fileDescrRight.fullName, m_useRecycleBin);
+ return true;
+
+ case SO_OVERWRITE_RIGHT:
+ case SO_OVERWRITE_LEFT:
+ case SO_UNRESOLVED_CONFLICT:
+ assert(false);
+ case SO_DO_NOTHING:
return false;
}
@@ -539,7 +507,7 @@ public:
~RemoveAtExit()
{
- removeRowsFromVector(gridToWrite, rowsToDelete);
+ globalFunctions::removeRowsFromVector(rowsToDelete, gridToWrite);
}
void markRow(int nr)
@@ -592,7 +560,7 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
const FileComparison& fileCmp = j->fileCmp;
//check if more than 50% of total number of files/dirs are to be created/overwritten/deleted
- if (m_warningSignificantDifference) //test if check should be executed
+ if (m_warnings.warningSignificantDifference) //test if check should be executed
{
if (significantDifferenceDetected(fileCmp))
{
@@ -601,12 +569,12 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.leftDirectory + wxT(" <-> ") + j->syncPair.rightDirectory + wxT("\n\n") +
_("More than 50% of the total number of files will be copied or deleted!"),
dontShowAgain);
- m_warningSignificantDifference = !dontShowAgain;
+ m_warnings.warningSignificantDifference = !dontShowAgain;
}
}
//check for sufficient free diskspace in left directory
- if (m_warningNotEnoughDiskSpace)
+ if (m_warnings.warningNotEnoughDiskSpace)
{
const std::pair<wxLongLong, wxLongLong> spaceNeeded = freeDiskSpaceNeeded(fileCmp, m_useRecycleBin);
@@ -620,12 +588,12 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.leftDirectory + wxT("\n\n") +
_("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.first).c_str(),
dontShowAgain);
- m_warningNotEnoughDiskSpace = !dontShowAgain;
+ m_warnings.warningNotEnoughDiskSpace = !dontShowAgain;
}
}
//check for sufficient free diskspace in right directory
- if (m_warningNotEnoughDiskSpace)
+ if (m_warnings.warningNotEnoughDiskSpace)
{
wxLongLong freeDiskSpaceRight;
if (wxGetDiskSpace(j->syncPair.rightDirectory.c_str(), NULL, &freeDiskSpaceRight))
@@ -637,7 +605,7 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
j->syncPair.rightDirectory + wxT("\n\n") +
_("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.second).c_str(),
dontShowAgain);
- m_warningNotEnoughDiskSpace = !dontShowAgain;
+ m_warnings.warningNotEnoughDiskSpace = !dontShowAgain;
}
}
}
@@ -645,14 +613,14 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
}
//check if unresolved conflicts exist
- if (m_warningUnresolvedConflict) //test if check should be executed
+ if (m_warnings.warningUnresolvedConflicts) //test if check should be executed
{
if (conflicts > 0)
{
bool dontShowAgain = false;
statusUpdater->reportWarning(_("Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization."),
dontShowAgain);
- m_warningUnresolvedConflict = !dontShowAgain;
+ m_warnings.warningUnresolvedConflicts = !dontShowAgain;
}
}
@@ -787,144 +755,72 @@ void SyncProcess::startSynchronizationProcess(FolderComparison& folderCmp)
//###########################################################################################
//callback functionality for smooth progress indicators
-struct CallBackData
-{
- StatusHandler* handler;
- wxLongLong bytesTransferredLast;
-};
-
-#ifdef FFS_WIN
-const DWORD COPY_FILE_COPY_SYMLINK = 0x00000800;
-
-DWORD CALLBACK copyProcessCallback(
- LARGE_INTEGER totalFileSize,
- LARGE_INTEGER totalBytesTransferred,
- LARGE_INTEGER streamSize,
- LARGE_INTEGER streamBytesTransferred,
- DWORD dwStreamNumber,
- DWORD dwCallbackReason,
- HANDLE hSourceFile,
- HANDLE hDestinationFile,
- LPVOID lpData)
+class WhileCopying : public FreeFileSync::CopyFileCallback //callback functionality
{
- //small performance optimization: it seems this callback function is called for every 64 kB (depending on cluster size).
- static unsigned callNr = 0;
- if (++callNr % 50 == 0) //reduce by factor of 50 =^ 10-20 calls/sec
- {
- CallBackData* sharedData = static_cast<CallBackData*>(lpData);
+public:
- assert(totalBytesTransferred.HighPart >= 0);
+ WhileCopying(wxLongLong& bytesTransferredLast, StatusHandler* statusHandler) :
+ m_bytesTransferredLast(bytesTransferredLast),
+ m_statusHandler(statusHandler) {}
- if (totalBytesTransferred.HighPart < 0) //let's see if someone answers the call...
- wxMessageBox(wxT("You've just discovered a bug in WIN32 API function \"CopyFileEx\"! \n\n\
- Please write a mail to the author of FreeFileSync at zhnmju123@gmx.de and simply state that\n\
- \"totalBytesTransferred.HighPart can be below zero\"!\n\n\
- This will then be handled in future versions of FreeFileSync.\n\nThanks -ZenJu"), wxT("Warning"));
+ virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred)
+ {
+ //convert to signed
+ const wxLongLong totalBytes = globalFunctions::convertToSigned(totalBytesTransferred);
//inform about the (differential) processed amount of data
- const wxLongLong currentBytesTransferred(totalBytesTransferred.HighPart, totalBytesTransferred.LowPart);
- sharedData->handler->updateProcessedData(0, currentBytesTransferred - sharedData->bytesTransferredLast);
- sharedData->bytesTransferredLast = currentBytesTransferred;
-
- sharedData->handler->requestUiRefresh(false); //don't allow throwing exception within this call
-
- if (sharedData->handler->abortIsRequested())
- return PROGRESS_CANCEL;
- }
-
- return PROGRESS_CONTINUE;
-}
+ m_statusHandler->updateProcessedData(0, totalBytes - m_bytesTransferredLast);
+ m_bytesTransferredLast = totalBytes;
+#ifdef FFS_WIN
+ m_statusHandler->requestUiRefresh(false); //don't allow throwing exception within this call
+ if (m_statusHandler->abortIsRequested())
+ return CopyFileCallback::CANCEL;
#elif defined FFS_LINUX
-void copyProcessCallback(const wxULongLong& totalBytesTransferred, void* data)
-{ //called every 512 kB
-
- CallBackData* sharedData = static_cast<CallBackData*>(data);
-
- //convert to unsigned
- const wxLongLong totalBytes = globalFunctions::convertToSigned(totalBytesTransferred);
-
- //inform about the (differential) processed amount of data
- sharedData->handler->updateProcessedData(0, totalBytes - sharedData->bytesTransferredLast);
- sharedData->bytesTransferredLast = totalBytes;
-
- sharedData->handler->requestUiRefresh(); //exceptions may be thrown here!
-}
+ m_statusHandler->requestUiRefresh(); //exceptions may be thrown here!
#endif
+ return CopyFileCallback::CONTINUE;
+ }
+
+private:
+ wxLongLong& m_bytesTransferredLast;
+ StatusHandler* m_statusHandler;
+};
//copy file while executing statusUpdater->requestUiRefresh() calls
void SyncProcess::copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& totalBytesToCpy)
{
//create folders first (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080)
- const Zstring targetDir = target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring targetDir = target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (!wxDirExists(targetDir.c_str()))
{
- const Zstring templateDir = source.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring templateDir = source.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
FreeFileSync::createDirectory(targetDir, templateDir, !m_traverseDirSymLinks); //might throw FileError() exception
}
//start of (possibly) long-running copy process: ensure status updates are performed regularly
-#ifdef FFS_WIN //update via call-back function
-
- CallBackData sharedData;
- sharedData.handler = statusUpdater;
-//data.bytesTransferredLast =
-
-
- DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
-
- if (m_copyFileSymLinks) //copy symbolic links instead of the files pointed at
- copyFlags |= COPY_FILE_COPY_SYMLINK;
-
- if (!CopyFileEx( //same performance as CopyFile()
- source.c_str(),
- target.c_str(),
- copyProcessCallback,
- &sharedData,
- NULL,
- copyFlags))
- {
- //error situation: undo communication of processed amount of data
- statusUpdater->updateProcessedData(0, sharedData.bytesTransferredLast * -1 );
-
- statusUpdater->requestUiRefresh(); //abort if requested, don't show error message if cancelled by user!
-
- Zstring errorMessage = Zstring(_("Error copying file:")) + wxT("\n\"") + source + wxT("\" -> \"") + target + wxT("\"");
- errorMessage += Zstring(wxT("\n\n"));
- errorMessage += FreeFileSync::getLastErrorFormatted(); //some additional windows error information
- throw FileError(errorMessage);
- }
-
- //inform about the (remaining) processed amount of data
- statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - sharedData.bytesTransferredLast);
-
-
-#elif defined FFS_LINUX //update via call-back function
-
- CallBackData sharedData;
- sharedData.handler = statusUpdater;
-//data.bytesTransferredLast =
+ wxLongLong totalBytesTransferred;
+ WhileCopying callback(totalBytesTransferred, statusUpdater);
try
{
- FreeFileSync::copyFile(source,
- target,
- m_copyFileSymLinks,
- copyProcessCallback,
- &sharedData);
+#ifdef FFS_WIN
+ FreeFileSync::copyFile(source, target, m_copyFileSymLinks, shadowCopyHandler.get(), &callback);
+#elif defined FFS_LINUX
+ FreeFileSync::copyFile(source, target, m_copyFileSymLinks, &callback);
+#endif
}
catch (...)
{
//error situation: undo communication of processed amount of data
- statusUpdater->updateProcessedData(0, sharedData.bytesTransferredLast * -1 );
-
+ statusUpdater->updateProcessedData(0, totalBytesTransferred * -1 );
+ statusUpdater->requestUiRefresh(true); //windows build: abort if requested, don't show error message if cancelled by user!
throw;
}
//inform about the (remaining) processed amount of data
- statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - sharedData.bytesTransferredLast);
-#endif
+ statusUpdater->updateProcessedData(0, globalFunctions::convertToSigned(totalBytesToCpy) - totalBytesTransferred);
}
/*
@@ -964,10 +860,10 @@ private:
void copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& totalBytesToCpy, StatusHandler* updateClass)
{
//create folders first (see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080)
- const Zstring targetDir = target.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring targetDir = target.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (!wxDirExists(targetDir.c_str()))
{
- const Zstring templateDir = source.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const Zstring templateDir = source.BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
FreeFileSync::createDirectory(targetDir, templateDir); //might throw FileError() exception
}
diff --git a/synchronization.h b/synchronization.h
index 47052fac..b837812a 100644
--- a/synchronization.h
+++ b/synchronization.h
@@ -2,8 +2,15 @@
#define SYNCHRONIZATION_H_INCLUDED
#include "structures.h"
+#include "library/processXml.h"
+#include <memory>
+
+#ifdef FFS_WIN
+#include "library/shadow.h"
+#endif
class StatusHandler;
+class wxBitmap;
namespace FreeFileSync
@@ -17,7 +24,25 @@ namespace FreeFileSync
bool synchronizationNeeded(const FolderComparison& folderCmp);
- void redetermineSyncDirection(const SyncConfiguration& config, FolderComparison& folderCmp);
+
+ enum SyncOperation
+ {
+ SO_CREATE_NEW_LEFT,
+ SO_CREATE_NEW_RIGHT,
+ SO_DELETE_LEFT,
+ SO_DELETE_RIGHT,
+ SO_OVERWRITE_RIGHT,
+ SO_OVERWRITE_LEFT,
+ SO_DO_NOTHING,
+ SO_UNRESOLVED_CONFLICT
+ };
+ SyncOperation getSyncOperation(const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir); //evaluate comparison result and sync direction
+
+ const wxBitmap& getSyncOpImage(const CompareFilesResult cmpResult,
+ const bool selectedForSynchronization,
+ const SyncDirection syncDir);
//class handling synchronization process
class SyncProcess
@@ -26,9 +51,7 @@ namespace FreeFileSync
SyncProcess(const bool useRecycler,
const bool copyFileSymLinks,
const bool traverseDirSymLinks,
- bool& warningSignificantDifference,
- bool& warningNotEnoughDiskSpace,
- bool& warningUnresolvedConflict,
+ xmlAccess::WarningMessages& warnings,
StatusHandler* handler);
void startSynchronizationProcess(FolderComparison& folderCmp);
@@ -44,9 +67,12 @@ namespace FreeFileSync
const bool m_traverseDirSymLinks;
//warnings
- bool& m_warningSignificantDifference;
- bool& m_warningNotEnoughDiskSpace;
- bool& m_warningUnresolvedConflict;
+ xmlAccess::WarningMessages& m_warnings;
+
+#ifdef FFS_WIN
+ //shadow copy buffer
+ std::auto_ptr<ShadowCopy> shadowCopyHandler;
+#endif
StatusHandler* statusUpdater;
diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp
index 32a1e124..e9119fea 100644
--- a/ui/MainDialog.cpp
+++ b/ui/MainDialog.cpp
@@ -19,6 +19,7 @@
#include "dragAndDrop.h"
#include "../library/filter.h"
#include "../structures.h"
+#include <wx/imaglist.h>
using namespace FreeFileSync;
@@ -136,56 +137,65 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale
cleanedUp(false),
lastSortColumn(-1),
lastSortGrid(NULL),
+#ifdef FFS_WIN
+ updateFileIcons(new IconUpdater(m_gridLeft, m_gridRight)),
+#endif
syncPreview(new SyncPreview(this))
{
+ m_bpButtonRemoveTopPair->Hide();
+
+
//initialize and load configuration
readGlobalSettings();
readConfigurationFromXml(cfgFileName, true);
//set icons for this dialog
- m_bpButton10->SetBitmapLabel(*globalResource.bitmapExit);
- m_buttonCompare->setBitmapFront(*globalResource.bitmapCompare);
- m_bpButtonSyncConfig->SetBitmapLabel(*globalResource.bitmapSyncCfg);
- m_bpButton14->SetBitmapLabel(*globalResource.bitmapHelp);
- m_bpButtonSave->SetBitmapLabel(*globalResource.bitmapSave);
- m_bpButtonLoad->SetBitmapLabel(*globalResource.bitmapLoad);
- m_bpButtonAddPair->SetBitmapLabel(*globalResource.bitmapAddFolderPair);
- m_bitmap15->SetBitmap(*globalResource.bitmapStatusEdge);
- m_bitmapShift->SetBitmap(*globalResource.bitmapShift);
- m_bitmapCreate->SetBitmap(*globalResource.bitmapCreate);
- m_bitmapUpdate->SetBitmap(*globalResource.bitmapUpdate);
- m_bitmapDelete->SetBitmap(*globalResource.bitmapDelete);
- m_bitmapData->SetBitmap(*globalResource.bitmapData);
+ m_bpButton10->SetBitmapLabel(*GlobalResources::getInstance().bitmapExit);
+ m_bpButtonSwapSides->SetBitmapLabel(*GlobalResources::getInstance().bitmapSwap);
+ m_buttonCompare->setBitmapFront(*GlobalResources::getInstance().bitmapCompare);
+ m_bpButtonSyncConfig->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCfg);
+ m_bpButton14->SetBitmapLabel(*GlobalResources::getInstance().bitmapHelp);
+ m_bpButtonSave->SetBitmapLabel(*GlobalResources::getInstance().bitmapSave);
+ m_bpButtonLoad->SetBitmapLabel(*GlobalResources::getInstance().bitmapLoad);
+ m_bpButtonAddPair->SetBitmapLabel(*GlobalResources::getInstance().bitmapAddFolderPair);
+ m_bpButtonRemoveTopPair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
+ m_bitmap15->SetBitmap(*GlobalResources::getInstance().bitmapStatusEdge);
+ m_bitmapShift->SetBitmap(*GlobalResources::getInstance().bitmapShift);
+
+ m_bitmapCreate->SetBitmap(*GlobalResources::getInstance().bitmapCreate);
+ m_bitmapUpdate->SetBitmap(*GlobalResources::getInstance().bitmapUpdate);
+ m_bitmapDelete->SetBitmap(*GlobalResources::getInstance().bitmapDelete);
+ m_bitmapData->SetBitmap(*GlobalResources::getInstance().bitmapData);
bSizer6->Layout(); //wxButtonWithImage size might have changed
//menu icons: workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build)
MenuItemUpdater updateMenuFile(m_menuFile);
- updateMenuFile.addForUpdate(m_menuItem10, *globalResource.bitmapCompareSmall);
- updateMenuFile.addForUpdate(m_menuItem11, *globalResource.bitmapSyncSmall);
- updateMenuFile.addForUpdate(m_menuItemSwitchView, *globalResource.bitmapSwitchViewSmall);
+ updateMenuFile.addForUpdate(m_menuItem10, *GlobalResources::getInstance().bitmapCompareSmall);
+ updateMenuFile.addForUpdate(m_menuItem11, *GlobalResources::getInstance().bitmapSyncSmall);
MenuItemUpdater updateMenuAdv(m_menuAdvanced);
- updateMenuAdv.addForUpdate(m_menuItemGlobSett, *globalResource.bitmapSettingsSmall);
- updateMenuAdv.addForUpdate(m_menuItem7, *globalResource.bitmapBatchSmall);
+ updateMenuAdv.addForUpdate(m_menuItemGlobSett, *GlobalResources::getInstance().bitmapSettingsSmall);
+ updateMenuAdv.addForUpdate(m_menuItem7, *GlobalResources::getInstance().bitmapBatchSmall);
MenuItemUpdater updateMenuHelp(m_menuHelp);
- updateMenuHelp.addForUpdate(m_menuItemAbout, *globalResource.bitmapAboutSmall);
-
- MenuItemUpdater updateMenuAdvLang(m_menuLanguages);
- updateMenuAdvLang.addForUpdate(m_menuItemGerman, *globalResource.bitmapGermany);
- updateMenuAdvLang.addForUpdate(m_menuItemEnglish, *globalResource.bitmapEngland);
- updateMenuAdvLang.addForUpdate(m_menuItemSpanish, *globalResource.bitmapSpain);
- updateMenuAdvLang.addForUpdate(m_menuItemFrench, *globalResource.bitmapFrance);
- updateMenuAdvLang.addForUpdate(m_menuItemItalian, *globalResource.bitmapItaly);
- updateMenuAdvLang.addForUpdate(m_menuItemHungarian, *globalResource.bitmapHungary);
- updateMenuAdvLang.addForUpdate(m_menuItemDutch, *globalResource.bitmapHolland);
- updateMenuAdvLang.addForUpdate(m_menuItemPolish, *globalResource.bitmapPoland);
- updateMenuAdvLang.addForUpdate(m_menuItemPortuguese, *globalResource.bitmapPortugal);
- updateMenuAdvLang.addForUpdate(m_menuItemPortugueseBrazil, *globalResource.bitmapBrazil);
- updateMenuAdvLang.addForUpdate(m_menuItemSlovenian, *globalResource.bitmapSlovakia);
- updateMenuAdvLang.addForUpdate(m_menuItemJapanese, *globalResource.bitmapJapan);
- updateMenuAdvLang.addForUpdate(m_menuItemChineseSimple, *globalResource.bitmapChina);
+ updateMenuHelp.addForUpdate(m_menuItemAbout, *GlobalResources::getInstance().bitmapAboutSmall);
+
+
+ //create language selection menu
+ for (std::vector<LocInfoLine>::const_iterator i = LocalizationInfo::getMapping().begin(); i != LocalizationInfo::getMapping().end(); ++i)
+ {
+ wxMenuItem* newItem = new wxMenuItem(m_menuLanguages, wxID_ANY, i->languageName, wxEmptyString, wxITEM_NORMAL );
+ newItem->SetBitmap(*i->languageFlag);
+
+ //map menu item IDs with language IDs: evaluated when processing event handler
+ languageMenuItemMap.insert(std::map<MenuItemID, LanguageID>::value_type(newItem->GetId(), i->languageID));
+
+ //connect event
+ Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnMenuLanguageSwitch));
+
+ m_menuLanguages->Append(newItem);
+ }
//prepare drag & drop
@@ -217,22 +227,9 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale
m_gridMiddle->Connect(FFS_SYNC_DIRECTION_EVENT, FFSSyncDirectionEventHandler(MainDialog::OnSetSyncDirection), NULL, this);
//init grid settings
- m_gridLeft->initSettings( globalSettings.gui.showFileIcons,
- m_gridLeft,
- m_gridRight,
- m_gridMiddle,
- &gridDataView);
-
- m_gridMiddle->initSettings(m_gridLeft,
- m_gridRight,
- m_gridMiddle,
- &gridDataView);
-
- m_gridRight->initSettings( globalSettings.gui.showFileIcons,
- m_gridLeft,
- m_gridRight,
- m_gridMiddle,
- &gridDataView);
+ m_gridLeft ->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, &gridDataView);
+ m_gridMiddle->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, &gridDataView);
+ m_gridRight ->initSettings(m_gridLeft, m_gridMiddle, m_gridRight, &gridDataView);
//disable sync button as long as "compare" hasn't been triggered.
syncPreview->enableSynchronization(false);
@@ -255,6 +252,9 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale
//register regular check for update on next idle event
Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), NULL, this);
+
+ //asynchronous call to wxWindow::Layout(): fix superfluous frame on right and bottom when FFS is started in fullscreen mode
+ Connect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), NULL, this);
}
@@ -273,7 +273,7 @@ void MainDialog::cleanUp()
//no need for event Disconnect() here; done automatically
//save configuration
- writeConfigurationToXml(xmlAccess::LAST_CONFIG_FILE); //don't trow exceptions in destructors
+ writeConfigurationToXml(FreeFileSync::getLastConfigFile()); //don't trow exceptions in destructors
writeGlobalSettings();
}
}
@@ -315,6 +315,15 @@ void MainDialog::readGlobalSettings()
i != globalSettings.gui.folderHistoryRight.rend();
++i)
addRightFolderToHistory(*i);
+
+ //show/hide file icons
+#ifdef FFS_WIN
+ m_gridLeft->enableFileIcons(globalSettings.gui.showFileIconsLeft);
+ m_gridRight->enableFileIcons(globalSettings.gui.showFileIconsRight);
+#endif
+
+ //set selected tab
+ m_notebookBottomLeft->ChangeSelection(globalSettings.gui.selectedTabBottomLeft);
}
@@ -344,6 +353,24 @@ void MainDialog::writeGlobalSettings()
const wxArrayString rightFolderHistory = m_directoryRight->GetStrings();
for (unsigned i = 0; i < rightFolderHistory.GetCount(); ++i)
globalSettings.gui.folderHistoryRight.push_back(rightFolderHistory[i]);
+
+ //get selected tab
+ globalSettings.gui.selectedTabBottomLeft = m_notebookBottomLeft->GetSelection();
+}
+
+
+void MainDialog::setSyncDirManually(const std::set<int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir)
+{
+ if (rowsToSetOnUiTable.size() > 0)
+ {
+ for (std::set<int>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i)
+ {
+ gridDataView[*i].direction = dir;
+ gridDataView[*i].selectedForSynchronization = true;
+ }
+
+ updateGuiGrid();
+ }
}
@@ -372,7 +399,7 @@ void MainDialog::filterRangeManually(const std::set<int>& rowsToFilterOnUiTable,
const std::set<int>& markedRows = compRef[i - currentGridData.begin()];
std::set<int> markedRowsTotal; //retrieve additional rows that need to be filtered, too
- for (std::set<int>::iterator i = markedRows.begin(); i != markedRows.end(); ++i)
+ for (std::set<int>::const_iterator i = markedRows.begin(); i != markedRows.end(); ++i)
{
markedRowsTotal.insert(*i);
FreeFileSync::addSubElements(fileCmp, fileCmp[*i], markedRowsTotal);
@@ -383,22 +410,7 @@ void MainDialog::filterRangeManually(const std::set<int>& rowsToFilterOnUiTable,
fileCmp[*i].selectedForSynchronization = newSelection;
}
- //signal UI that grids need to be refreshed on next Update()
- m_gridLeft->ForceRefresh();
- m_gridMiddle->ForceRefresh();
- m_gridRight->ForceRefresh();
- Update(); //show changes resulting from ForceRefresh()
-
- if (hideFilteredElements)
- {
- wxMilliSleep(400); //some delay to show user the rows he has filtered out before they are removed
- updateGuiGrid(); //redraw grid to remove excluded elements (keeping sort sequence)
-
- m_gridLeft->ClearSelection();
- m_gridRight->ClearSelection();
- }
- else
- updateGuiGrid();
+ refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
}
}
@@ -430,7 +442,7 @@ void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid)
{
wxString clipboardString;
- for (std::set<int>::iterator i = selectedRows.begin(); i != selectedRows.end(); ++i)
+ for (std::set<int>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i)
{
for (int k = 0; k < const_cast<CustomGrid*>(selectedGrid)->GetNumberCols(); ++k)
{
@@ -478,6 +490,18 @@ std::set<int> MainDialog::getSelectedRows(const CustomGrid* grid) const
}
+std::set<int> MainDialog::getSelectedRows() const
+{
+ //merge selections from left and right grid
+ std::set<int> selection = getSelectedRows(m_gridLeft);
+ std::set<int> additional = getSelectedRows(m_gridRight);
+ for (std::set<int>::const_iterator i = additional.begin(); i != additional.end(); ++i)
+ selection.insert(*i);
+
+ return selection;
+}
+
+
class DeleteErrorHandler : public ErrorHandler
{
public:
@@ -603,7 +627,7 @@ void MainDialog::openWithFileManager(const int rowNumber, const bool leftSide)
case FileDescrLine::TYPE_FILE:
command = globalSettings.gui.commandLineFileManager;
command.Replace(wxT("%name"), fileDescr->fullName.c_str());
- command.Replace(wxT("%path"), wxString(fileDescr->fullName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR));
+ command.Replace(wxT("%path"), wxString(fileDescr->fullName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR));
break;
case FileDescrLine::TYPE_DIRECTORY:
command = globalSettings.gui.commandLineFileManager;
@@ -625,7 +649,7 @@ void MainDialog::openWithFileManager(const int rowNumber, const bool leftSide)
switch (fileDescrOther->objType)
{
case FileDescrLine::TYPE_FILE:
- alternateFolder = syncFolder + wxString(fileDescrOther->relativeName.c_str()).BeforeLast(GlobalResources::FILE_NAME_SEPARATOR);
+ alternateFolder = syncFolder + wxString(fileDescrOther->relativeName.c_str()).BeforeLast(FreeFileSync::FILE_NAME_SEPARATOR);
break;
case FileDescrLine::TYPE_DIRECTORY:
alternateFolder = syncFolder + wxString(fileDescrOther->relativeName.c_str());
@@ -763,30 +787,79 @@ void MainDialog::onGridRightButtonEvent(wxKeyEvent& event)
}
-void MainDialog::OnContextMenu(wxGridEvent& event)
+void MainDialog::OnContextRim(wxGridEvent& event)
{
- std::set<int> selectionLeft = getSelectedRows(m_gridLeft);
- std::set<int> selectionRight = getSelectedRows(m_gridRight);
+ //usability: select row unter right-click if not already selected
+ wxGrid* sourceGrid = dynamic_cast<wxGrid*>(event.GetEventObject());
+ if (sourceGrid != NULL)
+ {
+ const int clickedRow = event.GetRow();
+ const int clickedCol = event.GetCol();
+ if (clickedRow >= 0 && clickedCol >= 0 && !sourceGrid->IsInSelection(clickedRow, 0))
+ {
+ sourceGrid->SelectRow(clickedRow);
+ sourceGrid->SetGridCursor(clickedRow, clickedCol);
+
+ if (sourceGrid == m_gridLeft)
+ m_gridRight->ClearSelection();
+ else if (sourceGrid == m_gridRight)
+ m_gridLeft->ClearSelection();
+ }
+ }
+//------------------------------------------------------------------------------
+
+
+ const std::set<int> selectionLeft = getSelectedRows(m_gridLeft);
+ const std::set<int> selectionRight = getSelectedRows(m_gridRight);
+
+ const int selectionBegin = selectionLeft.size() + selectionRight.size() == 0 ? 0 :
+ selectionLeft.size() == 0 ? *selectionRight.begin() :
+ selectionRight.size() == 0 ? *selectionLeft.begin() :
+ std::min(*selectionLeft.begin(), *selectionRight.begin());
//#######################################################
//re-create context menu
contextMenu.reset(new wxMenu);
+ if (syncPreview->previewIsEnabled())
+ {
+ if (selectionLeft.size() + selectionRight.size() > 0)
+ {
+ //CONTEXT_SYNC_DIR_LEFT
+ wxMenuItem* menuItemSyncDirLeft = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_LEFT, _("Change direction"));
+ menuItemSyncDirLeft->SetBitmap(getSyncOpImage(gridDataView[selectionBegin].cmpResult, true, SYNC_DIR_LEFT));
+ contextMenu->Append(menuItemSyncDirLeft);
+
+ //CONTEXT_SYNC_DIR_NONE
+ wxMenuItem* menuItemSyncDirNone = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_NONE, _("Change direction"));
+ menuItemSyncDirNone->SetBitmap(getSyncOpImage(gridDataView[selectionBegin].cmpResult, true, SYNC_DIR_NONE));
+ contextMenu->Append(menuItemSyncDirNone);
+
+ //CONTEXT_SYNC_DIR_RIGHT
+ wxMenuItem* menuItemSyncDirRight = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_RIGHT, _("Change direction"));
+ menuItemSyncDirRight->SetBitmap(getSyncOpImage(gridDataView[selectionBegin].cmpResult, true, SYNC_DIR_RIGHT));
+ contextMenu->Append(menuItemSyncDirRight);
+
+ contextMenu->AppendSeparator();
+ }
+ }
+
+
//CONTEXT_FILTER_TEMP
if (selectionLeft.size() + selectionRight.size() > 0)
{
- int selectionBegin = 0;
- if (!selectionLeft.size())
- selectionBegin = *selectionRight.begin();
- else if (!selectionRight.size())
- selectionBegin = *selectionLeft.begin();
- else
- selectionBegin = std::min(*selectionLeft.begin(), *selectionRight.begin());
-
if (gridDataView[selectionBegin].selectedForSynchronization) //valid access, as getSelectedRows returns valid references only
- contextMenu->Append(CONTEXT_FILTER_TEMP, _("Exclude temporarily"));
+ {
+ wxMenuItem* menuItemExclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, _("Exclude temporarily"));
+ menuItemExclTemp->SetBitmap(*GlobalResources::getInstance().bitmapCheckBoxFalse);
+ contextMenu->Append(menuItemExclTemp);
+ }
else
- contextMenu->Append(CONTEXT_FILTER_TEMP, _("Include temporarily"));
+ {
+ wxMenuItem* menuItemInclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, _("Include temporarily"));
+ menuItemInclTemp->SetBitmap(*GlobalResources::getInstance().bitmapCheckBoxTrue);
+ contextMenu->Append(menuItemInclTemp);
+ }
}
else
{
@@ -798,7 +871,7 @@ void MainDialog::OnContextMenu(wxGridEvent& event)
//get list of relative file/dir-names for filtering
exFilterCandidateObj.clear();
FilterObject newFilterEntry;
- for (std::set<int>::iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i)
+ for (std::set<int>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i)
{
const FileCompareLine& line = gridDataView[*i];
newFilterEntry.relativeName = line.fileDescrLeft.relativeName.c_str();
@@ -806,7 +879,7 @@ void MainDialog::OnContextMenu(wxGridEvent& event)
if (!newFilterEntry.relativeName.IsEmpty())
exFilterCandidateObj.push_back(newFilterEntry);
}
- for (std::set<int>::iterator i = selectionRight.begin(); i != selectionRight.end(); ++i)
+ for (std::set<int>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i)
{
const FileCompareLine& line = gridDataView[*i];
newFilterEntry.relativeName = line.fileDescrRight.relativeName.c_str();
@@ -820,20 +893,32 @@ void MainDialog::OnContextMenu(wxGridEvent& event)
exFilterCandidateExtension.clear();
if (exFilterCandidateObj.size() > 0 && exFilterCandidateObj[0].type == FileDescrLine::TYPE_FILE)
{
- const wxString filename = exFilterCandidateObj[0].relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR);
+ const wxString filename = exFilterCandidateObj[0].relativeName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR);
if (filename.Find(wxChar('.')) != wxNOT_FOUND) //be careful: AfterLast will return the whole string if '.' is not found!
{
exFilterCandidateExtension = filename.AfterLast(wxChar('.'));
- contextMenu->Append(CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + exFilterCandidateExtension);
+
+ //add context menu item
+ wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + exFilterCandidateExtension);
+ menuItemExclExt->SetBitmap(*GlobalResources::getInstance().bitmapFilterSmall);
+ contextMenu->Append(menuItemExclExt);
}
}
//CONTEXT_EXCLUDE_OBJ
+ wxMenuItem* menuItemExclObj = NULL;
if (exFilterCandidateObj.size() == 1)
- contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + exFilterCandidateObj[0].relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR));
+ menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + exFilterCandidateObj[0].relativeName.AfterLast(FreeFileSync::FILE_NAME_SEPARATOR));
else if (exFilterCandidateObj.size() > 1)
- contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>"));
+ menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>"));
+
+ if (menuItemExclObj != NULL)
+ {
+ menuItemExclObj->SetBitmap(*GlobalResources::getInstance().bitmapFilterSmall);
+ contextMenu->Append(menuItemExclObj);
+ }
+
contextMenu->AppendSeparator();
@@ -869,30 +954,51 @@ void MainDialog::OnContextMenu(wxGridEvent& event)
//###############################################################################################
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMenuSelection), NULL, this);
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimSelection), NULL, this);
//show context menu
PopupMenu(contextMenu.get());
}
-void MainDialog::OnContextMenuSelection(wxCommandEvent& event)
+void MainDialog::OnContextRimSelection(wxCommandEvent& event)
{
- int eventId = event.GetId();
- if (eventId == CONTEXT_FILTER_TEMP)
+ const ContextIDRim eventId = static_cast<ContextIDRim>(event.GetId());
+ switch (eventId)
+ {
+ case CONTEXT_SYNC_DIR_LEFT:
{
//merge selections from left and right grid
- std::set<int> selection = getSelectedRows(m_gridLeft);
- std::set<int> additional = getSelectedRows(m_gridRight);
- for (std::set<int>::const_iterator i = additional.begin(); i != additional.end(); ++i)
- selection.insert(*i);
+ const std::set<int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_LEFT);
+ }
+ break;
- if (selection.size() > 0)
- filterRangeManually(selection, *selection.begin());
+ case CONTEXT_SYNC_DIR_NONE:
+ {
+ //merge selections from left and right grid
+ const std::set<int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_NONE);
}
+ break;
- else if (eventId == CONTEXT_EXCLUDE_EXT)
+ case CONTEXT_SYNC_DIR_RIGHT:
{
+ //merge selections from left and right grid
+ const std::set<int> selection = getSelectedRows();
+ setSyncDirManually(selection, FreeFileSync::SYNC_DIR_RIGHT);
+ }
+ break;
+
+ case CONTEXT_FILTER_TEMP:
+ {
+ //merge selections from left and right grid
+ std::set<int> selection = getSelectedRows();
+ filterRangeManually(selection, *selection.begin());
+ }
+ break;
+
+ case CONTEXT_EXCLUDE_EXT:
if (!exFilterCandidateExtension.IsEmpty())
{
if (!cfg.excludeFilter.IsEmpty() && !cfg.excludeFilter.EndsWith(wxT(";")))
@@ -914,10 +1020,9 @@ void MainDialog::OnContextMenuSelection(wxCommandEvent& event)
m_gridMiddle->ClearSelection();
}
}
- }
+ break;
- else if (eventId == CONTEXT_EXCLUDE_OBJ)
- {
+ case CONTEXT_EXCLUDE_OBJ:
if (exFilterCandidateObj.size() > 0) //check needed to determine if filtering is needed
{
for (std::vector<FilterObject>::const_iterator i = exFilterCandidateObj.begin(); i != exFilterCandidateObj.end(); ++i)
@@ -926,9 +1031,9 @@ void MainDialog::OnContextMenuSelection(wxCommandEvent& event)
cfg.excludeFilter+= wxT("\n");
if (i->type == FileDescrLine::TYPE_FILE)
- cfg.excludeFilter+= wxString(GlobalResources::FILE_NAME_SEPARATOR) + i->relativeName;
+ cfg.excludeFilter+= wxString(FreeFileSync::FILE_NAME_SEPARATOR) + i->relativeName;
else if (i->type == FileDescrLine::TYPE_DIRECTORY)
- cfg.excludeFilter+= wxString(GlobalResources::FILE_NAME_SEPARATOR) + i->relativeName + GlobalResources::FILE_NAME_SEPARATOR + wxT("*");
+ cfg.excludeFilter+= wxString(FreeFileSync::FILE_NAME_SEPARATOR) + i->relativeName + FreeFileSync::FILE_NAME_SEPARATOR + wxT("*");
else assert(false);
}
@@ -946,18 +1051,16 @@ void MainDialog::OnContextMenuSelection(wxCommandEvent& event)
m_gridMiddle->ClearSelection();
}
}
- }
+ break;
- else if (eventId == CONTEXT_CLIPBOARD)
- {
+ case CONTEXT_CLIPBOARD:
if (m_gridLeft->isLeadGrid())
copySelectionToClipboard(m_gridLeft);
else if (m_gridRight->isLeadGrid())
copySelectionToClipboard(m_gridRight);
- }
+ break;
- else if (eventId == CONTEXT_EXPLORER)
- {
+ case CONTEXT_EXPLORER:
if (m_gridLeft->isLeadGrid() || m_gridRight->isLeadGrid())
{
const CustomGrid* leadGrid = NULL;
@@ -973,20 +1076,80 @@ void MainDialog::OnContextMenuSelection(wxCommandEvent& event)
else if (selection.size() == 0)
openWithFileManager(-1, m_gridLeft->isLeadGrid());
}
+ break;
+
+ case CONTEXT_DELETE_FILES:
+ deleteSelectedFiles();
+ break;
}
+}
+
+
+void MainDialog::OnContextRimLabelLeft(wxGridEvent& event)
+{
+ contextMenu.reset(new wxMenu); //re-create context menu
+ contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_LEFT, _("Customize columns"));
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimLabelSelection), NULL, this);
+ PopupMenu(contextMenu.get()); //show context menu
+}
- else if (eventId == CONTEXT_DELETE_FILES)
+
+void MainDialog::OnContextRimLabelRight(wxGridEvent& event)
+{
+ contextMenu.reset(new wxMenu); //re-create context menu
+ contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_RIGHT, _("Customize columns"));
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextRimLabelSelection), NULL, this);
+ PopupMenu(contextMenu.get()); //show context menu
+}
+
+
+void MainDialog::OnContextRimLabelSelection(wxCommandEvent& event)
+{
+ const ContextIDRimLabel eventId = static_cast<ContextIDRimLabel>(event.GetId());
+ switch (eventId)
{
- deleteSelectedFiles();
+ case CONTEXT_CUSTOMIZE_COLUMN_LEFT:
+ {
+ xmlAccess::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes();
+ CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsLeft);
+ if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
+ {
+ m_gridLeft->setColumnAttributes(colAttr);
+#ifdef FFS_WIN
+ m_gridLeft->enableFileIcons(globalSettings.gui.showFileIconsLeft);
+#endif
+
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING)); //hide sort direction indicator on GUI grids
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ }
+ }
+ break;
+ case CONTEXT_CUSTOMIZE_COLUMN_RIGHT:
+ {
+ xmlAccess::ColumnAttributes colAttr = m_gridRight->getColumnAttributes();
+ CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIconsRight);
+ if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
+ {
+ m_gridRight->setColumnAttributes(colAttr);
+#ifdef FFS_WIN
+ m_gridRight->enableFileIcons(globalSettings.gui.showFileIconsRight);
+#endif
+
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING)); //hide sort direction indicator on GUI grids
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ }
+ }
+ break;
}
}
-void MainDialog::OnContextMenuMiddle(wxGridEvent& event)
+void MainDialog::OnContextMiddle(wxGridEvent& event)
{
contextMenu.reset(new wxMenu); //re-create context menu
- contextMenu->Append(CONTEXT_SWAP_SIDES, _("Swap sides"));
- contextMenu->AppendSeparator();
+
contextMenu->Append(CONTEXT_CHECK_ALL, _("Check all"));
contextMenu->Append(CONTEXT_UNCHECK_ALL, _("Uncheck all"));
@@ -996,86 +1159,61 @@ void MainDialog::OnContextMenuMiddle(wxGridEvent& event)
contextMenu->Enable(CONTEXT_UNCHECK_ALL, false);
}
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMenuMiddleSelection), NULL, this);
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMiddleSelection), NULL, this);
PopupMenu(contextMenu.get()); //show context menu
}
-void MainDialog::OnContextMenuMiddleSelection(wxCommandEvent& event)
+void MainDialog::OnContextMiddleSelection(wxCommandEvent& event)
{
- int eventId = event.GetId();
- if (eventId == CONTEXT_SWAP_SIDES)
- {
- wxCommandEvent dummy;
- MainDialog::OnSwapSides(dummy);
- }
- else if (eventId == CONTEXT_CHECK_ALL)
+ const ContextIDMiddle eventId = static_cast<ContextIDMiddle>(event.GetId());
+ switch (eventId)
{
+ case CONTEXT_CHECK_ALL:
FreeFileSync::FilterProcess::includeAllRowsOnGrid(currentGridData);
- updateGuiGrid();
- }
- else if (eventId == CONTEXT_UNCHECK_ALL)
- {
+ refreshGridAfterFilterChange(0); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts break;
+ break;
+ case CONTEXT_UNCHECK_ALL:
FreeFileSync::FilterProcess::excludeAllRowsOnGrid(currentGridData);
- updateGuiGrid();
+ refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
+ break;
}
}
-void MainDialog::OnContextColumnLeft(wxGridEvent& event)
+void MainDialog::OnContextMiddleLabel(wxGridEvent& event)
{
contextMenu.reset(new wxMenu); //re-create context menu
- contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_LEFT, _("Customize columns"));
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextColumnSelection), NULL, this);
- PopupMenu(contextMenu.get()); //show context menu
- event.Skip();
-}
+ wxMenuItem* itemSyncPreview = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_PREVIEW, _("Synchronization Preview"));
+ wxMenuItem* itemCmpResult = new wxMenuItem(contextMenu.get(), CONTEXT_COMPARISON_RESULT, _("Comparison Result"));
+ if (syncPreview->previewIsEnabled())
+ itemSyncPreview->SetBitmap(*GlobalResources::getInstance().bitmapSyncViewSmall);
+ else
+ itemCmpResult->SetBitmap(*GlobalResources::getInstance().bitmapCmpViewSmall);
-void MainDialog::OnContextColumnRight(wxGridEvent& event)
-{
- contextMenu.reset(new wxMenu); //re-create context menu
- contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_RIGHT, _("Customize columns"));
- contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextColumnSelection), NULL, this);
- PopupMenu(contextMenu.get()); //show context menu
+ contextMenu->Append(itemCmpResult);
+ contextMenu->Append(itemSyncPreview);
- event.Skip();
+ contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::OnContextMiddleLabelSelection), NULL, this);
+ PopupMenu(contextMenu.get()); //show context menu
}
-void MainDialog::OnContextColumnSelection(wxCommandEvent& event)
+void MainDialog::OnContextMiddleLabelSelection(wxCommandEvent& event)
{
- int eventId = event.GetId();
- if (eventId == CONTEXT_CUSTOMIZE_COLUMN_LEFT)
- {
- xmlAccess::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes();
- CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIcons);
- if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
- {
- m_gridLeft->setColumnAttributes(colAttr);
- m_gridLeft->enableFileIcons(globalSettings.gui.showFileIcons);
- m_gridRight->enableFileIcons(globalSettings.gui.showFileIcons);
-
- m_gridLeft->setSortMarker(-1); //hide sort direction indicator on GUI grids
- m_gridMiddle->setSortMarker(-1);
- m_gridRight->setSortMarker(-1);
- }
- }
- else if (eventId == CONTEXT_CUSTOMIZE_COLUMN_RIGHT)
+ const ContextIDMiddleLabel eventId = static_cast<ContextIDMiddleLabel>(event.GetId());
+ switch (eventId)
{
- xmlAccess::ColumnAttributes colAttr = m_gridRight->getColumnAttributes();
- CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr, globalSettings.gui.showFileIcons);
- if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY)
- {
- m_gridRight->setColumnAttributes(colAttr);
- m_gridLeft->enableFileIcons(globalSettings.gui.showFileIcons);
- m_gridRight->enableFileIcons(globalSettings.gui.showFileIcons);
-
- m_gridLeft->setSortMarker(-1); //hide sort direction indicator on GUI grids
- m_gridMiddle->setSortMarker(-1);
- m_gridRight->setSortMarker(-1);
- }
+ case CONTEXT_COMPARISON_RESULT:
+ //change view
+ syncPreview->enablePreview(false);
+ break;
+ case CONTEXT_SYNC_PREVIEW:
+ //change view
+ syncPreview->enablePreview(true);
+ break;
}
}
@@ -1112,10 +1250,10 @@ bool sameFileSpecified(const wxString& file1, const wxString& file2)
wxString file2Full = file2;
if (wxFileName(file1).GetPath() == wxEmptyString)
- file1Full = wxFileName::GetCwd() + GlobalResources::FILE_NAME_SEPARATOR + file1;
+ file1Full = wxFileName::GetCwd() + FreeFileSync::FILE_NAME_SEPARATOR + file1;
if (wxFileName(file2).GetPath() == wxEmptyString)
- file2Full = wxFileName::GetCwd() + GlobalResources::FILE_NAME_SEPARATOR + file2;
+ file2Full = wxFileName::GetCwd() + FreeFileSync::FILE_NAME_SEPARATOR + file2;
#ifdef FFS_WIN //don't respect case in windows build
return FreeFileSync::compareStringsWin32(file1Full.c_str(), file2Full.c_str()) == 0;
@@ -1156,7 +1294,7 @@ void MainDialog::addFileToCfgHistory(const wxString& filename)
cfgFileNames.insert(cfgFileNames.begin(), filename);
//the default config file should receive another name on GUI
- if (sameFileSpecified(xmlAccess::LAST_CONFIG_FILE, filename))
+ if (sameFileSpecified(FreeFileSync::getLastConfigFile(), filename))
m_choiceHistory->Insert(_("<Last session>"), 0); //insert at beginning of list
else
m_choiceHistory->Insert(getFormattedHistoryElement(filename), 0); //insert at beginning of list
@@ -1462,7 +1600,10 @@ void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event)
if (0 <= lowerBound)
{
for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView.elementsOnView()) - 1); ++i)
+ {
gridDataView[i].direction = event.direction;
+ gridDataView[i].selectedForSynchronization = true;
+ }
updateGuiGrid();
}
@@ -1481,7 +1622,7 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
{
if (programStartup)
{
- if (filename == xmlAccess::LAST_CONFIG_FILE && !wxFileExists(filename)) //do not show error in this case
+ if (filename == FreeFileSync::getLastConfigFile() && !wxFileExists(filename)) //do not show error in this case
;
else //program startup: show error message and load defaults
wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR);
@@ -1566,7 +1707,7 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
lastConfigurationSaved = guiCfg;
- if (filename == xmlAccess::LAST_CONFIG_FILE) //set title
+ if (filename == FreeFileSync::getLastConfigFile()) //set title
{
SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
currentConfigFileName.clear();
@@ -1577,6 +1718,10 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program
currentConfigFileName = filename;
}
+ //update variant name
+ m_staticTextVariant->SetLabel(wxString(wxT("(")) + cfg.syncConfiguration.getVariantName() + wxT(")"));
+ bSizer6->Layout(); //adapt layout for variant text
+
return true;
}
@@ -1601,7 +1746,7 @@ bool MainDialog::writeConfigurationToXml(const wxString& filename)
lastConfigurationSaved = guiCfg;
- if (filename == xmlAccess::LAST_CONFIG_FILE) //set title
+ if (filename == FreeFileSync::getLastConfigFile()) //set title
{
SetTitle(wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization"));
currentConfigFileName.clear();
@@ -1642,6 +1787,27 @@ void MainDialog::OnShowHelpDialog(wxCommandEvent &event)
}
+void MainDialog::refreshGridAfterFilterChange(const int delay)
+{
+ //signal UI that grids need to be refreshed on next Update()
+ m_gridLeft->ForceRefresh();
+ m_gridMiddle->ForceRefresh();
+ m_gridRight->ForceRefresh();
+ Update(); //show changes resulting from ForceRefresh()
+
+ if (hideFilteredElements)
+ {
+ wxMilliSleep(delay); //some delay to show user the rows he has filtered out before they are removed
+ updateGuiGrid(); //redraw grid to remove excluded elements (keeping sort sequence)
+
+ m_gridLeft->ClearSelection();
+ m_gridRight->ClearSelection();
+ }
+ else
+ updateGuiGrid();
+}
+
+
void MainDialog::OnFilterButton(wxCommandEvent &event)
{ //toggle filter on/off
cfg.filterIsActive = !cfg.filterIsActive;
@@ -1652,11 +1818,13 @@ void MainDialog::OnFilterButton(wxCommandEvent &event)
{
FreeFileSync::FilterProcess filterInstance(cfg.includeFilter, cfg.excludeFilter);
filterInstance.filterGridData(currentGridData);
+ refreshGridAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
}
else
+ {
FreeFileSync::FilterProcess::includeAllRowsOnGrid(currentGridData);
-
- updateGuiGrid();
+ refreshGridAfterFilterChange(0); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts }
+ }
}
@@ -1669,7 +1837,7 @@ void MainDialog::OnHideFilteredButton(wxCommandEvent &event)
m_gridLeft->ClearSelection();
m_gridRight->ClearSelection();
- updateGuiGrid();
+ refreshGridAfterFilterChange(0);
event.Skip();
}
@@ -1704,6 +1872,7 @@ void MainDialog::OnConfigureFilter(wxHyperlinkEvent &event)
updateGuiGrid();
}
}
+
//no event.Skip() here, to not start browser
}
@@ -1789,112 +1958,112 @@ void MainDialog::updateViewFilterButtons()
//compare result buttons
if (gridDataView.leftOnlyFilesActive)
{
- m_bpButtonLeftOnly->SetBitmapLabel(*globalResource.bitmapLeftOnlyAct);
+ m_bpButtonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftOnlyAct);
m_bpButtonLeftOnly->SetToolTip(_("Hide files that exist on left side only"));
}
else
{
- m_bpButtonLeftOnly->SetBitmapLabel(*globalResource.bitmapLeftOnlyDeact);
+ m_bpButtonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftOnlyDeact);
m_bpButtonLeftOnly->SetToolTip(_("Show files that exist on left side only"));
}
if (gridDataView.rightOnlyFilesActive)
{
- m_bpButtonRightOnly->SetBitmapLabel(*globalResource.bitmapRightOnlyAct);
+ m_bpButtonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightOnlyAct);
m_bpButtonRightOnly->SetToolTip(_("Hide files that exist on right side only"));
}
else
{
- m_bpButtonRightOnly->SetBitmapLabel(*globalResource.bitmapRightOnlyDeact);
+ m_bpButtonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightOnlyDeact);
m_bpButtonRightOnly->SetToolTip(_("Show files that exist on right side only"));
}
if (gridDataView.leftNewerFilesActive)
{
- m_bpButtonLeftNewer->SetBitmapLabel(*globalResource.bitmapLeftNewerAct);
+ m_bpButtonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftNewerAct);
m_bpButtonLeftNewer->SetToolTip(_("Hide files that are newer on left"));
}
else
{
- m_bpButtonLeftNewer->SetBitmapLabel(*globalResource.bitmapLeftNewerDeact);
+ m_bpButtonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapLeftNewerDeact);
m_bpButtonLeftNewer->SetToolTip(_("Show files that are newer on left"));
}
if (gridDataView.rightNewerFilesActive)
{
- m_bpButtonRightNewer->SetBitmapLabel(*globalResource.bitmapRightNewerAct);
+ m_bpButtonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightNewerAct);
m_bpButtonRightNewer->SetToolTip(_("Hide files that are newer on right"));
}
else
{
- m_bpButtonRightNewer->SetBitmapLabel(*globalResource.bitmapRightNewerDeact);
+ m_bpButtonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapRightNewerDeact);
m_bpButtonRightNewer->SetToolTip(_("Show files that are newer on right"));
}
if (gridDataView.equalFilesActive)
{
- m_bpButtonEqual->SetBitmapLabel(*globalResource.bitmapEqualAct);
+ m_bpButtonEqual->SetBitmapLabel(*GlobalResources::getInstance().bitmapEqualAct);
m_bpButtonEqual->SetToolTip(_("Hide files that are equal"));
}
else
{
- m_bpButtonEqual->SetBitmapLabel(*globalResource.bitmapEqualDeact);
+ m_bpButtonEqual->SetBitmapLabel(*GlobalResources::getInstance().bitmapEqualDeact);
m_bpButtonEqual->SetToolTip(_("Show files that are equal"));
}
if (gridDataView.differentFilesActive)
{
- m_bpButtonDifferent->SetBitmapLabel(*globalResource.bitmapDifferentAct);
+ m_bpButtonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapDifferentAct);
m_bpButtonDifferent->SetToolTip(_("Hide files that are different"));
}
else
{
- m_bpButtonDifferent->SetBitmapLabel(*globalResource.bitmapDifferentDeact);
+ m_bpButtonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapDifferentDeact);
m_bpButtonDifferent->SetToolTip(_("Show files that are different"));
}
if (gridDataView.conflictFilesActive)
{
- m_bpButtonConflict->SetBitmapLabel(*globalResource.bitmapConflictAct);
+ m_bpButtonConflict->SetBitmapLabel(*GlobalResources::getInstance().bitmapConflictAct);
m_bpButtonConflict->SetToolTip(_("Hide conflicts"));
}
else
{
- m_bpButtonConflict->SetBitmapLabel(*globalResource.bitmapConflictDeact);
+ m_bpButtonConflict->SetBitmapLabel(*GlobalResources::getInstance().bitmapConflictDeact);
m_bpButtonConflict->SetToolTip(_("Show conflicts"));
}
//sync preview buttons
if (gridDataView.syncDirLeftActive)
{
- m_bpButtonSyncDirLeft->SetBitmapLabel(*globalResource.bitmapSyncDirLeftAct);
+ m_bpButtonSyncDirLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirLeftAct);
m_bpButtonSyncDirLeft->SetToolTip(_("Hide files that will be copied to the left side"));
}
else
{
- m_bpButtonSyncDirLeft->SetBitmapLabel(*globalResource.bitmapSyncDirLeftDeact);
+ m_bpButtonSyncDirLeft->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirLeftDeact);
m_bpButtonSyncDirLeft->SetToolTip(_("Show files that will be copied to the left side"));
}
if (gridDataView.syncDirRightActive)
{
- m_bpButtonSyncDirRight->SetBitmapLabel(*globalResource.bitmapSyncDirRightAct);
+ m_bpButtonSyncDirRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirRightAct);
m_bpButtonSyncDirRight->SetToolTip(_("Hide files that will be copied to the right side"));
}
else
{
- m_bpButtonSyncDirRight->SetBitmapLabel(*globalResource.bitmapSyncDirRightDeact);
+ m_bpButtonSyncDirRight->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirRightDeact);
m_bpButtonSyncDirRight->SetToolTip(_("Show files that will be copied to the right side"));
}
if (gridDataView.syncDirNoneActive)
{
- m_bpButtonSyncDirNone->SetBitmapLabel(*globalResource.bitmapSyncDirNoneAct);
+ m_bpButtonSyncDirNone->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirNoneAct);
m_bpButtonSyncDirNone->SetToolTip(_("Hide files that won't be copied"));
}
else
{
- m_bpButtonSyncDirNone->SetBitmapLabel(*globalResource.bitmapSyncDirNoneDeact);
+ m_bpButtonSyncDirNone->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncDirNoneDeact);
m_bpButtonSyncDirNone->SetToolTip(_("Show files that won't be copied"));
}
}
@@ -1904,13 +2073,26 @@ void MainDialog::updateFilterButton(wxBitmapButton* filterButton, bool isActive)
{
if (isActive)
{
- filterButton->SetBitmapLabel(*globalResource.bitmapFilterOn);
+ filterButton->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterOn);
filterButton->SetToolTip(_("Filter active: Press again to deactivate"));
+
+ //show filter icon
+ if (m_notebookBottomLeft->GetImageList() == NULL)
+ {
+ wxImageList* panelIcons = new wxImageList(16, 16);
+ panelIcons->Add(wxBitmap(*GlobalResources::getInstance().bitmapFilterSmall));
+ m_notebookBottomLeft->AssignImageList(panelIcons); //pass ownership
+ }
+ m_notebookBottomLeft->SetPageImage(1, 0);
+
}
else
{
- filterButton->SetBitmapLabel(*globalResource.bitmapFilterOff);
+ filterButton->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterOff);
filterButton->SetToolTip(_("Press button to activate filter"));
+
+ //hide filter icon
+ m_notebookBottomLeft->SetPageImage(1, -1);
}
}
@@ -1978,10 +2160,10 @@ void MainDialog::OnCompare(wxCommandEvent &event)
filterInstance.reset(new FreeFileSync::FilterProcess(cfg.includeFilter, cfg.excludeFilter));
//begin comparison
- FreeFileSync::CompareProcess comparison(globalSettings.shared.traverseDirectorySymlinks,
- globalSettings.shared.fileTimeTolerance,
- globalSettings.shared.ignoreOneHourDiff,
- globalSettings.shared.warningDependentFolders,
+ FreeFileSync::CompareProcess comparison(globalSettings.traverseDirectorySymlinks,
+ globalSettings.fileTimeTolerance,
+ globalSettings.ignoreOneHourDiff,
+ globalSettings.warnings,
filterInstance.get(),
&statusHandler);
@@ -1996,7 +2178,7 @@ void MainDialog::OnCompare(wxCommandEvent &event)
gridDataView.sortView(GridView::SORT_BY_DIRECTORY, true, true);
}
- catch (AbortThisProcess& theException)
+ catch (AbortThisProcess&)
{
aborted = true;
}
@@ -2013,9 +2195,9 @@ void MainDialog::OnCompare(wxCommandEvent &event)
m_buttonStartSync->SetFocus();
//hide sort direction indicator on GUI grids
- m_gridLeft->setSortMarker(-1);
- m_gridMiddle->setSortMarker(-1);
- m_gridRight->setSortMarker(-1);
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
//reset last sort selection: used for determining sort direction
lastSortColumn = -1;
@@ -2080,6 +2262,33 @@ void MainDialog::updateGuiGrid()
}
+void MainDialog::calculatePreview()
+{
+ //update preview of bytes to be transferred:
+ int objectsToCreate = 0;
+ int objectsToOverwrite = 0;
+ int objectsToDelete = 0;
+ int conflictsDummy = 0;
+ wxULongLong dataToProcess;
+ FreeFileSync::calcTotalBytesToSync(currentGridData,
+ objectsToCreate,
+ objectsToOverwrite,
+ objectsToDelete,
+ conflictsDummy,
+ dataToProcess);
+
+ const wxString toCreate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToCreate));
+ const wxString toUpdate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToOverwrite));
+ const wxString toDelete = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToDelete));
+ const wxString data = FreeFileSync::formatFilesizeToShortString(dataToProcess);
+
+ m_textCtrlCreate->SetValue(toCreate);
+ m_textCtrlUpdate->SetValue(toUpdate);
+ m_textCtrlDelete->SetValue(toDelete);
+ m_textCtrlData->SetValue(data);
+}
+
+
void MainDialog::OnSwitchView(wxCommandEvent& event)
{
//toggle view
@@ -2092,7 +2301,12 @@ void MainDialog::OnSyncSettings(wxCommandEvent& event)
SyncDialog* syncDlg = new SyncDialog(this, currentGridData, cfg, ignoreErrors);
if (syncDlg->ShowModal() == SyncDialog::BUTTON_OKAY)
{
+ //update variant name
+ m_staticTextVariant->SetLabel(wxString(wxT("(")) + cfg.syncConfiguration.getVariantName() + wxT(")"));
+ bSizer6->Layout(); //adapt layout for variant text
+
redetermineSyncDirection(cfg.syncConfiguration, currentGridData);
+
updateGuiGrid();
}
}
@@ -2102,6 +2316,40 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
{
if (syncPreview->synchronizationIsEnabled())
{
+ //show sync preview screen
+ if (globalSettings.gui.showSummaryBeforeSync)
+ {
+ //prepare preview screen
+ int objectsToCreate = 0;
+ int objectsToOverwrite = 0;
+ int objectsToDelete = 0;
+ int conflictsDummy = 0;
+ wxULongLong dataToProcess;
+ FreeFileSync::calcTotalBytesToSync(currentGridData,
+ objectsToCreate,
+ objectsToOverwrite,
+ objectsToDelete,
+ conflictsDummy,
+ dataToProcess);
+
+ const wxString toCreate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToCreate));
+ const wxString toUpdate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToOverwrite));
+ const wxString toDelete = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToDelete));
+ const wxString data = FreeFileSync::formatFilesizeToShortString(dataToProcess);
+
+ bool dontShowAgain = false;
+
+ SyncPreviewDlg* preview = new SyncPreviewDlg(
+ this, cfg.syncConfiguration.getVariantName(),
+ toCreate, toUpdate, toDelete, data,
+ dontShowAgain);
+
+ if (preview->ShowModal() != SyncPreviewDlg::BUTTON_START)
+ return;
+
+ globalSettings.gui.showSummaryBeforeSync = !dontShowAgain;
+ }
+
//check if there are files/folders to be sync'ed at all
if (!synchronizationNeeded(currentGridData))
{
@@ -2117,28 +2365,17 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
//class handling status updates and error messages
SyncStatusHandler statusHandler(this, ignoreErrors);
-// //small reminder that synchronization will be starting immediately
-// if (globalSettings.shared.warningSynchronizationStarting) //test if check should be executed
-// {
-// bool dontShowAgain = false;
-// statusHandler.reportWarning(_(""),
-// dontShowAgain);
-// globalSettings.shared.warningSynchronizationStarting = !dontShowAgain;
-// }
-
//start synchronization and return elements that were not sync'ed in currentGridData
FreeFileSync::SyncProcess synchronization(
cfg.useRecycleBin,
- globalSettings.shared.copyFileSymlinks,
- globalSettings.shared.traverseDirectorySymlinks,
- globalSettings.shared.warningSignificantDifference,
- globalSettings.shared.warningNotEnoughDiskSpace,
- globalSettings.shared.warningUnresolvedConflicts,
+ globalSettings.copyFileSymlinks,
+ globalSettings.traverseDirectorySymlinks,
+ globalSettings.warnings,
&statusHandler);
synchronization.startSynchronizationProcess(currentGridData);
}
- catch (AbortThisProcess& theException)
+ catch (AbortThisProcess&)
{ //do NOT disable the sync button: user might want to try to sync the REMAINING rows
} //enableSynchronization(false);
@@ -2161,6 +2398,7 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
}
}
+
void MainDialog::OnLeftGridDoubleClick(wxGridEvent& event)
{
openWithFileManager(event.GetRow(), true);
@@ -2217,12 +2455,9 @@ void MainDialog::OnSortLeftGrid(wxGridEvent& event)
updateGuiGrid(); //refresh gridDataView
//set sort direction indicator on UI
- m_gridMiddle->setSortMarker(-1);
- m_gridRight->setSortMarker(-1);
- if (sortAscending)
- m_gridLeft->setSortMarker(currentSortColumn, globalResource.bitmapSmallUp);
- else
- m_gridLeft->setSortMarker(currentSortColumn, globalResource.bitmapSmallDown);
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(currentSortColumn, sortAscending ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
}
}
@@ -2239,17 +2474,17 @@ void MainDialog::OnSortMiddleGrid(wxGridEvent& event)
lastSortGrid = m_gridMiddle;
//start sort
- gridDataView.sortView(GridView::SORT_BY_CMP_RESULT, true, sortAscending);
+ if (syncPreview->previewIsEnabled())
+ gridDataView.sortView(GridView::SORT_BY_SYNC_DIRECTION, true, sortAscending);
+ else
+ gridDataView.sortView(GridView::SORT_BY_CMP_RESULT, true, sortAscending);
updateGuiGrid(); //refresh gridDataView
//set sort direction indicator on UI
- m_gridLeft->setSortMarker(-1);
- m_gridRight->setSortMarker(-1);
- if (sortAscending)
- m_gridMiddle->setSortMarker(0, globalResource.bitmapSmallUp);
- else
- m_gridMiddle->setSortMarker(0, globalResource.bitmapSmallDown);
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(0, sortAscending ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
}
@@ -2295,12 +2530,9 @@ void MainDialog::OnSortRightGrid(wxGridEvent& event)
updateGuiGrid(); //refresh gridDataView
//set sort direction indicator on UI
- m_gridLeft->setSortMarker(-1);
- m_gridMiddle->setSortMarker(-1);
- if (sortAscending)
- m_gridRight->setSortMarker(currentSortColumn, globalResource.bitmapSmallUp);
- else
- m_gridRight->setSortMarker(currentSortColumn, globalResource.bitmapSmallDown);
+ m_gridLeft->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridMiddle->setSortMarker(CustomGrid::SortMarker(-1, CustomGrid::ASCENDING));
+ m_gridRight->setSortMarker(CustomGrid::SortMarker(currentSortColumn, sortAscending ? CustomGrid::ASCENDING : CustomGrid::DESCENDING));
}
}
@@ -2334,7 +2566,7 @@ void MainDialog::OnSwapSides(wxCommandEvent& event)
updateViewFilterButtons();
//swap grid information
- FreeFileSync::swapGrids(currentGridData);
+ FreeFileSync::swapGrids(cfg.syncConfiguration, currentGridData);
updateGuiGrid();
event.Skip();
}
@@ -2530,7 +2762,18 @@ void MainDialog::updateGridViewData()
void MainDialog::OnAddFolderPair(wxCommandEvent& event)
{
- addFolderPair(wxEmptyString, wxEmptyString);
+ const wxString topPairLeft = m_directoryLeft->GetValue();
+ const wxString topPairRight = m_directoryRight->GetValue();
+
+ //clear existing pairs first
+ m_directoryLeft->SetSelection(wxNOT_FOUND);
+ m_directoryLeft->SetValue(wxEmptyString);
+ m_dirPickerLeft->SetPath(wxEmptyString);
+ m_directoryRight->SetSelection(wxNOT_FOUND);
+ m_directoryRight->SetValue(wxEmptyString);
+ m_dirPickerRight->SetPath(wxEmptyString);
+
+ addFolderPair(topPairLeft.c_str(), topPairRight.c_str(), true); //add pair in front of additonal pairs
//disable the sync button
syncPreview->enableSynchronization(false);
@@ -2563,46 +2806,58 @@ void MainDialog::OnRemoveFolderPair(wxCommandEvent& event)
}
-void MainDialog::calculatePreview()
+void MainDialog::OnRemoveTopFolderPair(wxCommandEvent& event)
{
- //update preview of bytes to be transferred:
- int objectsToCreate = 0;
- int objectsToOverwrite = 0;
- int objectsToDelete = 0;
- int conflictsDummy = 0;
- wxULongLong dataToProcess;
- FreeFileSync::calcTotalBytesToSync(currentGridData,
- objectsToCreate,
- objectsToOverwrite,
- objectsToDelete,
- conflictsDummy,
- dataToProcess);
+ if (additionalFolderPairs.size() > 0)
+ {
+ m_directoryLeft->SetSelection(wxNOT_FOUND);
+ m_directoryRight->SetSelection(wxNOT_FOUND);
- const wxString toCreate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToCreate));
- const wxString toUpdate = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToOverwrite));
- const wxString toDelete = globalFunctions::includeNumberSeparator(globalFunctions::numberToWxString(objectsToDelete));
- const wxString data = FreeFileSync::formatFilesizeToShortString(dataToProcess);
+ m_directoryLeft->SetValue((*additionalFolderPairs.begin())->m_directoryLeft->GetValue());
+ m_directoryRight->SetValue((*additionalFolderPairs.begin())->m_directoryRight->GetValue());
- m_textCtrlCreate->SetValue(toCreate);
- m_textCtrlUpdate->SetValue(toUpdate);
- m_textCtrlDelete->SetValue(toDelete);
- m_textCtrlData->SetValue(data);
+ removeFolderPair(0); //remove first of additional folder pairs
+
+ //disable the sync button
+ syncPreview->enableSynchronization(false);
+
+ //clear grids
+ currentGridData.clear();
+ updateGuiGrid();
+ }
}
-void MainDialog::addFolderPair(const Zstring& leftDir, const Zstring& rightDir)
+void MainDialog::addFolderPair(const Zstring& leftDir, const Zstring& rightDir, bool addFront)
{
std::vector<FolderPair> newPairs;
- FolderPair pair;
- pair.leftDirectory = leftDir;
- pair.rightDirectory = rightDir;
- newPairs.push_back(pair);
+ newPairs.push_back(FolderPair(leftDir, rightDir));
+
+ MainDialog::addFolderPair(newPairs, addFront);
+}
+
- MainDialog::addFolderPair(newPairs);
+void scrollToBottom(wxScrolledWindow* scrWindow)
+{
+ int height = 0;
+ scrWindow->GetClientSize(NULL, &height);
+
+ int pixelPerLine = 0;
+ scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine);
+
+ if (height > 0 && pixelPerLine > 0)
+ {
+ const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL);
+ const int scrollLinesOnScreen = height / pixelPerLine;
+ const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen;
+
+ if (0 <= scrollPosBottom)
+ scrWindow->Scroll(0, scrollPosBottom);
+ }
}
-void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs)
+void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs, bool addFront)
{
if (newPairs.size() == 0)
return;
@@ -2611,14 +2866,22 @@ void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs)
{
//add new folder pair
FolderPairPanel* newPair = new FolderPairPanel(m_scrolledWindowFolderPairs);
- newPair->m_bitmap23->SetBitmap(*globalResource.bitmapLink);
- newPair->m_bpButtonRemovePair->SetBitmapLabel(*globalResource.bitmapRemoveFolderPair);
+ newPair->m_bitmap23->SetBitmap(*GlobalResources::getInstance().bitmapLink);
+ newPair->m_bpButtonRemovePair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair);
- bSizerFolderPairs->Add(newPair, 0, wxEXPAND, 5);
- additionalFolderPairs.push_back(newPair);
+ if (addFront)
+ {
+ bSizerFolderPairs->Insert(0, newPair, 0, wxEXPAND, 5);
+ additionalFolderPairs.insert(additionalFolderPairs.begin(), newPair);
+ }
+ else
+ {
+ bSizerFolderPairs->Add(newPair, 0, wxEXPAND, 5);
+ additionalFolderPairs.push_back(newPair);
+ }
//set size of scrolled window
- wxSize pairSize = newPair->GetSize();
+ const wxSize pairSize = newPair->GetSize();
const int additionalRows = additionalFolderPairs.size();
if (additionalRows <= 3) //up to 3 additional pairs shall be shown
@@ -2654,9 +2917,19 @@ void MainDialog::addFolderPair(const std::vector<FolderPair>& newPairs)
m_bitmapShift->Show();
}
+ //adapt delete top folder pair button
+ if (additionalFolderPairs.size() > 0)
+ {
+ m_bpButtonRemoveTopPair->Show();
+ m_panelTopRight->Layout();
+ }
+
+ //scroll to the bottom of wxScrolledWindow
+ //scrollToBottom(m_scrolledWindowFolderPairs);
+
m_scrolledWindowFolderPairs->Layout();
bSizer1->Layout();
- m_bpButtonSwitchView->Refresh();
+ m_bpButtonSwapSides->Refresh();
}
@@ -2680,15 +2953,24 @@ void MainDialog::removeFolderPair(const int pos, bool refreshLayout)
//adjust scrollbars (do not put in else clause)
m_scrolledWindowFolderPairs->Fit();
+ //adapt left-shift display distortion caused by scrollbars
if (refreshLayout)
{
- //adapt left-shift display distortion caused by scrollbars
- if (additionalFolderPairs.size() <= 3)
+ if (additionalRows <= 3)
m_bitmapShift->Hide();
m_scrolledWindowFolderPairs->Layout();
bSizer1->Layout();
}
+
+ //adapt delete top folder pair button
+ if (additionalFolderPairs.size() == 0)
+ {
+ m_bpButtonRemoveTopPair->Hide();
+ if (refreshLayout)
+ m_panelTopRight->Layout();
+ }
+
}
}
@@ -2808,7 +3090,17 @@ void MainDialog::OnRegularUpdateCheck(wxIdleEvent& event)
//execute just once per startup!
Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), NULL, this);
- FreeFileSync::checkForUpdatePeriodically(globalSettings.shared.lastUpdateCheck);
+ FreeFileSync::checkForUpdatePeriodically(globalSettings.lastUpdateCheck);
+}
+
+
+void MainDialog::OnLayoutWindowAsync(wxIdleEvent& event)
+{
+ //execute just once per startup!
+ Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnLayoutWindowAsync), NULL, this);
+
+ Layout(); //strangely this layout call works if called in next idle event only
+ Refresh();
}
@@ -2835,89 +3127,20 @@ void MainDialog::switchProgramLanguage(const int langID)
cleanUp(); //destructor's code: includes writing settings to HD
//create new dialog with respect to new language
- MainDialog* frame = new MainDialog(NULL, xmlAccess::LAST_CONFIG_FILE, programLanguage, globalSettings);
- frame->SetIcon(*globalResource.programIcon); //set application icon
+ MainDialog* frame = new MainDialog(NULL, FreeFileSync::getLastConfigFile(), programLanguage, globalSettings);
+ frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon
frame->Show();
Destroy();
}
-void MainDialog::OnMenuLangChineseSimp(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_CHINESE_SIMPLIFIED);
-}
-
-
-void MainDialog::OnMenuLangDutch(wxCommandEvent& event)
+void MainDialog::OnMenuLanguageSwitch(wxCommandEvent& event)
{
- switchProgramLanguage(wxLANGUAGE_DUTCH);
-}
+ std::map<MenuItemID, LanguageID>::const_iterator it = languageMenuItemMap.find(event.GetId());
-
-void MainDialog::OnMenuLangEnglish(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_ENGLISH);
-}
-
-
-void MainDialog::OnMenuLangFrench(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_FRENCH);
-}
-
-
-void MainDialog::OnMenuLangGerman(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_GERMAN);
-}
-
-
-void MainDialog::OnMenuLangHungarian(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_HUNGARIAN);
-}
-
-
-void MainDialog::OnMenuLangItalian(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_ITALIAN);
-}
-
-
-void MainDialog::OnMenuLangJapanese(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_JAPANESE);
-}
-
-
-void MainDialog::OnMenuLangPolish(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_POLISH);
-}
-
-
-void MainDialog::OnMenuLangPortuguese(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_PORTUGUESE);
-}
-
-
-void MainDialog::OnMenuLangPortugueseBrazil(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_PORTUGUESE_BRAZILIAN);
-}
-
-
-void MainDialog::OnMenuLangSlovenian(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_SLOVENIAN);
-}
-
-
-void MainDialog::OnMenuLangSpanish(wxCommandEvent& event)
-{
- switchProgramLanguage(wxLANGUAGE_SPANISH);
+ if (it != languageMenuItemMap.end())
+ switchProgramLanguage(it->second);
}
//#########################################################################################################
@@ -2941,19 +3164,6 @@ void SyncPreview::enablePreview(bool value)
{
syncPreviewEnabled = true;
- mainDlg_->m_bpButtonSwitchView->SetBitmapLabel(*globalResource.bitmapSyncView);
- mainDlg_->m_bpButtonSwitchView->SetToolTip(_("Synchronization Preview"));
-
- /*mainDlg_->m_bpButtonSyncConfig->Show();
- mainDlg_->m_bpButtonSyncConfig->Enable();
-
- mainDlg_->m_buttonStartSync->Show();
- mainDlg_->m_buttonStartSync->Enable();*/
-
- mainDlg_->m_panelSyncPreview->Show();
-
- mainDlg_->bSizer6->Layout();
-
//toggle display of sync preview in middle grid
mainDlg_->m_gridMiddle->enableSyncPreview(true);
@@ -2963,19 +3173,6 @@ void SyncPreview::enablePreview(bool value)
{
syncPreviewEnabled = false;
- mainDlg_->m_bpButtonSwitchView->SetBitmapLabel(*globalResource.bitmapCmpView);
- mainDlg_->m_bpButtonSwitchView->SetToolTip(_("Comparison Result"));
-
- /*mainDlg_->m_bpButtonSyncConfig->Disable();
- mainDlg_->m_bpButtonSyncConfig->Hide();
-
- mainDlg_->m_buttonStartSync->Disable();
- mainDlg_->m_buttonStartSync->Hide();*/
-
- mainDlg_->m_panelSyncPreview->Hide();
-
- mainDlg_->bSizer6->Layout();
-
//toggle display of sync preview in middle grid
mainDlg_->m_gridMiddle->enableSyncPreview(false);
@@ -2992,13 +3189,13 @@ void SyncPreview::enableSynchronization(bool value)
{
synchronizationEnabled = true;
mainDlg_->m_buttonStartSync->SetForegroundColour(*wxBLACK);
- mainDlg_->m_buttonStartSync->setBitmapFront(*globalResource.bitmapSync);
+ mainDlg_->m_buttonStartSync->setBitmapFront(*GlobalResources::getInstance().bitmapSync);
}
else
{
synchronizationEnabled = false;
mainDlg_->m_buttonStartSync->SetForegroundColour(wxColor(94, 94, 94)); //grey
- mainDlg_->m_buttonStartSync->setBitmapFront(*globalResource.bitmapSyncDisabled);
+ mainDlg_->m_buttonStartSync->setBitmapFront(*GlobalResources::getInstance().bitmapSyncDisabled);
}
}
diff --git a/ui/MainDialog.h b/ui/MainDialog.h
index 671da7ee..e8eae783 100644
--- a/ui/MainDialog.h
+++ b/ui/MainDialog.h
@@ -13,16 +13,22 @@
#include "../library/processXml.h"
#include "gridView.h"
#include <memory>
+#include <map>
class CompareStatusHandler;
class CompareStatus;
-class CustomLocale;
class MainFolderDragDrop;
class FolderPairPanel;
class CustomGrid;
class FFSCheckRowsEvent;
class FFSSyncDirectionEvent;
class SyncPreview;
+class IconUpdater;
+
+namespace FreeFileSync
+{
+ class CustomLocale;
+}
class MainDialog : public MainDialogGenerated
@@ -32,7 +38,7 @@ class MainDialog : public MainDialogGenerated
friend class SyncPreview;
//IDs for context menu items
- enum //context menu for left and right grids
+ enum ContextIDRim //context menu for left and right grids
{
CONTEXT_FILTER_TEMP = 10,
CONTEXT_EXCLUDE_EXT,
@@ -40,24 +46,36 @@ class MainDialog : public MainDialogGenerated
CONTEXT_CLIPBOARD,
CONTEXT_EXPLORER,
CONTEXT_DELETE_FILES,
- CONTEXT_SWAP_SIDES
+ CONTEXT_SYNC_DIR_LEFT,
+ CONTEXT_SYNC_DIR_NONE,
+ CONTEXT_SYNC_DIR_RIGHT
};
- enum //context menu for middle grid
+ enum ContextIDRimLabel//context menu for column settings
{
- CONTEXT_CHECK_ALL,
+ CONTEXT_CUSTOMIZE_COLUMN_LEFT,
+ CONTEXT_CUSTOMIZE_COLUMN_RIGHT
+ };
+
+ enum ContextIDMiddle//context menu for middle grid
+ {
+ CONTEXT_CHECK_ALL = 20,
CONTEXT_UNCHECK_ALL
};
- enum //context menu for column settings
+ enum ContextIDMiddleLabel
{
- CONTEXT_CUSTOMIZE_COLUMN_LEFT,
- CONTEXT_CUSTOMIZE_COLUMN_RIGHT
+ CONTEXT_COMPARISON_RESULT = 30,
+ CONTEXT_SYNC_PREVIEW
};
public:
- MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale* language, xmlAccess::XmlGlobalSettings& settings);
+ MainDialog(wxFrame* frame,
+ const wxString& cfgFileName,
+ FreeFileSync::CustomLocale* language,
+ xmlAccess::XmlGlobalSettings& settings);
+
~MainDialog();
private:
@@ -74,15 +92,15 @@ private:
void writeGlobalSettings();
void updateViewFilterButtons();
- static void updateFilterButton(wxBitmapButton* filterButton, bool isActive);
+ void updateFilterButton(wxBitmapButton* filterButton, bool isActive);
void updateCompareButtons();
void addFileToCfgHistory(const wxString& filename);
void addLeftFolderToHistory(const wxString& leftFolder);
void addRightFolderToHistory(const wxString& rightFolder);
- void addFolderPair(const Zstring& leftDir, const Zstring& rightDir);
- void addFolderPair(const std::vector<FreeFileSync::FolderPair>& newPairs);
+ void addFolderPair(const Zstring& leftDir, const Zstring& rightDir, bool addFront = false);
+ void addFolderPair(const std::vector<FreeFileSync::FolderPair>& newPairs, bool addFront = false);
void removeFolderPair(const int pos, bool refreshLayout = true); //keep it an int, allow negative values!
void clearFolderPairs();
@@ -93,6 +111,8 @@ private:
//context menu functions
std::set<int> getSelectedRows(const CustomGrid* grid) const;
+ std::set<int> getSelectedRows() const;
+ void setSyncDirManually(const std::set<int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir);
void filterRangeManually(const std::set<int>& rowsToFilterOnUiTable, const int leadingRow);
void copySelectionToClipboard(const CustomGrid* selectedGrid);
void openWithFileManager(const int rowNumber, const bool leftSide);
@@ -106,16 +126,18 @@ private:
void clearStatusBar();
//events
- void onGridLeftButtonEvent(wxKeyEvent& event);
- void onGridRightButtonEvent(wxKeyEvent& event);
- void onGridMiddleButtonEvent(wxKeyEvent& event);
- void OnContextMenu(wxGridEvent& event);
- void OnContextMenuSelection(wxCommandEvent& event);
- void OnContextMenuMiddle(wxGridEvent& event);
- void OnContextMenuMiddleSelection(wxCommandEvent& event);
- void OnContextColumnLeft(wxGridEvent& event);
- void OnContextColumnRight(wxGridEvent& event);
- void OnContextColumnSelection(wxCommandEvent& event);
+ void onGridLeftButtonEvent( wxKeyEvent& event);
+ void onGridRightButtonEvent( wxKeyEvent& event);
+ void onGridMiddleButtonEvent( wxKeyEvent& event);
+ void OnContextRim( wxGridEvent& event);
+ void OnContextRimSelection( wxCommandEvent& event);
+ void OnContextRimLabelLeft( wxGridEvent& event);
+ void OnContextRimLabelRight( wxGridEvent& event);
+ void OnContextRimLabelSelection( wxCommandEvent& event);
+ void OnContextMiddle( wxGridEvent& event);
+ void OnContextMiddleSelection( wxCommandEvent& event);
+ void OnContextMiddleLabel( wxGridEvent& event);
+ void OnContextMiddleLabelSelection(wxCommandEvent& event);
void OnDirSelected(wxFileDirPickerEvent& event);
@@ -151,6 +173,9 @@ private:
void OnCfgHistoryKeyEvent( wxKeyEvent& event);
void OnFolderHistoryKeyEvent(wxKeyEvent& event);
void OnRegularUpdateCheck( wxIdleEvent& event);
+ void OnLayoutWindowAsync( wxIdleEvent& event);
+
+ void refreshGridAfterFilterChange(const int delay);
void onResizeMainWindow( wxEvent& event);
void OnAbortCompare( wxCommandEvent& event);
@@ -168,10 +193,11 @@ private:
void OnClose( wxCloseEvent& event);
void OnQuit( wxCommandEvent& event);
+ void calculatePreview();
+
void OnAddFolderPair( wxCommandEvent& event);
void OnRemoveFolderPair( wxCommandEvent& event);
-
- void calculatePreview();
+ void OnRemoveTopFolderPair( wxCommandEvent& event);
//menu events
void OnMenuSaveConfig( wxCommandEvent& event);
@@ -182,22 +208,14 @@ private:
void OnMenuCheckVersion( wxCommandEvent& event);
void OnMenuAbout( wxCommandEvent& event);
void OnMenuQuit( wxCommandEvent& event);
- void OnMenuLangChineseSimp( wxCommandEvent& event);
- void OnMenuLangDutch( wxCommandEvent& event);
- void OnMenuLangEnglish( wxCommandEvent& event);
- void OnMenuLangFrench( wxCommandEvent& event);
- void OnMenuLangGerman( wxCommandEvent& event);
- void OnMenuLangHungarian( wxCommandEvent& event);
- void OnMenuLangItalian( wxCommandEvent& event);
- void OnMenuLangJapanese( wxCommandEvent& event);
- void OnMenuLangPolish( wxCommandEvent& event);
- void OnMenuLangPortuguese( wxCommandEvent& event);
- void OnMenuLangPortugueseBrazil(wxCommandEvent& event);
- void OnMenuLangSlovenian( wxCommandEvent& event);
- void OnMenuLangSpanish( wxCommandEvent& event);
+ void OnMenuLanguageSwitch( wxCommandEvent& event);
void switchProgramLanguage(const int langID);
+ typedef int MenuItemID;
+ typedef int LanguageID;
+ std::map<MenuItemID, LanguageID> languageMenuItemMap; //needed to attach menu item events
+
//***********************************************
//application variables are stored here:
@@ -234,7 +252,7 @@ private:
//***********************************************
std::auto_ptr<wxMenu> contextMenu;
- CustomLocale* programLanguage;
+ FreeFileSync::CustomLocale* programLanguage;
//status information
wxLongLong lastStatusChange;
@@ -270,6 +288,11 @@ private:
std::auto_ptr<MainFolderDragDrop> dragDropOnLeft;
std::auto_ptr<MainFolderDragDrop> dragDropOnRight;
+#ifdef FFS_WIN
+ //update icons periodically: one updater instance for both left and right grids
+ std::auto_ptr<IconUpdater> updateFileIcons;
+#endif
+
//encapsulation of handling of sync preview
std::auto_ptr<SyncPreview> syncPreview;
};
diff --git a/ui/SmallDialogs.cpp b/ui/SmallDialogs.cpp
index 9ab09e88..db20e526 100644
--- a/ui/SmallDialogs.cpp
+++ b/ui/SmallDialogs.cpp
@@ -6,29 +6,40 @@
#include "../library/customGrid.h"
#include "../library/customButton.h"
#include "../library/statistics.h"
+#include "../library/localization.h"
using namespace FreeFileSync;
AboutDlg::AboutDlg(wxWindow* window) : AboutDlgGenerated(window)
{
- m_bitmap9->SetBitmap(*globalResource.bitmapWebsite);
- m_bitmap10->SetBitmap(*globalResource.bitmapEmail);
- m_bitmap11->SetBitmap(*globalResource.bitmapLogo);
- m_bitmap13->SetBitmap(*globalResource.bitmapGPL);
-
- //flag bitmaps
- m_bitmapFrench ->SetBitmap(*globalResource.bitmapFrance);
- m_bitmapJapanese ->SetBitmap(*globalResource.bitmapJapan);
- m_bitmapDutch ->SetBitmap(*globalResource.bitmapHolland);
- m_bitmapChineseSimple ->SetBitmap(*globalResource.bitmapChina);
- m_bitmapPolish ->SetBitmap(*globalResource.bitmapPoland);
- m_bitmapPortuguese ->SetBitmap(*globalResource.bitmapPortugal);
- m_bitmapItalian ->SetBitmap(*globalResource.bitmapItaly);
- m_bitmapSlovenian ->SetBitmap(*globalResource.bitmapSlovakia);
- m_bitmapHungarian ->SetBitmap(*globalResource.bitmapHungary);
- m_bitmapSpanish ->SetBitmap(*globalResource.bitmapSpain);
- m_bitmapPortugueseBrazil->SetBitmap(*globalResource.bitmapBrazil);
+ m_bitmap9->SetBitmap(*GlobalResources::getInstance().bitmapWebsite);
+ m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapEmail);
+ m_bitmap11->SetBitmap(*GlobalResources::getInstance().bitmapLogo);
+ m_bitmap13->SetBitmap(*GlobalResources::getInstance().bitmapGPL);
+
+
+ //create language credits
+ for (std::vector<LocInfoLine>::const_iterator i = LocalizationInfo::getMapping().begin(); i != LocalizationInfo::getMapping().end(); ++i)
+ {
+ //flag
+ wxStaticBitmap* staticBitmapFlag = new wxStaticBitmap(m_scrolledWindowTranslators, wxID_ANY, *i->languageFlag, wxDefaultPosition, wxSize(-1,11), 0 );
+ fgSizerTranslators->Add(staticBitmapFlag, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ //language name
+ wxStaticText* staticTextLanguage = new wxStaticText(m_scrolledWindowTranslators, wxID_ANY, i->languageName, wxDefaultPosition, wxDefaultSize, 0 );
+ staticTextLanguage->Wrap( -1 );
+ fgSizerTranslators->Add(staticTextLanguage, 0, wxALIGN_CENTER_VERTICAL, 5);
+
+ //translator name
+ wxStaticText* staticTextTranslator = new wxStaticText(m_scrolledWindowTranslators, wxID_ANY, i->translatorName, wxDefaultPosition, wxDefaultSize, 0 );
+ staticTextTranslator->Wrap( -1 );
+ fgSizerTranslators->Add(staticTextTranslator, 0, wxALIGN_CENTER_VERTICAL, 5);
+ }
+
+ bSizerTranslators->Fit(m_scrolledWindowTranslators);
+
+
//build information
wxString build = wxString(wxT("(")) + _("Build:") + wxT(" ") + __TDATE__;
@@ -39,7 +50,7 @@ AboutDlg::AboutDlg(wxWindow* window) : AboutDlgGenerated(window)
#endif //wxUSE_UNICODE
m_build->SetLabel(build);
- m_animationControl1->SetAnimation(*globalResource.animationMoney);
+ m_animationControl1->SetAnimation(*GlobalResources::getInstance().animationMoney);
m_animationControl1->Play(); //Note: The animation is created hidden(!) to not disturb constraint based window creation;
m_animationControl1->Show(); //
@@ -65,7 +76,7 @@ HelpDlg::HelpDlg(wxWindow* window) : HelpDlgGenerated(window)
{
m_notebook1->SetFocus();
- m_bitmap25->SetBitmap(*globalResource.bitmapHelp);
+ m_bitmap25->SetBitmap(*GlobalResources::getInstance().bitmapHelp);
//populate decision trees: "compare by date"
wxTreeItemId treeRoot = m_treeCtrl1->AddRoot(_("DECISION TREE"));
@@ -120,10 +131,10 @@ FilterDlg::FilterDlg(wxWindow* window, wxString& filterIncl, wxString& filterExc
includeFilter(filterIncl),
excludeFilter(filterExcl)
{
- m_bitmap8->SetBitmap(*globalResource.bitmapInclude);
- m_bitmap9->SetBitmap(*globalResource.bitmapExclude);
- m_bitmap26->SetBitmap(*globalResource.bitmapFilter);
- m_bpButtonHelp->SetBitmapLabel(*globalResource.bitmapHelp);
+ m_bitmap8->SetBitmap(*GlobalResources::getInstance().bitmapInclude);
+ m_bitmap9->SetBitmap(*GlobalResources::getInstance().bitmapExclude);
+ m_bitmap26->SetBitmap(*GlobalResources::getInstance().bitmapFilter);
+ m_bpButtonHelp->SetBitmapLabel(*GlobalResources::getInstance().bitmapHelp);
m_textCtrlInclude->SetValue(includeFilter);
m_textCtrlExclude->SetValue(excludeFilter);
@@ -207,12 +218,12 @@ void DeleteDialog::updateTexts()
if (m_checkBoxUseRecycler->GetValue())
{
headerText = _("Do you really want to move the following objects(s) to the Recycle Bin?");
- m_bitmap12->SetBitmap(*globalResource.bitmapRecycler);
+ m_bitmap12->SetBitmap(*GlobalResources::getInstance().bitmapRecycler);
}
else
{
headerText = _("Do you really want to delete the following objects(s)?");
- m_bitmap12->SetBitmap(*globalResource.bitmapDeleteFile);
+ m_bitmap12->SetBitmap(*GlobalResources::getInstance().bitmapDeleteFile);
}
m_staticTextHeader->SetLabel(headerText);
@@ -282,7 +293,7 @@ ErrorDlg::ErrorDlg(wxWindow* parentWindow, const int activeButtons, const wxStri
ErrorDlgGenerated(parentWindow),
ignoreErrors(ignoreNextErrors)
{
- m_bitmap10->SetBitmap(*globalResource.bitmapError);
+ m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapError);
m_textCtrl8->SetValue(messageText);
m_checkBoxIgnoreErrors->SetValue(ignoreNextErrors);
@@ -343,7 +354,7 @@ WarningDlg::WarningDlg(wxWindow* parentWindow, int activeButtons, const wxStrin
WarningDlgGenerated(parentWindow),
dontShowAgain(dontShowDlgAgain)
{
- m_bitmap10->SetBitmap(*globalResource.bitmapWarning);
+ m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapWarning);
m_textCtrl8->SetValue(messageText);
m_checkBoxDontShowAgain->SetValue(dontShowAgain);
@@ -393,7 +404,7 @@ QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxStri
QuestionDlgGenerated(parentWindow),
dontShowAgain(dontShowDlgAgain)
{
- m_bitmap10->SetBitmap(*globalResource.bitmapQuestion);
+ m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapQuestion);
m_textCtrl8->SetValue(messageText);
m_checkBoxDontAskAgain->SetValue(dontShowAgain);
@@ -419,9 +430,6 @@ QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxStri
}
-QuestionDlg::~QuestionDlg() {}
-
-
void QuestionDlg::OnClose(wxCloseEvent& event)
{
dontShowAgain = m_checkBoxDontAskAgain->GetValue();
@@ -456,8 +464,8 @@ CustomizeColsDlg::CustomizeColsDlg(wxWindow* window, xmlAccess::ColumnAttributes
output(attr),
m_showFileIcons(showFileIcons)
{
- m_bpButton29->SetBitmapLabel(*globalResource.bitmapMoveUp);
- m_bpButton30->SetBitmapLabel(*globalResource.bitmapMoveDown);
+ m_bpButton29->SetBitmapLabel(*GlobalResources::getInstance().bitmapMoveUp);
+ m_bpButton30->SetBitmapLabel(*GlobalResources::getInstance().bitmapMoveDown);
xmlAccess::ColumnAttributes columnSettings = attr;
@@ -563,15 +571,68 @@ void CustomizeColsDlg::OnMoveDown(wxCommandEvent& event)
}
//########################################################################################
+
+
+SyncPreviewDlg::SyncPreviewDlg(wxWindow* parentWindow,
+ const wxString& variantName,
+ const wxString& toCreate,
+ const wxString& toUpdate,
+ const wxString& toDelete,
+ const wxString& data,
+ bool& dontShowAgain) :
+ SyncPreviewDlgGenerated(parentWindow),
+ m_dontShowAgain(dontShowAgain)
+{
+ //m_bitmapPreview->SetBitmap(*GlobalResources::getInstance().bitmapSync);
+ m_buttonStartSync->setBitmapFront(*GlobalResources::getInstance().bitmapStartSync);
+ m_bitmapCreate->SetBitmap(*GlobalResources::getInstance().bitmapCreate);
+ m_bitmapUpdate->SetBitmap(*GlobalResources::getInstance().bitmapUpdate);
+ m_bitmapDelete->SetBitmap(*GlobalResources::getInstance().bitmapDelete);
+ m_bitmapData->SetBitmap(*GlobalResources::getInstance().bitmapData);
+
+ m_staticTextVariant->SetLabel(variantName);
+ m_textCtrlCreate->SetValue(toCreate);
+ m_textCtrlUpdate->SetValue(toUpdate);
+ m_textCtrlDelete->SetValue(toDelete);
+ m_textCtrlData->SetValue(data);
+
+ m_checkBoxDontShowAgain->SetValue(dontShowAgain);
+
+ m_buttonStartSync->SetFocus();
+ Fit();
+}
+
+
+void SyncPreviewDlg::OnClose(wxCloseEvent& event)
+{
+ EndModal(BUTTON_CANCEL);
+}
+
+
+void SyncPreviewDlg::OnCancel(wxCommandEvent& event)
+{
+ EndModal(BUTTON_CANCEL);
+}
+
+
+void SyncPreviewDlg::OnStartSync(wxCommandEvent& event)
+{
+ m_dontShowAgain = m_checkBoxDontShowAgain->GetValue();
+ EndModal(BUTTON_START);
+}
+
+
+
+//########################################################################################
GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings& globalSettings) :
GlobalSettingsDlgGenerated(window),
settings(globalSettings)
{
- m_bitmapSettings->SetBitmap(*globalResource.bitmapSettings);
- m_buttonResetWarnings->setBitmapFront(*globalResource.bitmapWarningSmall, 5);
+ m_bitmapSettings->SetBitmap(*GlobalResources::getInstance().bitmapSettings);
+ m_buttonResetWarnings->setBitmapFront(*GlobalResources::getInstance().bitmapWarningSmall, 5);
- m_spinCtrlFileTimeTolerance->SetValue(globalSettings.shared.fileTimeTolerance);
- m_checkBoxIgnoreOneHour->SetValue(globalSettings.shared.ignoreOneHourDiff);
+ m_spinCtrlFileTimeTolerance->SetValue(globalSettings.fileTimeTolerance);
+ m_checkBoxIgnoreOneHour->SetValue(globalSettings.ignoreOneHourDiff);
m_textCtrlFileManager->SetValue(globalSettings.gui.commandLineFileManager);
@@ -582,8 +643,8 @@ GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* window, xmlAccess::XmlGlobalSetti
void GlobalSettingsDlg::OnOkay(wxCommandEvent& event)
{
//write global settings only when okay-button is pressed!
- settings.shared.fileTimeTolerance = m_spinCtrlFileTimeTolerance->GetValue();
- settings.shared.ignoreOneHourDiff = m_checkBoxIgnoreOneHour->GetValue();
+ settings.fileTimeTolerance = m_spinCtrlFileTimeTolerance->GetValue();
+ settings.ignoreOneHourDiff = m_checkBoxIgnoreOneHour->GetValue();
settings.gui.commandLineFileManager = m_textCtrlFileManager->GetValue();
@@ -595,7 +656,7 @@ void GlobalSettingsDlg::OnResetWarnings(wxCommandEvent& event)
{
wxMessageDialog* messageDlg = new wxMessageDialog(this, _("Reset all warning messages?"), _("Warning") , wxOK | wxCANCEL);
if (messageDlg->ShowModal() == wxID_OK)
- settings.shared.resetWarnings();
+ settings.warnings.resetWarnings();
}
@@ -803,7 +864,7 @@ SyncStatus::SyncStatus(StatusHandler* updater, wxWindow* parentWindow) :
lastStatCallSpeed(-1000000), //some big number
lastStatCallRemTime(-1000000)
{
- m_animationControl1->SetAnimation(*globalResource.animationSync);
+ m_animationControl1->SetAnimation(*GlobalResources::getInstance().animationSync);
m_animationControl1->Play();
//initialize gauge
@@ -943,37 +1004,37 @@ void SyncStatus::setCurrentStatus(SyncStatusID id)
switch (id)
{
case ABORTED:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusError);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusError);
m_staticTextStatus->SetLabel(_("Aborted"));
break;
case FINISHED_WITH_SUCCESS:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusSuccess);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusSuccess);
m_staticTextStatus->SetLabel(_("Completed"));
break;
case FINISHED_WITH_ERROR:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusWarning);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusWarning);
m_staticTextStatus->SetLabel(_("Completed"));
break;
case PAUSE:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusPause);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusPause);
m_staticTextStatus->SetLabel(_("Paused"));
break;
case SCANNING:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusScanning);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusScanning);
m_staticTextStatus->SetLabel(_("Scanning..."));
break;
case COMPARING_CONTENT:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusBinCompare);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusBinCompare);
m_staticTextStatus->SetLabel(_("Comparing content..."));
break;
case SYNCHRONIZING:
- m_bitmapStatus->SetBitmap(*globalResource.bitmapStatusSyncing);
+ m_bitmapStatus->SetBitmap(*GlobalResources::getInstance().bitmapStatusSyncing);
m_staticTextStatus->SetLabel(_("Synchronizing..."));
break;
}
diff --git a/ui/SmallDialogs.h b/ui/SmallDialogs.h
index 2c3e89d2..e9156665 100644
--- a/ui/SmallDialogs.h
+++ b/ui/SmallDialogs.h
@@ -143,7 +143,6 @@ class QuestionDlg : public QuestionDlgGenerated
{
public:
QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool& dontShowAgain);
- ~QuestionDlg();
enum
{
@@ -166,7 +165,6 @@ class CustomizeColsDlg : public CustomizeColsDlgGenerated
{
public:
CustomizeColsDlg(wxWindow* window, xmlAccess::ColumnAttributes& attr, bool& showFileIcons);
- ~CustomizeColsDlg() {}
enum
{
@@ -187,6 +185,32 @@ private:
};
+class SyncPreviewDlg : public SyncPreviewDlgGenerated
+{
+public:
+ SyncPreviewDlg(wxWindow* parentWindow,
+ const wxString& variantName,
+ const wxString& toCreate,
+ const wxString& toUpdate,
+ const wxString& toDelete,
+ const wxString& data,
+ bool& dontShowAgain);
+
+ enum
+ {
+ BUTTON_START = 1,
+ BUTTON_CANCEL = 2
+ };
+
+private:
+ void OnClose(wxCloseEvent& event);
+ void OnCancel(wxCommandEvent& event);
+ void OnStartSync(wxCommandEvent& event);
+
+ bool& m_dontShowAgain;
+};
+
+
class GlobalSettingsDlg : public GlobalSettingsDlgGenerated
{
public:
diff --git a/ui/SyncDialog.cpp b/ui/SyncDialog.cpp
index 2004a06c..58abc753 100644
--- a/ui/SyncDialog.cpp
+++ b/ui/SyncDialog.cpp
@@ -31,38 +31,30 @@ SyncDialog::SyncDialog(wxWindow* window,
updateConfigIcons(cfg.compareVar, localSyncConfiguration);
//set icons for this dialog
- m_bitmapLeftOnly->SetBitmap(*globalResource.bitmapLeftOnly);
- m_bitmapRightOnly->SetBitmap(*globalResource.bitmapRightOnly);
- m_bitmapLeftNewer->SetBitmap(*globalResource.bitmapLeftNewer);
- m_bitmapRightNewer->SetBitmap(*globalResource.bitmapRightNewer);
- m_bitmapDifferent->SetBitmap(*globalResource.bitmapDifferent);
+ m_bitmapLeftOnly->SetBitmap(*GlobalResources::getInstance().bitmapLeftOnly);
+ m_bitmapRightOnly->SetBitmap(*GlobalResources::getInstance().bitmapRightOnly);
+ m_bitmapLeftNewer->SetBitmap(*GlobalResources::getInstance().bitmapLeftNewer);
+ m_bitmapRightNewer->SetBitmap(*GlobalResources::getInstance().bitmapRightNewer);
+ m_bitmapDifferent->SetBitmap(*GlobalResources::getInstance().bitmapDifferent);
bSizer201->Layout(); //wxButtonWithImage size might have changed
//set radiobutton
- if ( localSyncConfiguration.exLeftSideOnly == SYNC_DIR_RIGHT &&
- localSyncConfiguration.exRightSideOnly == SYNC_DIR_RIGHT &&
- localSyncConfiguration.leftNewer == SYNC_DIR_RIGHT &&
- localSyncConfiguration.rightNewer == SYNC_DIR_RIGHT &&
- localSyncConfiguration.different == SYNC_DIR_RIGHT)
+ switch (localSyncConfiguration.getVariant())
+ {
+ case SyncConfiguration::MIRROR:
m_radioBtn1->SetValue(true); //one way ->
-
- else if (localSyncConfiguration.exLeftSideOnly == SYNC_DIR_RIGHT &&
- localSyncConfiguration.exRightSideOnly == SYNC_DIR_NONE &&
- localSyncConfiguration.leftNewer == SYNC_DIR_RIGHT &&
- localSyncConfiguration.rightNewer == SYNC_DIR_NONE &&
- localSyncConfiguration.different == SYNC_DIR_NONE)
+ break;
+ case SyncConfiguration::UPDATE:
m_radioBtnUpdate->SetValue(true); //Update ->
-
- else if (localSyncConfiguration.exLeftSideOnly == SYNC_DIR_RIGHT &&
- localSyncConfiguration.exRightSideOnly == SYNC_DIR_LEFT &&
- localSyncConfiguration.leftNewer == SYNC_DIR_RIGHT &&
- localSyncConfiguration.rightNewer == SYNC_DIR_LEFT &&
- localSyncConfiguration.different == SYNC_DIR_NONE)
+ break;
+ case SyncConfiguration::TWOWAY:
m_radioBtn2->SetValue(true); //two way <->
-
- else
+ break;
+ case SyncConfiguration::CUSTOM:
m_radioBtn3->SetValue(true); //other
+ break;
+ }
Fit();
}
@@ -106,112 +98,112 @@ void SyncDialog::updateConfigIcons(const CompareVariant compareVar,
switch (compareVar)
{
case CMP_BY_TIME_SIZE:
- buttonLeftOnly->Show();
- buttonRightOnly->Show();
- buttonLeftNewer->Show();
+ buttonLeftOnly ->Show();
+ buttonRightOnly ->Show();
+ buttonLeftNewer ->Show();
buttonRightNewer->Show();
- buttonDifferent->Hide();
+ buttonDifferent ->Hide();
- bitmapLeftOnly->Show();
- bitmapRightOnly->Show();
- bitmapLeftNewer->Show();
+ bitmapLeftOnly ->Show();
+ bitmapRightOnly ->Show();
+ bitmapLeftNewer ->Show();
bitmapRightNewer->Show();
- bitmapDifferent->Hide();
+ bitmapDifferent ->Hide();
break;
case CMP_BY_CONTENT:
- buttonLeftOnly->Show();
- buttonRightOnly->Show();
- buttonLeftNewer->Hide();
+ buttonLeftOnly ->Show();
+ buttonRightOnly ->Show();
+ buttonLeftNewer ->Hide();
buttonRightNewer->Hide();
- buttonDifferent->Show();
+ buttonDifferent ->Show();
- bitmapLeftOnly->Show();
- bitmapRightOnly->Show();
- bitmapLeftNewer->Hide();
+ bitmapLeftOnly ->Show();
+ bitmapRightOnly ->Show();
+ bitmapLeftNewer ->Hide();
bitmapRightNewer->Hide();
- bitmapDifferent->Show();
+ bitmapDifferent ->Show();
break;
}
if (syncConfig.exLeftSideOnly == SYNC_DIR_RIGHT)
{
- buttonLeftOnly->SetBitmapLabel(*globalResource.bitmapArrowRightCr);
+ buttonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowRightCr);
buttonLeftOnly->SetToolTip(_("Copy from left to right"));
}
else if (syncConfig.exLeftSideOnly == SYNC_DIR_LEFT)
{
- buttonLeftOnly->SetBitmapLabel(*globalResource.bitmapDeleteLeft);
+ buttonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapDeleteLeft);
buttonLeftOnly->SetToolTip(_("Delete files/folders existing on left side only"));
}
else if (syncConfig.exLeftSideOnly == SYNC_DIR_NONE)
{
- buttonLeftOnly->SetBitmapLabel(*globalResource.bitmapArrowNone);
+ buttonLeftOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowNone);
buttonLeftOnly->SetToolTip(_("Do nothing"));
}
if (syncConfig.exRightSideOnly == SYNC_DIR_RIGHT)
{
- buttonRightOnly->SetBitmapLabel(*globalResource.bitmapDeleteRight);
+ buttonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapDeleteRight);
buttonRightOnly->SetToolTip(_("Delete files/folders existing on right side only"));
}
else if (syncConfig.exRightSideOnly == SYNC_DIR_LEFT)
{
- buttonRightOnly->SetBitmapLabel(*globalResource.bitmapArrowLeftCr);
+ buttonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowLeftCr);
buttonRightOnly->SetToolTip(_("Copy from right to left"));
}
else if (syncConfig.exRightSideOnly == SYNC_DIR_NONE)
{
- buttonRightOnly->SetBitmapLabel(*globalResource.bitmapArrowNone);
+ buttonRightOnly->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowNone);
buttonRightOnly->SetToolTip(_("Do nothing"));
}
if (syncConfig.leftNewer == SYNC_DIR_RIGHT)
{
- buttonLeftNewer->SetBitmapLabel(*globalResource.bitmapArrowRight);
+ buttonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowRight);
buttonLeftNewer->SetToolTip(_("Copy from left to right overwriting"));
}
else if (syncConfig.leftNewer == SYNC_DIR_LEFT)
{
- buttonLeftNewer->SetBitmapLabel(*globalResource.bitmapArrowLeft);
+ buttonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowLeft);
buttonLeftNewer->SetToolTip(_("Copy from right to left overwriting"));
}
else if (syncConfig.leftNewer == SYNC_DIR_NONE)
{
- buttonLeftNewer->SetBitmapLabel(*globalResource.bitmapArrowNone);
+ buttonLeftNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowNone);
buttonLeftNewer->SetToolTip(_("Do nothing"));
}
if (syncConfig.rightNewer == SYNC_DIR_RIGHT)
{
- buttonRightNewer->SetBitmapLabel(*globalResource.bitmapArrowRight);
+ buttonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowRight);
buttonRightNewer->SetToolTip(_("Copy from left to right overwriting"));
}
else if (syncConfig.rightNewer == SYNC_DIR_LEFT)
{
- buttonRightNewer->SetBitmapLabel(*globalResource.bitmapArrowLeft);
+ buttonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowLeft);
buttonRightNewer->SetToolTip(_("Copy from right to left overwriting"));
}
else if (syncConfig.rightNewer == SYNC_DIR_NONE)
{
- buttonRightNewer->SetBitmapLabel(*globalResource.bitmapArrowNone);
+ buttonRightNewer->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowNone);
buttonRightNewer->SetToolTip(_("Do nothing"));
}
if (syncConfig.different == SYNC_DIR_RIGHT)
{
- buttonDifferent->SetBitmapLabel(*globalResource.bitmapArrowRight);
+ buttonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowRight);
buttonDifferent->SetToolTip(_("Copy from left to right overwriting"));
}
else if (syncConfig.different == SYNC_DIR_LEFT)
{
- buttonDifferent->SetBitmapLabel(*globalResource.bitmapArrowLeft);
+ buttonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowLeft);
buttonDifferent->SetToolTip(_("Copy from right to left overwriting"));
}
else if (syncConfig.different == SYNC_DIR_NONE)
{
- buttonDifferent->SetBitmapLabel(*globalResource.bitmapArrowNone);
+ buttonDifferent->SetBitmapLabel(*GlobalResources::getInstance().bitmapArrowNone);
buttonDifferent->SetToolTip(_("Do nothing"));
}
}
@@ -255,11 +247,7 @@ void SyncDialog::OnSelectRecycleBin(wxCommandEvent& event)
void SyncDialog::OnSyncLeftToRight(wxCommandEvent& event)
{
- localSyncConfiguration.exLeftSideOnly = SYNC_DIR_RIGHT;
- localSyncConfiguration.exRightSideOnly = SYNC_DIR_RIGHT;
- localSyncConfiguration.leftNewer = SYNC_DIR_RIGHT;
- localSyncConfiguration.rightNewer = SYNC_DIR_RIGHT;
- localSyncConfiguration.different = SYNC_DIR_RIGHT;
+ localSyncConfiguration.setVariant(SyncConfiguration::MIRROR);
updateConfigIcons(cfg.compareVar, localSyncConfiguration);
@@ -270,11 +258,7 @@ void SyncDialog::OnSyncLeftToRight(wxCommandEvent& event)
void SyncDialog::OnSyncUpdate(wxCommandEvent& event)
{
- localSyncConfiguration.exLeftSideOnly = SYNC_DIR_RIGHT;
- localSyncConfiguration.exRightSideOnly = SYNC_DIR_NONE;
- localSyncConfiguration.leftNewer = SYNC_DIR_RIGHT;
- localSyncConfiguration.rightNewer = SYNC_DIR_NONE;
- localSyncConfiguration.different = SYNC_DIR_NONE;
+ localSyncConfiguration.setVariant(SyncConfiguration::UPDATE);
updateConfigIcons(cfg.compareVar, localSyncConfiguration);
@@ -285,11 +269,7 @@ void SyncDialog::OnSyncUpdate(wxCommandEvent& event)
void SyncDialog::OnSyncBothSides(wxCommandEvent& event)
{
- localSyncConfiguration.exLeftSideOnly = SYNC_DIR_RIGHT;
- localSyncConfiguration.exRightSideOnly = SYNC_DIR_LEFT;
- localSyncConfiguration.leftNewer = SYNC_DIR_RIGHT;
- localSyncConfiguration.rightNewer = SYNC_DIR_LEFT;
- localSyncConfiguration.different = SYNC_DIR_NONE;
+ localSyncConfiguration.setVariant(SyncConfiguration::TWOWAY);
updateConfigIcons(cfg.compareVar, localSyncConfiguration);
@@ -430,14 +410,14 @@ void BatchDialog::init()
dragDropOnLogfileDir.reset(new DragDropOnDlg(m_panelLogging, m_dirPickerLogfileDir, m_textCtrlLogfileDir));
//set icons for this dialog
- m_bitmapLeftOnly->SetBitmap(*globalResource.bitmapLeftOnly);
- m_bitmapRightOnly->SetBitmap(*globalResource.bitmapRightOnly);
- m_bitmapLeftNewer->SetBitmap(*globalResource.bitmapLeftNewer);
- m_bitmapRightNewer->SetBitmap(*globalResource.bitmapRightNewer);
- m_bitmapDifferent->SetBitmap(*globalResource.bitmapDifferent);
- m_bitmap8->SetBitmap(*globalResource.bitmapInclude);
- m_bitmap9->SetBitmap(*globalResource.bitmapExclude);
- m_bitmap27->SetBitmap(*globalResource.bitmapBatch);
+ m_bitmapLeftOnly->SetBitmap(*GlobalResources::getInstance().bitmapLeftOnly);
+ m_bitmapRightOnly->SetBitmap(*GlobalResources::getInstance().bitmapRightOnly);
+ m_bitmapLeftNewer->SetBitmap(*GlobalResources::getInstance().bitmapLeftNewer);
+ m_bitmapRightNewer->SetBitmap(*GlobalResources::getInstance().bitmapRightNewer);
+ m_bitmapDifferent->SetBitmap(*GlobalResources::getInstance().bitmapDifferent);
+ m_bitmap8->SetBitmap(*GlobalResources::getInstance().bitmapInclude);
+ m_bitmap9->SetBitmap(*GlobalResources::getInstance().bitmapExclude);
+ m_bitmap27->SetBitmap(*GlobalResources::getInstance().bitmapBatch);
}
diff --git a/ui/batchStatusHandler.cpp b/ui/batchStatusHandler.cpp
index 716dccd5..f7f0df9f 100644
--- a/ui/batchStatusHandler.cpp
+++ b/ui/batchStatusHandler.cpp
@@ -14,13 +14,13 @@ public:
LogFile(const wxString& logfileDirectory)
{
//create logfile directory
- const Zstring logfileDir = logfileDirectory.empty() ? wxT("Logs") : logfileDirectory.c_str();
+ const Zstring logfileDir = logfileDirectory.empty() ? FreeFileSync::getDefaultLogDirectory().c_str() : logfileDirectory.c_str();
if (!wxDirExists(logfileDir))
try
{
FreeFileSync::createDirectory(logfileDir, Zstring(), false);
}
- catch (FileError&)
+ catch (FreeFileSync::FileError&)
{
readyToWrite = false;
return;
@@ -29,10 +29,10 @@ public:
//assemble logfile name
wxString logfileName = logfileDir.c_str();
if (!FreeFileSync::endsWithPathSeparator(logfileName.c_str()))
- logfileName += GlobalResources::FILE_NAME_SEPARATOR;
+ logfileName += FreeFileSync::FILE_NAME_SEPARATOR;
wxString timeNow = wxDateTime::Now().FormatISOTime();
- timeNow.Replace(wxT(":"), wxEmptyString);
- logfileName += wxT("FFS_") + wxDateTime::Now().FormatISODate() + wxChar('_') + timeNow + wxT(".log");
+ timeNow.Replace(wxT(":"), wxT("-"));
+ logfileName += wxDateTime::Now().FormatISODate() + wxChar(' ') + timeNow + wxT(".log");
logFile.Open(logfileName.c_str(), wxT("w"));
@@ -111,9 +111,9 @@ public:
m_statusHandler(statusHandler),
processPaused(false)
{
- running.reset(new wxIcon(*globalResource.programIcon));
+ running.reset(new wxIcon(*GlobalResources::getInstance().programIcon));
paused.reset(new wxIcon);
- paused->CopyFromBitmap(*globalResource.bitmapFFSPaused);
+ paused->CopyFromBitmap(*GlobalResources::getInstance().bitmapFFSPaused);
wxTaskBarIcon::SetIcon(*running);
}
diff --git a/ui/gridView.cpp b/ui/gridView.cpp
index aa309970..aa1867fd 100644
--- a/ui/gridView.cpp
+++ b/ui/gridView.cpp
@@ -4,7 +4,7 @@
using FreeFileSync::GridView;
-GridView::GridView(FolderComparison& results) :
+GridView::GridView(FreeFileSync::FolderComparison& results) :
leftOnlyFilesActive(false),
rightOnlyFilesActive(false),
leftNewerFilesActive(false),
@@ -48,26 +48,24 @@ GridView::StatusInfo GridView::update_sub(const bool hideFiltered)
{
const FileComparison& fileCmp = j->fileCmp;
- output.objectsTotal += j->fileCmp.size();
-
RefIndex newEntry;
newEntry.folderIndex = j - folderCmp.begin();
for (FileComparison::const_iterator i = fileCmp.begin(); i != fileCmp.end(); ++i)
{
- //hide filtered row, if corresponding option is set
- if (hideFiltered && !i->selectedForSynchronization)
- continue;
-
//process UI filter settings
if (syncPreviewActive) //synchronization preview
{
//exclude result "=="
- if (i->cmpResult == FILE_EQUAL) //note: consider elementsTotal()!
- {
- --output.objectsTotal;
+ if (i->cmpResult == FILE_EQUAL) //note: consider "objectsTotal"
continue;
- }
+
+ output.objectsTotal++;
+
+ //hide filtered row, if corresponding option is set
+ if (hideFiltered && !i->selectedForSynchronization) //keep AFTER "objectsTotal++"
+ continue;
+
switch (i->direction)
{
@@ -91,6 +89,12 @@ GridView::StatusInfo GridView::update_sub(const bool hideFiltered)
}
else //comparison results view
{
+ output.objectsTotal++;
+
+ //hide filtered row, if corresponding option is set
+ if (hideFiltered && !i->selectedForSynchronization)
+ continue;
+
switch (i->cmpResult)
{
case FILE_LEFT_SIDE_ONLY:
@@ -164,13 +168,13 @@ GridView::StatusInfo GridView::update(const bool hideFiltered, const bool syncPr
}
-void GridView::viewRefToFolderRef(const std::set<int>& viewRef, FolderCompRef& output)
+void GridView::viewRefToFolderRef(const std::set<int>& viewRef, FreeFileSync::FolderCompRef& output)
{
output.clear();
for (int i = 0; i < int(folderCmp.size()); ++i)
output.push_back(std::set<int>()); //avoid copy by value for full set<int>
- for (std::set<int>::iterator i = viewRef.begin(); i != viewRef.end(); ++i)
+ for (std::set<int>::const_iterator i = viewRef.begin(); i != viewRef.end(); ++i)
{
const unsigned int folder = refView[*i].folderIndex;
const unsigned int row = refView[*i].rowIndex;
@@ -261,6 +265,10 @@ void GridView::sortView(const SortType type, const bool onLeft, const bool ascen
if ( ascending) std::sort(fileCmp.begin(), fileCmp.end(), sortByCmpResult<ASCENDING>);
else if (!ascending) std::sort(fileCmp.begin(), fileCmp.end(), sortByCmpResult<DESCENDING>);
break;
+ case SORT_BY_SYNC_DIRECTION:
+ if ( ascending) std::sort(fileCmp.begin(), fileCmp.end(), sortBySyncDirection<ASCENDING>);
+ else if (!ascending) std::sort(fileCmp.begin(), fileCmp.end(), sortBySyncDirection<DESCENDING>);
+ break;
default:
assert(false);
}
diff --git a/ui/gridView.h b/ui/gridView.h
index 2a4d4e29..b531093d 100644
--- a/ui/gridView.h
+++ b/ui/gridView.h
@@ -78,7 +78,8 @@ namespace FreeFileSync
SORT_BY_FILESIZE,
SORT_BY_DATE,
SORT_BY_CMP_RESULT,
- SORT_BY_DIRECTORY
+ SORT_BY_DIRECTORY,
+ SORT_BY_SYNC_DIRECTION
};
void sortView(const SortType type, const bool onLeft, const bool ascending);
diff --git a/ui/guiGenerated.cpp b/ui/guiGenerated.cpp
index 4819f9e6..de21b0f8 100644
--- a/ui/guiGenerated.cpp
+++ b/ui/guiGenerated.cpp
@@ -14,7 +14,7 @@
MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+ this->SetSizeHints( wxSize( 640,400 ), wxDefaultSize );
m_menubar1 = new wxMenuBar( 0 );
m_menuFile = new wxMenu();
@@ -49,45 +49,6 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_menuAdvanced = new wxMenu();
m_menuLanguages = new wxMenu();
- m_menuItemGerman = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Deutsch") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemGerman );
-
- m_menuItemEnglish = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("English") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemEnglish );
-
- m_menuItemSpanish = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Español") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemSpanish );
-
- m_menuItemFrench = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Français") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemFrench );
-
- m_menuItemItalian = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Italiano") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemItalian );
-
- m_menuItemHungarian = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Magyar") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemHungarian );
-
- m_menuItemDutch = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Nederlands") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemDutch );
-
- m_menuItemPolish = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Polski") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemPolish );
-
- m_menuItemPortuguese = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Português") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemPortuguese );
-
- m_menuItemPortugueseBrazil = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Português do Brasil") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemPortugueseBrazil );
-
- m_menuItemSlovenian = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("Slovenščina") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemSlovenian );
-
- m_menuItemJapanese = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("日本語") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemJapanese );
-
- m_menuItemChineseSimple = new wxMenuItem( m_menuLanguages, wxID_ANY, wxString( _("简体中文") ) , wxEmptyString, wxITEM_NORMAL );
- m_menuLanguages->Append( m_menuItemChineseSimple );
-
m_menuAdvanced->Append( -1, _("&Language"), m_menuLanguages );
m_menuAdvanced->AppendSeparator();
@@ -184,54 +145,35 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer6->Add( 0, 0, 1, 0, 5 );
- wxBoxSizer* bSizer56;
- bSizer56 = new wxBoxSizer( wxVERTICAL );
-
- wxStaticBoxSizer* sbSizer9;
- sbSizer9 = new wxStaticBoxSizer( new wxStaticBox( m_panel71, wxID_ANY, _("Filter files") ), wxHORIZONTAL );
-
- m_bpButtonFilter = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
- sbSizer9->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
-
- wxBoxSizer* bSizer23;
- bSizer23 = new wxBoxSizer( wxVERTICAL );
-
- m_hyperlinkCfgFilter = new wxHyperlinkCtrl( m_panel71, wxID_ANY, _("Configure filter..."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
-
- m_hyperlinkCfgFilter->SetNormalColour( wxColour( 0, 0, 255 ) );
- m_hyperlinkCfgFilter->SetVisitedColour( wxColour( 0, 0, 255 ) );
- bSizer23->Add( m_hyperlinkCfgFilter, 0, wxALL, 5 );
-
- m_checkBoxHideFilt = new wxCheckBox( m_panel71, wxID_ANY, _("Hide filtered items"), wxDefaultPosition, wxDefaultSize, 0 );
-
- m_checkBoxHideFilt->SetToolTip( _("Choose to hide filtered files/directories from list") );
-
- bSizer23->Add( m_checkBoxHideFilt, 0, 0, 5 );
-
- sbSizer9->Add( bSizer23, 0, 0, 5 );
-
- bSizer56->Add( sbSizer9, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
+ wxFlexGridSizer* fgSizer12;
+ fgSizer12 = new wxFlexGridSizer( 2, 2, 0, 0 );
+ fgSizer12->SetFlexibleDirection( wxBOTH );
+ fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
- bSizer56->Add( 0, 4, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- bSizer6->Add( bSizer56, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ fgSizer12->Add( 0, 0, 1, wxEXPAND, 5 );
+ m_staticTextVariant = new wxStaticText( m_panel71, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextVariant->Wrap( -1 );
+ m_staticTextVariant->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) );
+ m_staticTextVariant->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
- bSizer6->Add( 20, 0, 0, 0, 5 );
+ fgSizer12->Add( m_staticTextVariant, 1, wxALIGN_CENTER_HORIZONTAL, 5 );
m_bpButtonSyncConfig = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,40 ), wxBU_AUTODRAW );
m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") );
m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") );
- bSizer6->Add( m_bpButtonSyncConfig, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
+ fgSizer12->Add( m_bpButtonSyncConfig, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
- m_buttonStartSync = new wxButtonWithImage( m_panel71, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
+ m_buttonStartSync = new wxButtonWithImage( m_panel71, wxID_ANY, _("Synchronize..."), wxDefaultPosition, wxSize( -1,40 ), 0 );
m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) );
m_buttonStartSync->SetToolTip( _("Start synchronization") );
- bSizer6->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ fgSizer12->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer6->Add( fgSizer12, 0, wxALIGN_CENTER_VERTICAL, 5 );
bSizer6->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 );
@@ -270,17 +212,18 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer93 = new wxBoxSizer( wxVERTICAL );
- bSizer93->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer93->Add( 0, 3, 0, 0, 5 );
bSizerMiddle = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonSwitchView = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 44,44 ), wxBU_AUTODRAW );
- bSizerMiddle->Add( m_bpButtonSwitchView, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+ m_bpButtonSwapSides = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW );
+ m_bpButtonSwapSides->SetToolTip( _("Swap sides") );
- bSizer93->Add( bSizerMiddle, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ m_bpButtonSwapSides->SetToolTip( _("Swap sides") );
+ bSizerMiddle->Add( m_bpButtonSwapSides, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
- bSizer93->Add( 0, 0, 0, 0, 5 );
+ bSizer93->Add( bSizerMiddle, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
m_panelTopMiddle->SetSizer( bSizer93 );
m_panelTopMiddle->Layout();
@@ -297,15 +240,19 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer781;
bSizer781 = new wxBoxSizer( wxVERTICAL );
-
- bSizer781->Add( 0, 3, 0, 0, 5 );
-
m_bpButtonAddPair = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW );
m_bpButtonAddPair->SetToolTip( _("Add folder pair") );
m_bpButtonAddPair->SetToolTip( _("Add folder pair") );
- bSizer781->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 5 );
+ bSizer781->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 3 );
+
+ m_bpButtonRemoveTopPair = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW );
+ m_bpButtonRemoveTopPair->SetToolTip( _("Remove folder pair") );
+
+ m_bpButtonRemoveTopPair->SetToolTip( _("Remove folder pair") );
+
+ bSizer781->Add( m_bpButtonRemoveTopPair, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
bSizer77->Add( bSizer781, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
@@ -320,7 +267,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
sbSizer3->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 );
- bSizer77->Add( sbSizer3, 1, wxRIGHT|wxLEFT, 3 );
+ bSizer77->Add( sbSizer3, 1, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 3 );
bSizer94->Add( bSizer77, 0, wxEXPAND, 5 );
@@ -471,31 +418,66 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
wxBoxSizer* bSizer120;
bSizer120 = new wxBoxSizer( wxVERTICAL );
- wxStaticBoxSizer* sbSizer16;
- sbSizer16 = new wxStaticBoxSizer( new wxStaticBox( m_panel4, wxID_ANY, _("Configuration") ), wxHORIZONTAL );
+ m_notebookBottomLeft = new wxNotebook( m_panel4, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+ m_panel30 = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* bSizer139;
+ bSizer139 = new wxBoxSizer( wxHORIZONTAL );
- m_bpButtonSave = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
+ m_bpButtonSave = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
m_bpButtonSave->SetToolTip( _("Save current configuration to file") );
m_bpButtonSave->SetToolTip( _("Save current configuration to file") );
- sbSizer16->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer139->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_bpButtonLoad = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
+ m_bpButtonLoad = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW );
m_bpButtonLoad->SetToolTip( _("Load configuration from file") );
m_bpButtonLoad->SetToolTip( _("Load configuration from file") );
- sbSizer16->Add( m_bpButtonLoad, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+ bSizer139->Add( m_bpButtonLoad, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
wxArrayString m_choiceHistoryChoices;
- m_choiceHistory = new wxChoice( m_panel4, wxID_ANY, wxDefaultPosition, wxSize( 150,-1 ), m_choiceHistoryChoices, 0 );
+ m_choiceHistory = new wxChoice( m_panel30, wxID_ANY, wxDefaultPosition, wxSize( 150,-1 ), m_choiceHistoryChoices, 0 );
m_choiceHistory->SetSelection( 0 );
m_choiceHistory->SetToolTip( _("Load configuration history (press DEL to delete items)") );
- sbSizer16->Add( m_choiceHistory, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer139->Add( m_choiceHistory, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_panel30->SetSizer( bSizer139 );
+ m_panel30->Layout();
+ bSizer139->Fit( m_panel30 );
+ m_notebookBottomLeft->AddPage( m_panel30, _("Configuration"), true );
+ m_panelFilter = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ wxBoxSizer* bSizer140;
+ bSizer140 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bpButtonFilter = new wxBitmapButton( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE );
+ bSizer140->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+
+ wxBoxSizer* bSizer23;
+ bSizer23 = new wxBoxSizer( wxVERTICAL );
+
+ m_hyperlinkCfgFilter = new wxHyperlinkCtrl( m_panelFilter, wxID_ANY, _("Configure filter..."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE );
+
+ m_hyperlinkCfgFilter->SetNormalColour( wxColour( 0, 0, 255 ) );
+ m_hyperlinkCfgFilter->SetVisitedColour( wxColour( 0, 0, 255 ) );
+ bSizer23->Add( m_hyperlinkCfgFilter, 0, wxALL, 5 );
+
+ m_checkBoxHideFilt = new wxCheckBox( m_panelFilter, wxID_ANY, _("Hide filtered items"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ m_checkBoxHideFilt->SetToolTip( _("Choose to hide filtered files/directories from list") );
- bSizer120->Add( sbSizer16, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer23->Add( m_checkBoxHideFilt, 0, 0, 5 );
+
+ bSizer140->Add( bSizer23, 0, 0, 5 );
+
+ m_panelFilter->SetSizer( bSizer140 );
+ m_panelFilter->Layout();
+ bSizer140->Fit( m_panelFilter );
+ m_notebookBottomLeft->AddPage( m_panelFilter, _("Filter files"), false );
+
+ bSizer120->Add( m_notebookBottomLeft, 0, wxALL, 5 );
bSizer3->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
@@ -550,18 +532,17 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
bSizer64->Fit( m_panel112 );
bSizer3->Add( m_panel112, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
- wxBoxSizer* bSizer66;
- bSizer66 = new wxBoxSizer( wxHORIZONTAL );
+ bSizerBottomRight = new wxBoxSizer( wxHORIZONTAL );
- bSizer66->Add( 0, 0, 1, 0, 5 );
+ bSizerBottomRight->Add( 5, 0, 1, 0, 5 );
m_panelSyncPreview = new wxPanel( m_panel4, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer121;
bSizer121 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer161;
- sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( m_panelSyncPreview, wxID_ANY, _("Preview") ), wxHORIZONTAL );
+ sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( m_panelSyncPreview, wxID_ANY, _("Statistics") ), wxHORIZONTAL );
wxFlexGridSizer* fgSizer5;
fgSizer5 = new wxFlexGridSizer( 2, 2, 0, 5 );
@@ -630,16 +611,16 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_panelSyncPreview->SetSizer( bSizer121 );
m_panelSyncPreview->Layout();
bSizer121->Fit( m_panelSyncPreview );
- bSizer66->Add( m_panelSyncPreview, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerBottomRight->Add( m_panelSyncPreview, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_bpButton10 = new wxBitmapButton( m_panel4, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 50,50 ), wxBU_AUTODRAW );
m_bpButton10->SetToolTip( _("Quit") );
m_bpButton10->SetToolTip( _("Quit") );
- bSizer66->Add( m_bpButton10, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 );
+ bSizerBottomRight->Add( m_bpButton10, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 );
- bSizer3->Add( bSizer66, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
+ bSizer3->Add( bSizerBottomRight, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
m_panel4->SetSizer( bSizer3 );
m_panel4->Layout();
@@ -727,19 +708,6 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
this->Connect( m_menuItem14->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuSaveConfig ) );
this->Connect( m_menuItem13->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLoadConfig ) );
this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) );
- this->Connect( m_menuItemGerman->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangGerman ) );
- this->Connect( m_menuItemEnglish->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangEnglish ) );
- this->Connect( m_menuItemSpanish->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangSpanish ) );
- this->Connect( m_menuItemFrench->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangFrench ) );
- this->Connect( m_menuItemItalian->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangItalian ) );
- this->Connect( m_menuItemHungarian->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangHungarian ) );
- this->Connect( m_menuItemDutch->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangDutch ) );
- this->Connect( m_menuItemPolish->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPolish ) );
- this->Connect( m_menuItemPortuguese->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortuguese ) );
- this->Connect( m_menuItemPortugueseBrazil->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortugueseBrazil ) );
- this->Connect( m_menuItemSlovenian->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangSlovenian ) );
- this->Connect( m_menuItemJapanese->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangJapanese ) );
- this->Connect( m_menuItemChineseSimple->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangChineseSimp ) );
this->Connect( m_menuItemGlobSett->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) );
this->Connect( m_menuItem7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) );
this->Connect( m_menuItem5->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) );
@@ -750,31 +718,33 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const
m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByTimeSize ), NULL, this );
m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByContent ), NULL, this );
m_bpButton14->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnShowHelpDialog ), NULL, this );
- m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this );
- m_hyperlinkCfgFilter->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this );
- m_checkBoxHideFilt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this );
m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this );
m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this );
m_directoryLeft->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this );
m_dirPickerLeft->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this );
- m_bpButtonSwitchView->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ), NULL, this );
+ m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this );
m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this );
+ m_bpButtonRemoveTopPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRemoveTopFolderPair ), NULL, this );
m_directoryRight->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this );
m_dirPickerRight->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this );
m_gridLeft->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this );
- m_gridLeft->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenu ), NULL, this );
+ m_gridLeft->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this );
m_gridLeft->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this );
- m_gridLeft->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextColumnLeft ), NULL, this );
- m_gridMiddle->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenuMiddle ), NULL, this );
+ m_gridLeft->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this );
+ m_gridMiddle->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this );
m_gridMiddle->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this );
+ m_gridMiddle->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this );
m_gridRight->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this );
- m_gridRight->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenu ), NULL, this );
+ m_gridRight->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this );
m_gridRight->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this );
- m_gridRight->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextColumnRight ), NULL, this );
+ m_gridRight->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this );
m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this );
m_bpButtonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this );
m_choiceHistory->Connect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this );
m_choiceHistory->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this );
+ m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this );
+ m_hyperlinkCfgFilter->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this );
+ m_checkBoxHideFilt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this );
m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this );
m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this );
m_bpButtonEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this );
@@ -798,19 +768,6 @@ MainDialogGenerated::~MainDialogGenerated()
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuSaveConfig ) );
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLoadConfig ) );
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangGerman ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangEnglish ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangSpanish ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangFrench ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangItalian ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangHungarian ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangDutch ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPolish ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortuguese ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortugueseBrazil ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangSlovenian ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangJapanese ) );
- this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangChineseSimp ) );
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) );
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) );
this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) );
@@ -821,31 +778,33 @@ MainDialogGenerated::~MainDialogGenerated()
m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByTimeSize ), NULL, this );
m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByContent ), NULL, this );
m_bpButton14->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnShowHelpDialog ), NULL, this );
- m_bpButtonFilter->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this );
- m_hyperlinkCfgFilter->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this );
- m_checkBoxHideFilt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this );
m_bpButtonSyncConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this );
m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this );
m_directoryLeft->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this );
m_dirPickerLeft->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this );
- m_bpButtonSwitchView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ), NULL, this );
+ m_bpButtonSwapSides->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this );
m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this );
+ m_bpButtonRemoveTopPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRemoveTopFolderPair ), NULL, this );
m_directoryRight->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this );
m_dirPickerRight->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this );
m_gridLeft->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this );
- m_gridLeft->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenu ), NULL, this );
+ m_gridLeft->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this );
m_gridLeft->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this );
- m_gridLeft->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextColumnLeft ), NULL, this );
- m_gridMiddle->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenuMiddle ), NULL, this );
+ m_gridLeft->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this );
+ m_gridMiddle->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this );
m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this );
+ m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this );
m_gridRight->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this );
- m_gridRight->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMenu ), NULL, this );
+ m_gridRight->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this );
m_gridRight->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this );
- m_gridRight->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextColumnRight ), NULL, this );
+ m_gridRight->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this );
m_bpButtonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this );
m_bpButtonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this );
m_choiceHistory->Disconnect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this );
m_choiceHistory->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this );
+ m_bpButtonFilter->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this );
+ m_hyperlinkCfgFilter->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this );
+ m_checkBoxHideFilt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this );
m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this );
m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this );
m_bpButtonEqual->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this );
@@ -1729,7 +1688,7 @@ SyncDlgGenerated::SyncDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
bSizer201->Add( m_checkBoxIgnoreErrors, 0, wxALL, 5 );
- bSizer29->Add( bSizer201, 0, 0, 5 );
+ bSizer29->Add( bSizer201, 0, wxTOP|wxBOTTOM, 5 );
bSizer29->Add( 0, 5, 1, 0, 5 );
@@ -1741,7 +1700,7 @@ SyncDlgGenerated::SyncDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr
m_button6->SetDefault();
m_button6->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) );
- bSizer291->Add( m_button6, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 );
+ bSizer291->Add( m_button6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) );
@@ -2376,156 +2335,33 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS
bSizer73->Fit( m_scrolledWindow4 );
bSizer53->Add( m_scrolledWindow4, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 10 );
- m_scrolledWindow3 = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL );
- m_scrolledWindow3->SetScrollRate( 5, 5 );
- m_scrolledWindow3->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) );
- m_scrolledWindow3->SetMinSize( wxSize( -1,140 ) );
- m_scrolledWindow3->SetMaxSize( wxSize( -1,140 ) );
+ m_scrolledWindowTranslators = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL );
+ m_scrolledWindowTranslators->SetScrollRate( 5, 5 );
+ m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) );
+ m_scrolledWindowTranslators->SetMinSize( wxSize( -1,140 ) );
+ m_scrolledWindowTranslators->SetMaxSize( wxSize( -1,140 ) );
- wxBoxSizer* bSizer72;
- bSizer72 = new wxBoxSizer( wxVERTICAL );
+ bSizerTranslators = new wxBoxSizer( wxVERTICAL );
- m_staticText54 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Big thanks for localizing FreeFileSync goes out to:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText54 = new wxStaticText( m_scrolledWindowTranslators, wxID_ANY, _("Big thanks for localizing FreeFileSync goes out to:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText54->Wrap( -1 );
m_staticText54->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) );
- bSizer72->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 );
-
-
- bSizer72->Add( 0, 5, 0, 0, 5 );
-
- wxFlexGridSizer* fgSizer9;
- fgSizer9 = new wxFlexGridSizer( 1, 3, 5, 20 );
- fgSizer9->SetFlexibleDirection( wxBOTH );
- fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
-
- m_bitmapFrench = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapFrench, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText68 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Jean-François Hartmann"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText68->Wrap( -1 );
- fgSizer9->Add( m_staticText68, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText69 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Français"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText69->Wrap( -1 );
- fgSizer9->Add( m_staticText69, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapJapanese = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapJapanese, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticText70 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Tilt"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText70->Wrap( -1 );
- fgSizer9->Add( m_staticText70, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText71 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("日本語"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText71->Wrap( -1 );
- fgSizer9->Add( m_staticText71, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapDutch = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapDutch, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText711 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("M.D. Vrakking"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText711->Wrap( -1 );
- fgSizer9->Add( m_staticText711, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText712 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Nederlands"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText712->Wrap( -1 );
- fgSizer9->Add( m_staticText712, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapChineseSimple = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapChineseSimple, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticText91 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Misty Wu"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText91->Wrap( -1 );
- fgSizer9->Add( m_staticText91, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText92 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("简体中文"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText92->Wrap( -1 );
- fgSizer9->Add( m_staticText92, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapPolish = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapPolish, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText911 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Wojtek Pietruszewski"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText911->Wrap( -1 );
- fgSizer9->Add( m_staticText911, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText921 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Polski"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText921->Wrap( -1 );
- fgSizer9->Add( m_staticText921, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapPortuguese = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapPortuguese, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+ bSizerTranslators->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 );
- m_staticText9211 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("QuestMark"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText9211->Wrap( -1 );
- fgSizer9->Add( m_staticText9211, 0, wxALIGN_CENTER_VERTICAL, 5 );
- m_staticText9212 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Português"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText9212->Wrap( -1 );
- fgSizer9->Add( m_staticText9212, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerTranslators->Add( 0, 5, 0, 0, 5 );
- m_bitmapItalian = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapItalian, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+ fgSizerTranslators = new wxFlexGridSizer( 1, 3, 5, 20 );
+ fgSizerTranslators->SetFlexibleDirection( wxBOTH );
+ fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
- m_staticText92121 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Emmo"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText92121->Wrap( -1 );
- fgSizer9->Add( m_staticText92121, 0, wxALIGN_CENTER_VERTICAL, 5 );
+ bSizerTranslators->Add( fgSizerTranslators, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
- m_staticText92122 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Italiano"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText92122->Wrap( -1 );
- fgSizer9->Add( m_staticText92122, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapSlovenian = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapSlovenian, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText921221 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Matej Badalic"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText921221->Wrap( -1 );
- fgSizer9->Add( m_staticText921221, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText921222 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Slovenščina"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText921222->Wrap( -1 );
- fgSizer9->Add( m_staticText921222, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapHungarian = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapHungarian, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText682 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Demon"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText682->Wrap( -1 );
- fgSizer9->Add( m_staticText682, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText681 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Magyar"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText681->Wrap( -1 );
- fgSizer9->Add( m_staticText681, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapSpanish = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapSpanish, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_staticText683 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("David Rodríguez"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText683->Wrap( -1 );
- fgSizer9->Add( m_staticText683, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText691 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Español"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText691->Wrap( -1 );
- fgSizer9->Add( m_staticText691, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_bitmapPortugueseBrazil = new wxStaticBitmap( m_scrolledWindow3, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,11 ), 0 );
- fgSizer9->Add( m_bitmapPortugueseBrazil, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText684 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Edison Aranha"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText684->Wrap( -1 );
- fgSizer9->Add( m_staticText684, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- m_staticText685 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Português do Brasil"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticText685->Wrap( -1 );
- fgSizer9->Add( m_staticText685, 0, wxALIGN_CENTER_VERTICAL, 5 );
-
- bSizer72->Add( fgSizer9, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
-
- m_scrolledWindow3->SetSizer( bSizer72 );
- m_scrolledWindow3->Layout();
- bSizer72->Fit( m_scrolledWindow3 );
- bSizer53->Add( m_scrolledWindow3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+ m_scrolledWindowTranslators->SetSizer( bSizerTranslators );
+ m_scrolledWindowTranslators->Layout();
+ bSizerTranslators->Fit( m_scrolledWindowTranslators );
+ bSizer53->Add( m_scrolledWindowTranslators, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
bSizer31->Add( bSizer53, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 25 );
@@ -2741,7 +2577,7 @@ WarningDlgGenerated::WarningDlgGenerated( wxWindow* parent, wxWindowID id, const
bSizer24->Add( 0, 10, 0, wxEXPAND, 5 );
- m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this warning again"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer24->Add( m_checkBoxDontShowAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 );
@@ -2965,7 +2801,7 @@ FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const w
wxBoxSizer* bSizer72;
bSizer72 = new wxBoxSizer( wxVERTICAL );
- m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Synchronization filter"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Filter files"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText56->Wrap( -1 );
m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) );
@@ -3407,3 +3243,137 @@ GlobalSettingsDlgGenerated::~GlobalSettingsDlgGenerated()
m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this );
m_button29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this );
}
+
+SyncPreviewDlgGenerated::SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
+{
+ this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+
+ wxBoxSizer* bSizer134;
+ bSizer134 = new wxBoxSizer( wxVERTICAL );
+
+ wxStaticBoxSizer* sbSizer28;
+ sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Variant") ), wxVERTICAL );
+
+ m_staticTextVariant = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextVariant->Wrap( -1 );
+ m_staticTextVariant->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) );
+
+ sbSizer28->Add( m_staticTextVariant, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ bSizer134->Add( sbSizer28, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+ wxBoxSizer* bSizer141;
+ bSizer141 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_buttonStartSync = new wxButtonWithImage( this, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 );
+ m_buttonStartSync->SetDefault();
+ m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) );
+ m_buttonStartSync->SetToolTip( _("Start synchronization") );
+
+ bSizer141->Add( m_buttonStartSync, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL );
+ bSizer141->Add( m_staticline14, 0, wxEXPAND|wxRIGHT, 5 );
+
+
+ bSizer141->Add( 0, 0, 1, wxEXPAND, 5 );
+
+ wxStaticBoxSizer* sbSizer161;
+ sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Statistics") ), wxHORIZONTAL );
+
+ wxFlexGridSizer* fgSizer5;
+ fgSizer5 = new wxFlexGridSizer( 4, 2, 0, 5 );
+ fgSizer5->SetFlexibleDirection( wxHORIZONTAL );
+ fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+ m_bitmapCreate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapCreate->SetToolTip( _("Number of files and directories that will be created") );
+
+ fgSizer5->Add( m_bitmapCreate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_textCtrlCreate = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY );
+ m_textCtrlCreate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) );
+ m_textCtrlCreate->SetBackgroundColour( wxColour( 222, 222, 236 ) );
+ m_textCtrlCreate->SetToolTip( _("Number of files and directories that will be created") );
+
+ fgSizer5->Add( m_textCtrlCreate, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapDelete = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapDelete->SetToolTip( _("Number of files and directories that will be deleted") );
+
+ fgSizer5->Add( m_bitmapDelete, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_textCtrlDelete = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY );
+ m_textCtrlDelete->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) );
+ m_textCtrlDelete->SetBackgroundColour( wxColour( 222, 222, 236 ) );
+ m_textCtrlDelete->SetToolTip( _("Number of files and directories that will be deleted") );
+
+ fgSizer5->Add( m_textCtrlDelete, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapUpdate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapUpdate->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer5->Add( m_bitmapUpdate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_textCtrlUpdate = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY );
+ m_textCtrlUpdate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) );
+ m_textCtrlUpdate->SetBackgroundColour( wxColour( 222, 222, 236 ) );
+ m_textCtrlUpdate->SetToolTip( _("Number of files that will be overwritten") );
+
+ fgSizer5->Add( m_textCtrlUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_bitmapData = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+ m_bitmapData->SetToolTip( _("Total amount of data that will be transferred") );
+
+ fgSizer5->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ m_textCtrlData = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY );
+ m_textCtrlData->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) );
+ m_textCtrlData->SetBackgroundColour( wxColour( 222, 222, 236 ) );
+ m_textCtrlData->SetToolTip( _("Total amount of data that will be transferred") );
+
+ fgSizer5->Add( m_textCtrlData, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ sbSizer161->Add( fgSizer5, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
+
+ bSizer141->Add( sbSizer161, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+ bSizer134->Add( bSizer141, 0, wxEXPAND, 5 );
+
+ m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer134->Add( m_staticline12, 0, wxEXPAND|wxBOTTOM, 5 );
+
+ wxBoxSizer* bSizer142;
+ bSizer142 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 );
+
+ bSizer142->Add( m_checkBoxDontShowAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 );
+
+
+ bSizer142->Add( 10, 0, 1, 0, 5 );
+
+ m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) );
+
+ bSizer142->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ bSizer134->Add( bSizer142, 0, wxEXPAND, 5 );
+
+ this->SetSizer( bSizer134 );
+ this->Layout();
+ bSizer134->Fit( this );
+
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) );
+ m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this );
+ m_button16->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this );
+}
+
+SyncPreviewDlgGenerated::~SyncPreviewDlgGenerated()
+{
+ // Disconnect Events
+ this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) );
+ m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this );
+ m_button16->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this );
+}
diff --git a/ui/guiGenerated.h b/ui/guiGenerated.h
index 37d41205..5230128b 100644
--- a/ui/guiGenerated.h
+++ b/ui/guiGenerated.h
@@ -29,8 +29,7 @@ class wxButtonWithImage;
#include <wx/radiobut.h>
#include <wx/bmpbuttn.h>
#include <wx/statbox.h>
-#include <wx/hyperlink.h>
-#include <wx/checkbox.h>
+#include <wx/stattext.h>
#include <wx/panel.h>
#include <wx/combobox.h>
#include <wx/filepicker.h>
@@ -38,11 +37,12 @@ class wxButtonWithImage;
#include <wx/scrolwin.h>
#include <wx/grid.h>
#include <wx/choice.h>
+#include <wx/hyperlink.h>
+#include <wx/checkbox.h>
+#include <wx/notebook.h>
#include <wx/textctrl.h>
-#include <wx/stattext.h>
#include <wx/statline.h>
#include <wx/frame.h>
-#include <wx/notebook.h>
#include <wx/dialog.h>
#include <wx/gauge.h>
#include <wx/animate.h>
@@ -68,19 +68,6 @@ class MainDialogGenerated : public wxFrame
wxMenuItem* m_menuItemSwitchView;
wxMenu* m_menuAdvanced;
wxMenu* m_menuLanguages;
- wxMenuItem* m_menuItemGerman;
- wxMenuItem* m_menuItemEnglish;
- wxMenuItem* m_menuItemSpanish;
- wxMenuItem* m_menuItemFrench;
- wxMenuItem* m_menuItemItalian;
- wxMenuItem* m_menuItemHungarian;
- wxMenuItem* m_menuItemDutch;
- wxMenuItem* m_menuItemPolish;
- wxMenuItem* m_menuItemPortuguese;
- wxMenuItem* m_menuItemPortugueseBrazil;
- wxMenuItem* m_menuItemSlovenian;
- wxMenuItem* m_menuItemJapanese;
- wxMenuItem* m_menuItemChineseSimple;
wxMenuItem* m_menuItemGlobSett;
wxMenuItem* m_menuItem7;
wxMenu* m_menuHelp;
@@ -96,11 +83,8 @@ class MainDialogGenerated : public wxFrame
wxBitmapButton* m_bpButton14;
- wxBitmapButton* m_bpButtonFilter;
- wxHyperlinkCtrl* m_hyperlinkCfgFilter;
- wxCheckBox* m_checkBoxHideFilt;
-
+ wxStaticText* m_staticTextVariant;
wxBitmapButton* m_bpButtonSyncConfig;
wxButtonWithImage* m_buttonStartSync;
@@ -111,11 +95,10 @@ class MainDialogGenerated : public wxFrame
wxPanel* m_panelTopMiddle;
wxBoxSizer* bSizerMiddle;
- wxBitmapButton* m_bpButtonSwitchView;
-
+ wxBitmapButton* m_bpButtonSwapSides;
wxPanel* m_panelTopRight;
-
wxBitmapButton* m_bpButtonAddPair;
+ wxBitmapButton* m_bpButtonRemoveTopPair;
wxComboBox* m_directoryRight;
wxDirPickerCtrl* m_dirPickerRight;
wxBoxSizer* bSizer106;
@@ -129,9 +112,15 @@ class MainDialogGenerated : public wxFrame
wxPanel* m_panelRight;
CustomGridRight* m_gridRight;
wxBoxSizer* bSizer3;
+ wxNotebook* m_notebookBottomLeft;
+ wxPanel* m_panel30;
wxBitmapButton* m_bpButtonSave;
wxBitmapButton* m_bpButtonLoad;
wxChoice* m_choiceHistory;
+ wxPanel* m_panelFilter;
+ wxBitmapButton* m_bpButtonFilter;
+ wxHyperlinkCtrl* m_hyperlinkCfgFilter;
+ wxCheckBox* m_checkBoxHideFilt;
wxPanel* m_panel112;
wxBitmapButton* m_bpButtonLeftOnly;
@@ -145,6 +134,7 @@ class MainDialogGenerated : public wxFrame
wxBitmapButton* m_bpButtonSyncDirRight;
wxBitmapButton* m_bpButtonConflict;
+ wxBoxSizer* bSizerBottomRight;
wxPanel* m_panelSyncPreview;
wxStaticBitmap* m_bitmapCreate;
@@ -178,19 +168,6 @@ class MainDialogGenerated : public wxFrame
virtual void OnMenuSaveConfig( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuLoadConfig( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuQuit( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangGerman( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangEnglish( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangSpanish( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangFrench( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangItalian( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangHungarian( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangDutch( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangPolish( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangPortuguese( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangPortugueseBrazil( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangSlovenian( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangJapanese( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnMenuLangChineseSimp( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuGlobalSettings( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuBatchJob( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuExportFileList( wxCommandEvent& event ){ event.Skip(); }
@@ -200,26 +177,29 @@ class MainDialogGenerated : public wxFrame
virtual void OnCompareByTimeSize( wxCommandEvent& event ){ event.Skip(); }
virtual void OnCompareByContent( wxCommandEvent& event ){ event.Skip(); }
virtual void OnShowHelpDialog( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnFilterButton( wxCommandEvent& event ){ event.Skip(); }
- virtual void OnConfigureFilter( wxHyperlinkEvent& event ){ event.Skip(); }
- virtual void OnHideFilteredButton( wxCommandEvent& event ){ event.Skip(); }
virtual void OnSyncSettings( wxCommandEvent& event ){ event.Skip(); }
virtual void OnFolderHistoryKeyEvent( wxKeyEvent& event ){ event.Skip(); }
virtual void OnDirSelected( wxFileDirPickerEvent& event ){ event.Skip(); }
+ virtual void OnSwapSides( wxCommandEvent& event ){ event.Skip(); }
virtual void OnAddFolderPair( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnRemoveTopFolderPair( wxCommandEvent& event ){ event.Skip(); }
virtual void OnLeftGridDoubleClick( wxGridEvent& event ){ event.Skip(); }
- virtual void OnContextMenu( wxGridEvent& event ){ event.Skip(); }
+ virtual void OnContextRim( wxGridEvent& event ){ event.Skip(); }
virtual void OnSortLeftGrid( wxGridEvent& event ){ event.Skip(); }
- virtual void OnContextColumnLeft( wxGridEvent& event ){ event.Skip(); }
- virtual void OnContextMenuMiddle( wxGridEvent& event ){ event.Skip(); }
+ virtual void OnContextRimLabelLeft( wxGridEvent& event ){ event.Skip(); }
+ virtual void OnContextMiddle( wxGridEvent& event ){ event.Skip(); }
virtual void OnSortMiddleGrid( wxGridEvent& event ){ event.Skip(); }
+ virtual void OnContextMiddleLabel( wxGridEvent& event ){ event.Skip(); }
virtual void OnRightGridDoubleClick( wxGridEvent& event ){ event.Skip(); }
virtual void OnSortRightGrid( wxGridEvent& event ){ event.Skip(); }
- virtual void OnContextColumnRight( wxGridEvent& event ){ event.Skip(); }
+ virtual void OnContextRimLabelRight( wxGridEvent& event ){ event.Skip(); }
virtual void OnSaveConfig( wxCommandEvent& event ){ event.Skip(); }
virtual void OnLoadConfig( wxCommandEvent& event ){ event.Skip(); }
virtual void OnCfgHistoryKeyEvent( wxKeyEvent& event ){ event.Skip(); }
virtual void OnLoadFromHistory( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnFilterButton( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnConfigureFilter( wxHyperlinkEvent& event ){ event.Skip(); }
+ virtual void OnHideFilteredButton( wxCommandEvent& event ){ event.Skip(); }
virtual void OnLeftOnlyFiles( wxCommandEvent& event ){ event.Skip(); }
virtual void OnLeftNewerFiles( wxCommandEvent& event ){ event.Skip(); }
virtual void OnEqualFiles( wxCommandEvent& event ){ event.Skip(); }
@@ -612,42 +592,11 @@ class AboutDlgGenerated : public wxDialog
wxStaticText* m_staticText72;
wxStaticText* m_staticText73;
wxStaticText* m_staticText74;
- wxScrolledWindow* m_scrolledWindow3;
+ wxScrolledWindow* m_scrolledWindowTranslators;
+ wxBoxSizer* bSizerTranslators;
wxStaticText* m_staticText54;
- wxStaticBitmap* m_bitmapFrench;
- wxStaticText* m_staticText68;
- wxStaticText* m_staticText69;
- wxStaticBitmap* m_bitmapJapanese;
- wxStaticText* m_staticText70;
- wxStaticText* m_staticText71;
- wxStaticBitmap* m_bitmapDutch;
- wxStaticText* m_staticText711;
- wxStaticText* m_staticText712;
- wxStaticBitmap* m_bitmapChineseSimple;
- wxStaticText* m_staticText91;
- wxStaticText* m_staticText92;
- wxStaticBitmap* m_bitmapPolish;
- wxStaticText* m_staticText911;
- wxStaticText* m_staticText921;
- wxStaticBitmap* m_bitmapPortuguese;
- wxStaticText* m_staticText9211;
- wxStaticText* m_staticText9212;
- wxStaticBitmap* m_bitmapItalian;
- wxStaticText* m_staticText92121;
- wxStaticText* m_staticText92122;
- wxStaticBitmap* m_bitmapSlovenian;
- wxStaticText* m_staticText921221;
- wxStaticText* m_staticText921222;
- wxStaticBitmap* m_bitmapHungarian;
- wxStaticText* m_staticText682;
- wxStaticText* m_staticText681;
- wxStaticBitmap* m_bitmapSpanish;
- wxStaticText* m_staticText683;
- wxStaticText* m_staticText691;
- wxStaticBitmap* m_bitmapPortugueseBrazil;
- wxStaticText* m_staticText684;
- wxStaticText* m_staticText685;
+ wxFlexGridSizer* fgSizerTranslators;
wxStaticLine* m_staticline3;
wxPanel* m_panel22;
wxStaticText* m_staticText131;
@@ -929,4 +878,41 @@ class GlobalSettingsDlgGenerated : public wxDialog
};
+///////////////////////////////////////////////////////////////////////////////
+/// Class SyncPreviewDlgGenerated
+///////////////////////////////////////////////////////////////////////////////
+class SyncPreviewDlgGenerated : public wxDialog
+{
+ private:
+
+ protected:
+ wxStaticText* m_staticTextVariant;
+ wxButtonWithImage* m_buttonStartSync;
+ wxStaticLine* m_staticline14;
+
+ wxStaticBitmap* m_bitmapCreate;
+ wxTextCtrl* m_textCtrlCreate;
+ wxStaticBitmap* m_bitmapDelete;
+ wxTextCtrl* m_textCtrlDelete;
+ wxStaticBitmap* m_bitmapUpdate;
+ wxTextCtrl* m_textCtrlUpdate;
+ wxStaticBitmap* m_bitmapData;
+ wxTextCtrl* m_textCtrlData;
+ wxStaticLine* m_staticline12;
+ wxCheckBox* m_checkBoxDontShowAgain;
+
+ wxButton* m_button16;
+
+ // Virtual event handlers, overide them in your derived class
+ virtual void OnClose( wxCloseEvent& event ){ event.Skip(); }
+ virtual void OnStartSync( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); }
+
+
+ public:
+ SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization Preview"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
+ ~SyncPreviewDlgGenerated();
+
+};
+
#endif //__guiGenerated__
diff --git a/ui/guiStatusHandler.cpp b/ui/guiStatusHandler.cpp
index c2f27fac..51714ed8 100644
--- a/ui/guiStatusHandler.cpp
+++ b/ui/guiStatusHandler.cpp
@@ -12,6 +12,7 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) :
{
//prevent user input during "compare", do not disable maindialog since abort-button would also be disabled
//it's not nice, but works
+ mainDialog->m_notebookBottomLeft->Disable();
mainDialog->m_radioBtnSizeDate->Disable();
mainDialog->m_radioBtnContent->Disable();
mainDialog->m_bpButtonFilter->Disable();
@@ -21,7 +22,7 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) :
mainDialog->m_buttonStartSync->Disable();
mainDialog->m_dirPickerLeft->Disable();
mainDialog->m_dirPickerRight->Disable();
- mainDialog->m_bpButtonSwitchView->Disable();
+ mainDialog->m_bpButtonSwapSides->Disable();
mainDialog->m_bpButtonLeftOnly->Disable();
mainDialog->m_bpButtonLeftNewer->Disable();
mainDialog->m_bpButtonEqual->Disable();
@@ -66,6 +67,7 @@ CompareStatusHandler::~CompareStatusHandler()
updateUiNow(); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks
//reenable complete main dialog
+ mainDialog->m_notebookBottomLeft->Enable();
mainDialog->m_radioBtnSizeDate->Enable();
mainDialog->m_radioBtnContent->Enable();
mainDialog->m_bpButtonFilter->Enable();
@@ -75,7 +77,7 @@ CompareStatusHandler::~CompareStatusHandler()
mainDialog->m_buttonStartSync->Enable();
mainDialog->m_dirPickerLeft->Enable();
mainDialog->m_dirPickerRight->Enable();
- mainDialog->m_bpButtonSwitchView->Enable();
+ mainDialog->m_bpButtonSwapSides->Enable();
mainDialog->m_bpButtonLeftOnly->Enable();
mainDialog->m_bpButtonLeftNewer->Enable();
mainDialog->m_bpButtonEqual->Enable();
diff --git a/ui/sorting.h b/ui/sorting.h
index f7879a8b..2716eceb 100644
--- a/ui/sorting.h
+++ b/ui/sorting.h
@@ -89,11 +89,11 @@ namespace FreeFileSync
const wxChar* stringA = descrLineA->relativeName.c_str();
const wxChar* stringB = descrLineB->relativeName.c_str();
- size_t pos = descrLineA->relativeName.findFromEnd(GlobalResources::FILE_NAME_SEPARATOR); //start search beginning from end
+ size_t pos = descrLineA->relativeName.findFromEnd(FreeFileSync::FILE_NAME_SEPARATOR); //start search beginning from end
if (pos != std::string::npos)
stringA += pos + 1;
- pos = descrLineB->relativeName.findFromEnd(GlobalResources::FILE_NAME_SEPARATOR); //start search beginning from end
+ pos = descrLineB->relativeName.findFromEnd(FreeFileSync::FILE_NAME_SEPARATOR); //start search beginning from end
if (pos != std::string::npos)
stringB += pos + 1;
@@ -119,7 +119,7 @@ namespace FreeFileSync
relLengthA = descrLineA->relativeName.length();
else if (descrLineA->objType == FileDescrLine::TYPE_FILE)
{
- relLengthA = descrLineA->relativeName.findFromEnd(GlobalResources::FILE_NAME_SEPARATOR); //start search beginning from end
+ relLengthA = descrLineA->relativeName.findFromEnd(FreeFileSync::FILE_NAME_SEPARATOR); //start search beginning from end
if (relLengthA == wxNOT_FOUND)
{
relLengthA = 0;
@@ -144,7 +144,7 @@ namespace FreeFileSync
relLengthB = descrLineB->relativeName.length();
else if (descrLineB->objType == FileDescrLine::TYPE_FILE)
{
- relLengthB = descrLineB->relativeName.findFromEnd(GlobalResources::FILE_NAME_SEPARATOR); //start search beginning from end
+ relLengthB = descrLineB->relativeName.findFromEnd(FreeFileSync::FILE_NAME_SEPARATOR); //start search beginning from end
if (relLengthB == wxNOT_FOUND)
{
relLengthB = 0;
@@ -283,6 +283,16 @@ namespace FreeFileSync
}
+ template <SortDirection sortAscending>
+ inline
+ bool sortBySyncDirection(const FileCompareLine& a, const FileCompareLine& b)
+ {
+ return sortAscending == ASCENDING ?
+ a.direction < b.direction :
+ a.direction > b.direction;
+ }
+
+
template <SortDirection sortAscending, SideToSort side>
inline
bool sortByDirectory(const FolderCompareLine& a, const FolderCompareLine& b)
diff --git a/version/version.h b/version/version.h
index 41c73ce9..003e3872 100644
--- a/version/version.h
+++ b/version/version.h
@@ -2,5 +2,5 @@
namespace FreeFileSync
{
- static const wxString currentVersion = wxT("1.19"); //internal linkage!
+ static const wxString currentVersion = wxT("2.0"); //internal linkage!
}
bgstack15