diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:16:21 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:16:21 +0200 |
commit | 88a2d0007db222c339f0b6a17794a2014a241892 (patch) | |
tree | 75105ef49b3a52b7ee176a1ad480e7652e49825f | |
parent | 4.2 (diff) | |
download | FreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.tar.gz FreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.tar.bz2 FreeFileSync-88a2d0007db222c339f0b6a17794a2014a241892.zip |
4.3
-rw-r--r-- | Application.cpp | 2 | ||||
-rw-r--r-- | BUILD/Changelog.txt | 17 | ||||
-rw-r--r-- | BUILD/FreeFileSync.chm | bin | 671768 -> 672005 bytes | |||
-rw-r--r-- | BUILD/Help/html/ComparisonSettings.html | 10 | ||||
-rw-r--r-- | BUILD/Help/html/FreeFileSync.html | 18 | ||||
-rw-r--r-- | BUILD/Help/html/RealtimeSync.html | 6 | ||||
-rw-r--r-- | BUILD/Help/html/RunAsService.html | 12 | ||||
-rw-r--r-- | BUILD/Help/html/ScheduleBatch.html | 10 | ||||
-rw-r--r-- | BUILD/Help/html/ScheduleBatch_html_372f0f3.gif | bin | 20148 -> 0 bytes | |||
-rw-r--r-- | BUILD/Help/html/ShadowCopy.html | 2 | ||||
-rw-r--r-- | BUILD/Help/html/VariableDrive.html | 2 | ||||
-rw-r--r-- | BUILD/Help/html/scheduleBatch_html_13615436.gif | bin | 27319 -> 0 bytes | |||
-rw-r--r-- | BUILD/Help/html/scheduleBatch_html_28bb3203.gif | bin | 28325 -> 0 bytes | |||
-rw-r--r-- | BUILD/Help/html/scheduleBatch_html_m22c860a2.gif | bin | 27294 -> 0 bytes | |||
-rw-r--r-- | BUILD/Help/img/CmpSettings.png (renamed from BUILD/Help/html/CmpSettings.png) | bin | 28812 -> 28854 bytes | |||
-rw-r--r-- | BUILD/Help/img/CompareButton.png (renamed from BUILD/Help/html/CompareButton.png) | bin | 4856 -> 4856 bytes | |||
-rw-r--r-- | BUILD/Help/img/ErrorHandling.png (renamed from BUILD/Help/html/ErrorHandling.png) | bin | 28680 -> 28680 bytes | |||
-rw-r--r-- | BUILD/Help/img/MainDialog.png (renamed from BUILD/Help/html/MainDialog.png) | bin | 76362 -> 76362 bytes | |||
-rw-r--r-- | BUILD/Help/img/RealtimeSync.png (renamed from BUILD/Help/html/RealtimeSync.png) | bin | 32699 -> 32699 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_17e8fbfe.png (renamed from BUILD/Help/html/RunAsService_html_17e8fbfe.png) | bin | 9916 -> 9916 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_4f230a46.png (renamed from BUILD/Help/html/RunAsService_html_4f230a46.png) | bin | 16072 -> 16072 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_68e0fe53.png (renamed from BUILD/Help/html/RunAsService_html_68e0fe53.png) | bin | 7391 -> 7391 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_7aa44556.png (renamed from BUILD/Help/html/RunAsService_html_7aa44556.png) | bin | 101229 -> 101229 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_bf02de4e.png (renamed from BUILD/Help/html/RunAsService_html_bf02de4e.png) | bin | 13958 -> 13958 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_m3be0f332.png (renamed from BUILD/Help/html/RunAsService_html_m3be0f332.png) | bin | 16574 -> 16574 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunAsService_html_m3e56d901.png (renamed from BUILD/Help/html/RunAsService_html_m3e56d901.png) | bin | 72687 -> 72687 bytes | |||
-rw-r--r-- | BUILD/Help/img/RunMinimized.png (renamed from BUILD/Help/html/RunMinimized.png) | bin | 41946 -> 41946 bytes | |||
-rw-r--r-- | BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif (renamed from BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif) | bin | 21107 -> 21107 bytes | |||
-rw-r--r-- | BUILD/Help/img/SourceTarget.png (renamed from BUILD/Help/html/SourceTarget.png) | bin | 4857 -> 4857 bytes | |||
-rw-r--r-- | BUILD/Help/img/SyncConfigButton.png (renamed from BUILD/Help/html/SyncConfigButton.png) | bin | 2813 -> 2813 bytes | |||
-rw-r--r-- | BUILD/Help/img/SynchronizeButton.png (renamed from BUILD/Help/html/SynchronizeButton.png) | bin | 5109 -> 5109 bytes | |||
-rw-r--r-- | BUILD/Help/img/VolumeName.png (renamed from BUILD/Help/html/VolumeName.png) | bin | 5553 -> 5553 bytes | |||
-rw-r--r-- | BUILD/Help/img/WatchUsbInsert.png (renamed from BUILD/Help/html/WatchUsbInsert.png) | bin | 34801 -> 34801 bytes | |||
-rw-r--r-- | BUILD/Help/img/ffsicon.png (renamed from BUILD/Help/html/ffsicon.png) | bin | 7709 -> 7709 bytes | |||
-rw-r--r-- | BUILD/Help/img/menuAdv.png (renamed from BUILD/Help/html/menuAdv.png) | bin | 2711 -> 2711 bytes | |||
-rw-r--r-- | BUILD/Help/img/menuFile.png (renamed from BUILD/Help/html/menuFile.png) | bin | 5574 -> 5574 bytes | |||
-rw-r--r-- | BUILD/Help/img/menuHelp.png (renamed from BUILD/Help/html/menuHelp.png) | bin | 1823 -> 1823 bytes | |||
-rw-r--r-- | BUILD/Help/img/rtsicon.png (renamed from BUILD/Help/html/rtsicon.png) | bin | 7462 -> 7462 bytes | |||
-rw-r--r-- | BUILD/Help/img/ubuntuScheduler.png (renamed from BUILD/Help/html/ubuntuScheduler.png) | bin | 53376 -> 53376 bytes | |||
-rw-r--r-- | BUILD/Help/img/win7scheduler.png (renamed from BUILD/Help/html/win7scheduler.png) | bin | 29311 -> 29311 bytes | |||
-rw-r--r-- | BUILD/Languages/chinese_simple.lng | 426 | ||||
-rw-r--r-- | BUILD/Languages/chinese_traditional.lng | 438 | ||||
-rw-r--r-- | BUILD/Languages/croatian.lng | 1490 | ||||
-rw-r--r-- | BUILD/Languages/czech.lng | 448 | ||||
-rw-r--r-- | BUILD/Languages/danish.lng | 442 | ||||
-rw-r--r-- | BUILD/Languages/dutch.lng | 432 | ||||
-rw-r--r-- | BUILD/Languages/english_uk.lng | 442 | ||||
-rw-r--r-- | BUILD/Languages/finnish.lng | 98 | ||||
-rw-r--r-- | BUILD/Languages/french.lng | 432 | ||||
-rw-r--r-- | BUILD/Languages/german.lng | 76 | ||||
-rw-r--r-- | BUILD/Languages/greek.lng | 78 | ||||
-rw-r--r-- | BUILD/Languages/hebrew.lng | 444 | ||||
-rw-r--r-- | BUILD/Languages/hungarian.lng | 76 | ||||
-rw-r--r-- | BUILD/Languages/italian.lng | 442 | ||||
-rw-r--r-- | BUILD/Languages/japanese.lng | 104 | ||||
-rw-r--r-- | BUILD/Languages/korean.lng | 436 | ||||
-rw-r--r-- | BUILD/Languages/polish.lng | 448 | ||||
-rw-r--r-- | BUILD/Languages/portuguese.lng | 432 | ||||
-rw-r--r-- | BUILD/Languages/portuguese_br.lng | 448 | ||||
-rw-r--r-- | BUILD/Languages/romanian.lng | 464 | ||||
-rw-r--r-- | BUILD/Languages/russian.lng | 438 | ||||
-rw-r--r-- | BUILD/Languages/slovenian.lng | 454 | ||||
-rw-r--r-- | BUILD/Languages/spanish.lng | 444 | ||||
-rw-r--r-- | BUILD/Languages/swedish.lng | 442 | ||||
-rw-r--r-- | BUILD/Languages/turkish.lng | 98 | ||||
-rw-r--r-- | BUILD/Languages/ukrainian.lng | 438 | ||||
-rw-r--r-- | BUILD/Resources.zip | bin | 250353 -> 272977 bytes | |||
-rw-r--r-- | FreeFileSync.cbp | 6 | ||||
-rw-r--r-- | RealtimeSync/RealtimeSync.cbp | 4 | ||||
-rw-r--r-- | RealtimeSync/watcher.cpp | 13 | ||||
-rw-r--r-- | algorithm.cpp | 185 | ||||
-rw-r--r-- | algorithm.h | 4 | ||||
-rw-r--r-- | comparison.cpp | 127 | ||||
-rw-r--r-- | comparison.h | 2 | ||||
-rw-r--r-- | file_hierarchy.cpp | 227 | ||||
-rw-r--r-- | file_hierarchy.h | 191 | ||||
-rw-r--r-- | lib/custom_grid.cpp | 169 | ||||
-rw-r--r-- | lib/db_file.cpp | 476 | ||||
-rw-r--r-- | lib/db_file.h | 5 | ||||
-rw-r--r-- | lib/detect_renaming.cpp | 285 | ||||
-rw-r--r-- | lib/detect_renaming.h | 26 | ||||
-rw-r--r-- | lib/dir_exist_async.h | 4 | ||||
-rw-r--r-- | lib/dir_lock.cpp | 16 | ||||
-rw-r--r-- | lib/dir_name.cpp | 2 | ||||
-rw-r--r-- | lib/localization.cpp | 1 | ||||
-rw-r--r-- | lib/parallel_scan.cpp | 15 | ||||
-rw-r--r-- | lib/status_handler.h | 18 | ||||
-rw-r--r-- | structures.cpp | 126 | ||||
-rw-r--r-- | structures.h | 56 | ||||
-rw-r--r-- | synchronization.cpp | 1423 | ||||
-rw-r--r-- | synchronization.h | 49 | ||||
-rw-r--r-- | ui/batch_status_handler.cpp | 10 | ||||
-rw-r--r-- | ui/batch_status_handler.h | 10 | ||||
-rw-r--r-- | ui/grid_view.cpp | 4 | ||||
-rw-r--r-- | ui/gui_generated.cpp | 369 | ||||
-rw-r--r-- | ui/gui_generated.h | 99 | ||||
-rw-r--r-- | ui/gui_status_handler.cpp | 20 | ||||
-rw-r--r-- | ui/gui_status_handler.h | 20 | ||||
-rw-r--r-- | ui/main_dlg.cpp | 81 | ||||
-rw-r--r-- | ui/progress_indicator.cpp | 75 | ||||
-rw-r--r-- | ui/small_dlgs.cpp | 16 | ||||
-rw-r--r-- | ui/sync_cfg.cpp | 41 | ||||
-rw-r--r-- | ui/wx_form_build_hide_warnings.h | 6 | ||||
-rw-r--r-- | version/version.h | 2 | ||||
-rw-r--r-- | version/version.rc | 4 | ||||
-rw-r--r-- | wx+/format_unit.cpp | 2 | ||||
-rw-r--r-- | wx+/format_unit.h | 2 | ||||
-rw-r--r-- | wx+/serialize.h | 114 | ||||
-rw-r--r-- | zen/FindFilePlus/FindFilePlus.vcxproj (renamed from lib/FindFilePlus/FindFilePlus.vcxproj) | 0 | ||||
-rw-r--r-- | zen/FindFilePlus/dll_main.cpp (renamed from lib/FindFilePlus/dll_main.cpp) | 0 | ||||
-rw-r--r-- | zen/FindFilePlus/find_file_plus.cpp (renamed from lib/FindFilePlus/find_file_plus.cpp) | 0 | ||||
-rw-r--r-- | zen/FindFilePlus/find_file_plus.h (renamed from lib/FindFilePlus/find_file_plus.h) | 2 | ||||
-rw-r--r-- | zen/FindFilePlus/init_dll_binding.h (renamed from lib/FindFilePlus/init_dll_binding.h) | 0 | ||||
-rw-r--r-- | zen/FindFilePlus/load_dll.cpp (renamed from lib/FindFilePlus/load_dll.cpp) | 0 | ||||
-rw-r--r-- | zen/FindFilePlus/load_dll.h (renamed from lib/FindFilePlus/load_dll.h) | 0 | ||||
-rw-r--r-- | zen/dir_watcher.cpp | 54 | ||||
-rw-r--r-- | zen/dir_watcher.h | 3 | ||||
-rw-r--r-- | zen/file_handling.cpp | 84 | ||||
-rw-r--r-- | zen/file_handling.h | 7 | ||||
-rw-r--r-- | zen/file_id.cpp | 13 | ||||
-rw-r--r-- | zen/file_id.h | 5 | ||||
-rw-r--r-- | zen/file_id_def.h | 65 | ||||
-rw-r--r-- | zen/file_id_internal.h | 48 | ||||
-rw-r--r-- | zen/file_traverser.cpp | 767 | ||||
-rw-r--r-- | zen/file_traverser.h | 7 | ||||
-rw-r--r-- | zen/guid.h | 2 | ||||
-rw-r--r-- | zen/int64.h | 4 | ||||
-rw-r--r-- | zen/long_path_prefix.h | 1 | ||||
-rw-r--r-- | zen/notify_removal.cpp | 41 | ||||
-rw-r--r-- | zen/privilege.cpp | 80 | ||||
-rw-r--r-- | zen/privilege.h | 47 | ||||
-rw-r--r-- | zen/process_status.h | 40 | ||||
-rw-r--r-- | zen/stl_tools.h | 46 | ||||
-rw-r--r-- | zen/symlink_target.h | 2 | ||||
-rw-r--r-- | zen/time.h | 5 |
135 files changed, 8881 insertions, 7236 deletions
diff --git a/Application.cpp b/Application.cpp index 24763493..e15b3db0 100644 --- a/Application.cpp +++ b/Application.cpp @@ -369,7 +369,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet syncProc.startSynchronizationProcess(syncProcessCfg, folderCmp); - //play (optional) sound notification after sync has completed + //play (optional) sound notification after sync has completed -> don't play in silent mode, consider RealtimeSync! if (!batchCfg.silent) { const wxString soundFile = toWx(getResourceDir()) + wxT("Sync_Complete.wav"); diff --git a/BUILD/Changelog.txt b/BUILD/Changelog.txt index dbe9bd75..7116b447 100644 --- a/BUILD/Changelog.txt +++ b/BUILD/Changelog.txt @@ -2,8 +2,19 @@ |FreeFileSync| -------------- +Changelog v4.3 +-------------- +Detection of moved and renamed files +New database format for <Automatic> mode: a full sync is suggested before upgrading +Fixed overwrite symlink with regular file +Fixed synchronization result dialog GUI glitch (Windows XP) +Fixed macro %weekday% +RealtimeSync: Fixed support for manual volume unmount (Windows) +Added Croatian language + + Changelog v4.2 ---------------- +-------------- Implemented workaround for compiler bug leading to uncaught exceptions (Windows 32 bit) Shadow Copy Service: Native support for Windows7/Server 2008 Fixed reference by volume name parsing issue @@ -17,7 +28,7 @@ New option in GlobalSettings.xml: "RunWithBackgroundPriority" (Windows Vista and Changelog v4.1 ---------------- +-------------- Improved synchronization progress dialog Show all available aliases in directory history list Show password prompt when connecting to mapped network share @@ -31,7 +42,7 @@ Allow passing multiple directory names via command line Changelog v4.0 ---------------- +-------------- Thumbnail list view Option to specify comparison settings at folder pair level Correctly update parent-child relationship when changing sync directions diff --git a/BUILD/FreeFileSync.chm b/BUILD/FreeFileSync.chm Binary files differindex 7a38d187..cc0d3174 100644 --- a/BUILD/FreeFileSync.chm +++ b/BUILD/FreeFileSync.chm diff --git a/BUILD/Help/html/ComparisonSettings.html b/BUILD/Help/html/ComparisonSettings.html index 069a7fd0..15fffaaf 100644 --- a/BUILD/Help/html/ComparisonSettings.html +++ b/BUILD/Help/html/ComparisonSettings.html @@ -5,7 +5,7 @@ <TITLE></TITLE> <META NAME="GENERATOR" CONTENT="OpenOffice.org 3.2 (Win32)"> <META NAME="CREATED" CONTENT="20091206;16574000"> - <META NAME="CHANGED" CONTENT="20110910;15564800"> + <META NAME="CHANGED" CONTENT="20111117;19373200"> <META NAME="Info 1" CONTENT=""> <META NAME="Info 2" CONTENT=""> <META NAME="Info 3" CONTENT=""> @@ -25,7 +25,7 @@ <BODY LANG="en-US" DIR="LTR"> <H3 CLASS="western"><FONT FACE="Tahoma, sans-serif">Comparison Settings</FONT></H3> -<P STYLE="margin-bottom: 0cm"><IMG SRC="CmpSettings.png" NAME="Grafik1" ALIGN=BOTTOM BORDER=0></P> +<P STYLE="margin-bottom: 0cm"><IMG SRC="../img/CmpSettings.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=250 HEIGHT=257 BORDER=0></P> <H3 CLASS="western" STYLE="page-break-after: avoid"><FONT FACE="Tahoma, sans-serif">I. Compare by "File time and size"</FONT></H3> <P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">This @@ -131,9 +131,9 @@ handling</FONT></H3> offers three options to configure processing of symbolic links (also called symlinks or soft links):</FONT></P> <OL> - <LI><P STYLE="margin-bottom: 0cm"><SPAN STYLE="text-decoration: none"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><B>Ignore:</B></SPAN></FONT></SPAN> - <FONT FACE="Tahoma, sans-serif">excludes symbolic links while - scanning input directories.<BR></FONT> </P> + <LI><P STYLE="margin-bottom: 0cm"><SPAN STYLE="text-decoration: none"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><B>Exclude:</B></SPAN></FONT></SPAN> + <FONT FACE="Tahoma, sans-serif">skips symbolic links while scanning + input directories.<BR></FONT> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Direct:</B></FONT> <FONT FACE="Tahoma, sans-serif">configures synchronization of the symbolic link object itself and not its target. symbolic links will diff --git a/BUILD/Help/html/FreeFileSync.html b/BUILD/Help/html/FreeFileSync.html index 0b81ac64..762445b4 100644 --- a/BUILD/Help/html/FreeFileSync.html +++ b/BUILD/Help/html/FreeFileSync.html @@ -24,23 +24,23 @@ </STYLE> </HEAD> <BODY LANG="de-DE" DIR="LTR"> -<H3 CLASS="western" ALIGN=CENTER><IMG SRC="ffsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0> +<H3 CLASS="western" ALIGN=CENTER><IMG SRC="../img/ffsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0> <FONT SIZE=4 STYLE="font-size: 16pt">FreeFileSync<BR></FONT><FONT SIZE=3><I><SPAN STYLE="font-weight: normal">- Folder Comparison and Synchronization -</SPAN></I></FONT></H3> <H3 CLASS="western" ALIGN=LEFT>Usage:</H3> <OL> <LI VALUE=1><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Choose - left and right directories.<BR></FONT><IMG SRC="SourceTarget.png" NAME="Grafik4" ALIGN=TEXTTOP WIDTH=427 HEIGHT=52 BORDER=0></P> + left and right directories.<BR></FONT><IMG SRC="../img/SourceTarget.png" NAME="Grafik4" ALIGN=TEXTTOP WIDTH=427 HEIGHT=52 BORDER=0></P> <P STYLE="margin-bottom: 0cm"> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">"</FONT><FONT FACE="Tahoma, sans-serif"><I>Compare</I></FONT><FONT FACE="Tahoma, sans-serif">" - them.<BR></FONT><IMG SRC="CompareButton.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=178 HEIGHT=39 BORDER=0></P> + them.<BR></FONT><IMG SRC="../img/CompareButton.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=178 HEIGHT=39 BORDER=0></P> <P STYLE="margin-bottom: 0cm"> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Select - synchronization settings.<BR></FONT><IMG SRC="SyncConfigButton.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=46 HEIGHT=40 BORDER=0></P> + synchronization settings.<BR></FONT><IMG SRC="../img/SyncConfigButton.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=46 HEIGHT=40 BORDER=0></P> <P STYLE="margin-bottom: 0cm"> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Press "</FONT><FONT FACE="Tahoma, sans-serif"><I>Synchronize...</I></FONT><FONT FACE="Tahoma, sans-serif">" - to begin synchronization.<BR></FONT><IMG SRC="SynchronizeButton.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=183 HEIGHT=40 BORDER=0></P> + to begin synchronization.<BR></FONT><IMG SRC="../img/SynchronizeButton.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=183 HEIGHT=40 BORDER=0></P> </OL> <P STYLE="margin-bottom: 0cm; border-top: none; border-bottom: 1px solid #000000; border-left: none; border-right: none; padding-top: 0cm; padding-bottom: 0.07cm; padding-left: 0cm; padding-right: 0cm"> <BR> @@ -50,7 +50,7 @@ Folder Comparison and Synchronization -</SPAN></I></FONT></H3> <H3 CLASS="western" STYLE="page-break-before: always"><FONT FACE="Tahoma, sans-serif">Main Dialog:</FONT></H3> <OL> - <P STYLE="margin-bottom: 0cm"><IMG SRC="MainDialog.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=743 HEIGHT=438 BORDER=0></P> + <P STYLE="margin-bottom: 0cm"><IMG SRC="../img/MainDialog.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=743 HEIGHT=438 BORDER=0></P> </OL> <P STYLE="margin-bottom: 0cm"><BR> </P> @@ -127,7 +127,7 @@ bar:</FONT></H3> </UL> </TD> <TD WIDTH=212> - <P><IMG SRC="menuFile.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=211 HEIGHT=196 BORDER=0></P> + <P><IMG SRC="../img/menuFile.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=211 HEIGHT=196 BORDER=0></P> </TD> </TR> </TABLE> @@ -158,7 +158,7 @@ bar:</FONT></H3> </UL> </TD> <TD WIDTH=157> - <P><IMG SRC="menuAdv.png" NAME="Grafik11" ALIGN=MIDDLE WIDTH=159 HEIGHT=112 BORDER=0></P> + <P><IMG SRC="../img/menuAdv.png" NAME="Grafik11" ALIGN=MIDDLE WIDTH=159 HEIGHT=112 BORDER=0></P> </TD> </TR> </TABLE> @@ -181,7 +181,7 @@ bar:</FONT></H3> </UL> </TD> <TD WIDTH=202> - <P><IMG SRC="menuHelp.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=202 HEIGHT=90 BORDER=0></P> + <P><IMG SRC="../img/menuHelp.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=202 HEIGHT=90 BORDER=0></P> </TD> </TR> </TABLE> diff --git a/BUILD/Help/html/RealtimeSync.html b/BUILD/Help/html/RealtimeSync.html index fc0a2054..3468bc76 100644 --- a/BUILD/Help/html/RealtimeSync.html +++ b/BUILD/Help/html/RealtimeSync.html @@ -23,7 +23,7 @@ </STYLE> </HEAD> <BODY LANG="en-US" DIR="LTR"> -<H3 CLASS="western" ALIGN=CENTER><IMG SRC="rtsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0> +<H3 CLASS="western" ALIGN=CENTER><IMG SRC="../img/rtsicon.png" NAME="Grafik6" ALIGN=ABSMIDDLE WIDTH=37 HEIGHT=37 BORDER=0> <FONT SIZE=4 STYLE="font-size: 16pt">RealtimeSync<BR></FONT><FONT SIZE=3><I><SPAN STYLE="font-weight: normal">- Automated Synchronization -</SPAN></I></FONT></H3> <P ALIGN=LEFT><BR><BR> @@ -53,7 +53,7 @@ but also sets up the command-line to execute the </FONT><FONT FACE="Courier New, Now press "</FONT><FONT FACE="Tahoma, sans-serif"><I>Start</I></FONT><FONT FACE="Tahoma, sans-serif">" to begin monitoring.</FONT></P> <UL> - <P STYLE="margin-bottom: 0cm"><IMG SRC="RealtimeSync.png" NAME="Grafik3" ALIGN=MIDDLE WIDTH=420 HEIGHT=480 BORDER=0></P> + <P STYLE="margin-bottom: 0cm"><IMG SRC="../img/RealtimeSync.png" NAME="Grafik3" ALIGN=MIDDLE WIDTH=420 HEIGHT=480 BORDER=0></P> </UL> <P STYLE="margin-bottom: 0cm"><BR> </P> @@ -95,7 +95,7 @@ the relevant configuration on the USB stick's root directory to have it called when the stick is mounted. Then configure RealtimeSync as shown in the following:</FONT></P> <UL> - <P><IMG SRC="WatchUsbInsert.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=436 HEIGHT=447 BORDER=0></P> + <P><IMG SRC="../img/WatchUsbInsert.png" NAME="Grafik2" ALIGN=BOTTOM WIDTH=436 HEIGHT=447 BORDER=0></P> </UL> <P STYLE="margin-bottom: 0cm"><BR> </P> diff --git a/BUILD/Help/html/RunAsService.html b/BUILD/Help/html/RunAsService.html index c347a4fa..8b5e0d42 100644 --- a/BUILD/Help/html/RunAsService.html +++ b/BUILD/Help/html/RunAsService.html @@ -49,7 +49,7 @@ Create and register a new Service via command line:</FONT></P> <P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm"> <FONT FACE="Courier New, monospace">instsrv <ServiceName> <PathToResourceKit>\srvany.exe</FONT></P> - </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="RunAsService_html_4f230a46.png" NAME="Grafik9" ALIGN=BOTTOM WIDTH=430 HEIGHT=107 BORDER=0></P> + </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="../img/RunAsService_html_4f230a46.png" NAME="Grafik9" ALIGN=BOTTOM WIDTH=430 HEIGHT=107 BORDER=0></P> </UL> <P STYLE="margin-bottom: 0cm"><BR> </P> @@ -60,10 +60,10 @@ the new Service with RealtimeSync:</FONT></P> the Registry editor (Regedit.exe) and navigate to key "</FONT><FONT FACE="Courier New, monospace">HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<ServiceName></FONT><FONT FACE="Tahoma, sans-serif">"</FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Add - a new key "</FONT><FONT FACE="Courier New, monospace">Parameters</FONT><FONT FACE="Tahoma, sans-serif">".<BR><IMG SRC="RunAsService_html_bf02de4e.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=249 HEIGHT=101 BORDER=0></FONT></P> + a new key "</FONT><FONT FACE="Courier New, monospace">Parameters</FONT><FONT FACE="Tahoma, sans-serif">".<BR><IMG SRC="../img/RunAsService_html_bf02de4e.png" NAME="Grafik8" ALIGN=BOTTOM WIDTH=249 HEIGHT=101 BORDER=0></FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Add a new String value named "</FONT><FONT FACE="Courier New, monospace">Application</FONT><FONT FACE="Tahoma, sans-serif">" - and specify a command line that shall be executed as value.<BR><IMG SRC="RunAsService_html_m3be0f332.png" NAME="Grafik10" ALIGN=BOTTOM WIDTH=620 HEIGHT=58 BORDER=0></FONT></P> + and specify a command line that shall be executed as value.<BR><IMG SRC="../img/RunAsService_html_m3be0f332.png" NAME="Grafik10" ALIGN=BOTTOM WIDTH=620 HEIGHT=58 BORDER=0></FONT></P> </UL> <P STYLE="margin-bottom: 0cm"><BR> </P> @@ -97,7 +97,7 @@ administration:</FONT></P> <P STYLE="margin-right: 0.98cm"><SPAN ID="Rahmen5" DIR="LTR" STYLE="float: left; width: 80%; height: 0.14cm; border: none; padding: 0cm; background: #e6e6e6"> <P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm"> <FONT FACE="Tahoma, sans-serif">net start <ServiceName></FONT></P> - </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="RunAsService_html_17e8fbfe.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=640 HEIGHT=55 BORDER=0><BR> <BR><IMG SRC="RunAsService_html_7aa44556.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=548 HEIGHT=291 BORDER=0></P> + </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="../img/RunAsService_html_17e8fbfe.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=640 HEIGHT=55 BORDER=0><BR> <BR><IMG SRC="../img/RunAsService_html_7aa44556.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=548 HEIGHT=291 BORDER=0></P> </UL> <P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><BR> </P> @@ -111,7 +111,7 @@ administration:</FONT></P> Service administration.</FONT></P> </SPAN><BR CLEAR=LEFT><BR> </P> -<P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><IMG SRC="RunAsService_html_m3e56d901.png" NAME="Grafik6" ALIGN=BOTTOM WIDTH=410 HEIGHT=468 BORDER=0></P> +<P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><IMG SRC="../img/RunAsService_html_m3e56d901.png" NAME="Grafik6" ALIGN=BOTTOM WIDTH=410 HEIGHT=468 BORDER=0></P> <P STYLE="margin-left: 1.46cm; margin-bottom: 0cm"><BR> </P> <P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR> @@ -122,7 +122,7 @@ Service shall be removed from the system, enter via command line:</FONT></P> <P STYLE="margin-right: 0.98cm"><SPAN ID="Rahmen6" DIR="LTR" STYLE="float: left; width: 80%; height: 0.14cm; border: none; padding: 0cm; background: #e6e6e6"> <P ALIGN=LEFT STYLE="margin-left: 0.79cm; margin-right: 0.98cm; margin-bottom: 0cm"> <FONT FACE="Tahoma, sans-serif">instsrv <ServiceName> remove</FONT></P> - </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="RunAsService_html_68e0fe53.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=640 HEIGHT=52 BORDER=0></P> + </SPAN><BR CLEAR=LEFT> <BR><IMG SRC="../img/RunAsService_html_68e0fe53.png" NAME="Grafik7" ALIGN=MIDDLE WIDTH=640 HEIGHT=52 BORDER=0></P> </UL> <P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><BR> </P> diff --git a/BUILD/Help/html/ScheduleBatch.html b/BUILD/Help/html/ScheduleBatch.html index 4bd0c8ad..9594ec3d 100644 --- a/BUILD/Help/html/ScheduleBatch.html +++ b/BUILD/Help/html/ScheduleBatch.html @@ -31,12 +31,12 @@ Job</FONT></H3> for example, as "</FONT><FONT FACE="Courier New, monospace">C:\SyncJob.ffs_batch</FONT><FONT FACE="Tahoma, sans-serif">".<BR> </FONT></P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Enable checkbox "<I>Run miminized</I>" to avoid blocking while - showing a status dialog at the end of the process.<BR><IMG SRC="RunMinimized.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=709 HEIGHT=332 BORDER=0></FONT></P> + showing a status dialog at the end of the process.<BR><IMG SRC="../img/RunMinimized.png" NAME="Grafik3" ALIGN=BOTTOM WIDTH=709 HEIGHT=332 BORDER=0></FONT></P> <P STYLE="margin-bottom: 0cm"> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">In order to prevent error or warning popup messages from stopping progress, set "<I>Error handling</I>" to either "<I>Ignore - errors</I>" or "<I>Exit instantly</I>".<BR><IMG SRC="ErrorHandling.png" NAME="Grafik4" ALIGN=BOTTOM WIDTH=313 HEIGHT=331 BORDER=0></FONT></P> + errors</I>" or "<I>Exit instantly</I>".<BR><IMG SRC="../img/ErrorHandling.png" NAME="Grafik4" ALIGN=BOTTOM WIDTH=313 HEIGHT=331 BORDER=0></FONT></P> <P STYLE="margin-bottom: 0cm"> </P> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">Setup your operating system's scheduler</FONT></P> @@ -63,7 +63,7 @@ Job</FONT></H3> <UL> <LI><P STYLE="margin-bottom: 0cm; font-weight: normal"><FONT FACE="Tahoma, sans-serif"><FONT COLOR="#000000"><FONT SIZE=3>Use quotes if any paths contain spaces, e.g.: </FONT></FONT><FONT COLOR="#000000"><FONT FACE="Courier New, monospace"><FONT SIZE=3>"C:\some - folder\SyncJob.ffs_batch"</FONT></FONT></FONT><FONT COLOR="#000000"><FONT SIZE=3><BR></FONT></FONT><IMG SRC="win7scheduler.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=708 HEIGHT=321 BORDER=0><BR> </FONT></P> + folder\SyncJob.ffs_batch"</FONT></FONT></FONT><FONT COLOR="#000000"><FONT SIZE=3><BR></FONT></FONT><IMG SRC="../img/win7scheduler.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=708 HEIGHT=321 BORDER=0><BR> </FONT></P> </UL> </OL> </OL> @@ -80,7 +80,7 @@ Job</FONT></H3> <LI><P STYLE="margin-bottom: 0cm; font-weight: normal"><FONT FACE="Tahoma, sans-serif">Make sure "Run:" is specified as: <FONT FACE="Courier New, monospace"><FreeFileSync installation directory>\FreeFileSync.exe <ffs_batch - file></FONT><BR><IMG SRC="ScheduleBatch_html_m10bf0d36.gif" NAME="Grafik2" ALIGN=BOTTOM WIDTH=406 HEIGHT=455 BORDER=0><BR> </FONT></P> + file></FONT><BR><IMG SRC="../img/ScheduleBatch_html_m10bf0d36.gif" NAME="Grafik2" ALIGN=BOTTOM WIDTH=406 HEIGHT=455 BORDER=0><BR> </FONT></P> </UL> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Ubuntu Linux Gnome-schedule:</B></FONT></P> @@ -105,7 +105,7 @@ Job</FONT></H3> <UL> <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">Specify the command as:</SPAN></SPAN></FONT> <FONT FACE="Courier New, monospace"><I><SPAN STYLE="font-weight: normal"><FreeFileSync - installation directory>\FreeFileSync <ffs_batch file><BR></SPAN></I></FONT><IMG SRC="ubuntuScheduler.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=629 HEIGHT=560 BORDER=0></P> + installation directory>\FreeFileSync <ffs_batch file><BR></SPAN></I></FONT><IMG SRC="../img/ubuntuScheduler.png" NAME="Grafik5" ALIGN=BOTTOM WIDTH=629 HEIGHT=560 BORDER=0></P> </UL> </OL> </OL> diff --git a/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif b/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif Binary files differdeleted file mode 100644 index 4cddbc19..00000000 --- a/BUILD/Help/html/ScheduleBatch_html_372f0f3.gif +++ /dev/null diff --git a/BUILD/Help/html/ShadowCopy.html b/BUILD/Help/html/ShadowCopy.html index d8286285..ce66ccee 100644 --- a/BUILD/Help/html/ShadowCopy.html +++ b/BUILD/Help/html/ShadowCopy.html @@ -39,7 +39,7 @@ Copy of the source drive. To enable this feature go to </FONT><FONT FACE="Tahoma not use Volume Shadow Copy Service when being synchronized.</FONT></P> <LI><P ALIGN=LEFT STYLE="margin-right: 0.98cm; margin-bottom: 0cm"><SPAN STYLE="font-style: normal"><FONT FACE="Tahoma, sans-serif">Creating Volume Snapshots using VSS requires the application to be started - with Administrator rights.</FONT></SPAN></P> + with administrator rights.</FONT></SPAN></P> </UL> </SPAN><BR CLEAR=LEFT><BR> </P> diff --git a/BUILD/Help/html/VariableDrive.html b/BUILD/Help/html/VariableDrive.html index ebf80b8d..3e0ea71e 100644 --- a/BUILD/Help/html/VariableDrive.html +++ b/BUILD/Help/html/VariableDrive.html @@ -42,7 +42,7 @@ name>]\<path></FONT></FONT></P> </P> <P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif">It is not required to look up and enter the volume name manually. Just -select the corresponding entry in the drop down menu.<BR></FONT><IMG SRC="VolumeName.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=279 HEIGHT=103 BORDER=0></P> +select the corresponding entry in the drop down menu.<BR></FONT><IMG SRC="../img/VolumeName.png" NAME="Grafik1" ALIGN=BOTTOM WIDTH=279 HEIGHT=103 BORDER=0></P> <P STYLE="margin-bottom: 0cm"><BR> </P> <P STYLE="margin-bottom: 0cm"><FONT FACE="Tahoma, sans-serif"><B>Option diff --git a/BUILD/Help/html/scheduleBatch_html_13615436.gif b/BUILD/Help/html/scheduleBatch_html_13615436.gif Binary files differdeleted file mode 100644 index 23d7bda9..00000000 --- a/BUILD/Help/html/scheduleBatch_html_13615436.gif +++ /dev/null diff --git a/BUILD/Help/html/scheduleBatch_html_28bb3203.gif b/BUILD/Help/html/scheduleBatch_html_28bb3203.gif Binary files differdeleted file mode 100644 index 45c8b1c2..00000000 --- a/BUILD/Help/html/scheduleBatch_html_28bb3203.gif +++ /dev/null diff --git a/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif b/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif Binary files differdeleted file mode 100644 index 1f8da914..00000000 --- a/BUILD/Help/html/scheduleBatch_html_m22c860a2.gif +++ /dev/null diff --git a/BUILD/Help/html/CmpSettings.png b/BUILD/Help/img/CmpSettings.png Binary files differindex eb0c83ab..d2548891 100644 --- a/BUILD/Help/html/CmpSettings.png +++ b/BUILD/Help/img/CmpSettings.png diff --git a/BUILD/Help/html/CompareButton.png b/BUILD/Help/img/CompareButton.png Binary files differindex bab3780b..bab3780b 100644 --- a/BUILD/Help/html/CompareButton.png +++ b/BUILD/Help/img/CompareButton.png diff --git a/BUILD/Help/html/ErrorHandling.png b/BUILD/Help/img/ErrorHandling.png Binary files differindex 628fac9c..628fac9c 100644 --- a/BUILD/Help/html/ErrorHandling.png +++ b/BUILD/Help/img/ErrorHandling.png diff --git a/BUILD/Help/html/MainDialog.png b/BUILD/Help/img/MainDialog.png Binary files differindex ab6a6f7c..ab6a6f7c 100644 --- a/BUILD/Help/html/MainDialog.png +++ b/BUILD/Help/img/MainDialog.png diff --git a/BUILD/Help/html/RealtimeSync.png b/BUILD/Help/img/RealtimeSync.png Binary files differindex 20d582c6..20d582c6 100644 --- a/BUILD/Help/html/RealtimeSync.png +++ b/BUILD/Help/img/RealtimeSync.png diff --git a/BUILD/Help/html/RunAsService_html_17e8fbfe.png b/BUILD/Help/img/RunAsService_html_17e8fbfe.png Binary files differindex 23eb6083..23eb6083 100644 --- a/BUILD/Help/html/RunAsService_html_17e8fbfe.png +++ b/BUILD/Help/img/RunAsService_html_17e8fbfe.png diff --git a/BUILD/Help/html/RunAsService_html_4f230a46.png b/BUILD/Help/img/RunAsService_html_4f230a46.png Binary files differindex a32a442d..a32a442d 100644 --- a/BUILD/Help/html/RunAsService_html_4f230a46.png +++ b/BUILD/Help/img/RunAsService_html_4f230a46.png diff --git a/BUILD/Help/html/RunAsService_html_68e0fe53.png b/BUILD/Help/img/RunAsService_html_68e0fe53.png Binary files differindex 5639a21c..5639a21c 100644 --- a/BUILD/Help/html/RunAsService_html_68e0fe53.png +++ b/BUILD/Help/img/RunAsService_html_68e0fe53.png diff --git a/BUILD/Help/html/RunAsService_html_7aa44556.png b/BUILD/Help/img/RunAsService_html_7aa44556.png Binary files differindex b37fe6e4..b37fe6e4 100644 --- a/BUILD/Help/html/RunAsService_html_7aa44556.png +++ b/BUILD/Help/img/RunAsService_html_7aa44556.png diff --git a/BUILD/Help/html/RunAsService_html_bf02de4e.png b/BUILD/Help/img/RunAsService_html_bf02de4e.png Binary files differindex 2bdac2db..2bdac2db 100644 --- a/BUILD/Help/html/RunAsService_html_bf02de4e.png +++ b/BUILD/Help/img/RunAsService_html_bf02de4e.png diff --git a/BUILD/Help/html/RunAsService_html_m3be0f332.png b/BUILD/Help/img/RunAsService_html_m3be0f332.png Binary files differindex 5ad45cfa..5ad45cfa 100644 --- a/BUILD/Help/html/RunAsService_html_m3be0f332.png +++ b/BUILD/Help/img/RunAsService_html_m3be0f332.png diff --git a/BUILD/Help/html/RunAsService_html_m3e56d901.png b/BUILD/Help/img/RunAsService_html_m3e56d901.png Binary files differindex 860d1543..860d1543 100644 --- a/BUILD/Help/html/RunAsService_html_m3e56d901.png +++ b/BUILD/Help/img/RunAsService_html_m3e56d901.png diff --git a/BUILD/Help/html/RunMinimized.png b/BUILD/Help/img/RunMinimized.png Binary files differindex 145a7568..145a7568 100644 --- a/BUILD/Help/html/RunMinimized.png +++ b/BUILD/Help/img/RunMinimized.png diff --git a/BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif b/BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif Binary files differindex 20d27d6d..20d27d6d 100644 --- a/BUILD/Help/html/ScheduleBatch_html_m10bf0d36.gif +++ b/BUILD/Help/img/ScheduleBatch_html_m10bf0d36.gif diff --git a/BUILD/Help/html/SourceTarget.png b/BUILD/Help/img/SourceTarget.png Binary files differindex 2a3a834e..2a3a834e 100644 --- a/BUILD/Help/html/SourceTarget.png +++ b/BUILD/Help/img/SourceTarget.png diff --git a/BUILD/Help/html/SyncConfigButton.png b/BUILD/Help/img/SyncConfigButton.png Binary files differindex 2ac5c94e..2ac5c94e 100644 --- a/BUILD/Help/html/SyncConfigButton.png +++ b/BUILD/Help/img/SyncConfigButton.png diff --git a/BUILD/Help/html/SynchronizeButton.png b/BUILD/Help/img/SynchronizeButton.png Binary files differindex a8b8002b..a8b8002b 100644 --- a/BUILD/Help/html/SynchronizeButton.png +++ b/BUILD/Help/img/SynchronizeButton.png diff --git a/BUILD/Help/html/VolumeName.png b/BUILD/Help/img/VolumeName.png Binary files differindex 9d1b9201..9d1b9201 100644 --- a/BUILD/Help/html/VolumeName.png +++ b/BUILD/Help/img/VolumeName.png diff --git a/BUILD/Help/html/WatchUsbInsert.png b/BUILD/Help/img/WatchUsbInsert.png Binary files differindex 9d106fb8..9d106fb8 100644 --- a/BUILD/Help/html/WatchUsbInsert.png +++ b/BUILD/Help/img/WatchUsbInsert.png diff --git a/BUILD/Help/html/ffsicon.png b/BUILD/Help/img/ffsicon.png Binary files differindex 7ff53bb6..7ff53bb6 100644 --- a/BUILD/Help/html/ffsicon.png +++ b/BUILD/Help/img/ffsicon.png diff --git a/BUILD/Help/html/menuAdv.png b/BUILD/Help/img/menuAdv.png Binary files differindex 3626c1f0..3626c1f0 100644 --- a/BUILD/Help/html/menuAdv.png +++ b/BUILD/Help/img/menuAdv.png diff --git a/BUILD/Help/html/menuFile.png b/BUILD/Help/img/menuFile.png Binary files differindex 7e6844d5..7e6844d5 100644 --- a/BUILD/Help/html/menuFile.png +++ b/BUILD/Help/img/menuFile.png diff --git a/BUILD/Help/html/menuHelp.png b/BUILD/Help/img/menuHelp.png Binary files differindex db51f82f..db51f82f 100644 --- a/BUILD/Help/html/menuHelp.png +++ b/BUILD/Help/img/menuHelp.png diff --git a/BUILD/Help/html/rtsicon.png b/BUILD/Help/img/rtsicon.png Binary files differindex dabaa256..dabaa256 100644 --- a/BUILD/Help/html/rtsicon.png +++ b/BUILD/Help/img/rtsicon.png diff --git a/BUILD/Help/html/ubuntuScheduler.png b/BUILD/Help/img/ubuntuScheduler.png Binary files differindex 82bf329f..82bf329f 100644 --- a/BUILD/Help/html/ubuntuScheduler.png +++ b/BUILD/Help/img/ubuntuScheduler.png diff --git a/BUILD/Help/html/win7scheduler.png b/BUILD/Help/img/win7scheduler.png Binary files differindex 29fa1f36..29fa1f36 100644 --- a/BUILD/Help/html/win7scheduler.png +++ b/BUILD/Help/img/win7scheduler.png diff --git a/BUILD/Languages/chinese_simple.lng b/BUILD/Languages/chinese_simple.lng index fc37aac5..65887d4f 100644 --- a/BUILD/Languages/chinese_simple.lng +++ b/BUILD/Languages/chinese_simple.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>实时同步 - 自动同步</target> -<source>Browse</source> -<target>浏览</target> - -<source>Windows Error Code %x:</source> -<target>Windows错误代码 %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux错误代码 %x:</target> - -<source>Invalid command line: %x</source> -<target>无效的命令行: %x</target> - -<source>Error resolving symbolic link:</source> -<target>解决符号链接出错:</target> - -<source>Show pop-up</source> -<target>显示弹出对话框</target> - -<source>Show pop-up on errors or warnings</source> -<target>在错误或警告时显示弹出对话框</target> - -<source>Ignore errors</source> -<target>忽略错误</target> - -<source>Hide all error and warning messages</source> -<target>隐藏所有错误与警告信息</target> - -<source>Exit instantly</source> -<target>立即退出</target> - -<source>Abort synchronization immediately</source> -<target>立即中止同步</target> - <source>Select alternate comparison settings</source> <target>选择替换的比较设置</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>选择时间跨度</target> +<source>Show pop-up</source> +<target>显示弹出对话框</target> + +<source>Show pop-up on errors or warnings</source> +<target>在错误或警告时显示弹出对话框</target> + +<source>Ignore errors</source> +<target>忽略错误</target> + +<source>Hide all error and warning messages</source> +<target>隐藏所有错误与警告信息</target> + +<source>Exit instantly</source> +<target>立即退出</target> + +<source>Abort synchronization immediately</source> +<target>立即中止同步</target> + +<source>Browse</source> +<target>浏览</target> + +<source>Error reading from synchronization database:</source> +<target>从同步数据库中读取时出错:</target> + +<source>Error writing to synchronization database:</source> +<target>向同步数据库中写入时出错:</target> + +<source>Invalid command line: %x</source> +<target>无效的命令行: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows错误代码 %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux错误代码 %x:</target> + +<source>Error resolving symbolic link:</source> +<target>解决符号链接出错:</target> + <source>%x MB</source> <target>%x MB</target> @@ -162,17 +168,14 @@ <source>Comparison Result</source> <target>比较结果</target> -<source>Incompatible synchronization database format:</source> -<target>不兼容的同步数据库格式:</target> - <source>Initial synchronization:</source> <target>初始化同步:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>FreeFileSync数据库文件其中一个不存在:</target> -<source>Error reading from synchronization database:</source> -<target>从同步数据库中读取时出错:</target> +<source>Incompatible synchronization database format:</source> +<target>不兼容的同步数据库格式:</target> <source>Database files do not share a common synchronization session:</source> <target>数据库文件没不共享一个公共的同步段</target> @@ -197,12 +200,18 @@ <pluralform>%x 秒</pluralform> </target> +<source>Drag && drop</source> +<target>拖放</target> + <source>Info</source> <target>信息</target> <source>Fatal Error</source> <target>致命错误</target> +<source>Error reading file:</source> +<target>读取文件出错:</target> + <source>Scanning:</source> <target>扫描中:</target> @@ -220,15 +229,36 @@ <source>Invalid FreeFileSync config file!</source> <target>无效的 FreeFileSync 配置文件!</target> -<source>File does not exist:</source> -<target>文件不存在:</target> - <source>Error parsing configuration file:</source> <target>分析配置文件出错:</target> +<source>Error moving to Recycle Bin:</source> +<target>移动到回收站出错:</target> + +<source>Could not load a required DLL:</source> +<target>不能加载所需的动态连接库:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>使用卷影复制服务时出错!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>不支持在WOW64上使用卷影复制. 请使用 FreeFileSync 64位版本.</target> + +<source>Could not determine volume name for file:</source> +<target>不能确定此文件的卷名称:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>卷名 %x 并非文件名 %y 的一部分!</target> + <source>/sec</source> <target>/秒</target> +<source>File does not exist:</source> +<target>文件不存在:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>不能从如下XML节点读取数值:</target> + <source>S&ave configuration...</source> <target>保存配置(&A)...</target> @@ -321,138 +351,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>有一个目录输入字段是空的.</target> -<source>Drag && drop</source> -<target>拖放</target> - -<source>Could not initialize directory monitoring:</source> -<target>不能初始化目录监视:</target> - -<source>Error when monitoring directories.</source> -<target>监视目录时出错.</target> - -<source>Conversion error:</source> -<target>转换错误:</target> - -<source>Error deleting file:</source> -<target>删除文件出错:</target> - -<source>Error moving file:</source> -<target>移动文件时出错:</target> - -<source>Target file already existing!</source> -<target>目标文件已经存在!</target> - -<source>Error moving directory:</source> -<target>移动目录时出错:</target> - -<source>Target directory already existing!</source> -<target>目标目录已经存在!</target> - -<source>Error deleting directory:</source> -<target>删除目录出错:</target> - -<source>Error changing modification time:</source> -<target>改变修改时间时出错:</target> - -<source>Error loading library function:</source> -<target>加载库函数出错:</target> - -<source>Error reading security context:</source> -<target>读取安全上下文时出错:</target> - -<source>Error writing security context:</source> -<target>写入安全上下文时出错:</target> - -<source>Error copying file permissions:</source> -<target>复制文件权限时出错:</target> - -<source>Error creating directory:</source> -<target>创建目录出错:</target> - -<source>Error copying symbolic link:</source> -<target>复制符号链接时出错:</target> - -<source>Error copying file:</source> -<target>复制文件出错:</target> - -<source>Error opening file:</source> -<target>打开文件出错:</target> - -<source>Error writing file:</source> -<target>写入文件出错:</target> - -<source>Error reading file:</source> -<target>读取文件出错:</target> - -<source>Operation aborted!</source> -<target>操作已取消!</target> - -<source>Endless loop when traversing directory:</source> -<target>遍历目录时出现无限循环:</target> - -<source>Error traversing directory:</source> -<target>遍历目录出错:</target> - -<source>Error setting privilege:</source> -<target>设置权限时出错:</target> - -<source>Error moving to Recycle Bin:</source> -<target>移动到回收站出错:</target> - -<source>Could not load a required DLL:</source> -<target>不能加载所需的动态连接库:</target> - -<source>Error writing to synchronization database:</source> -<target>向同步数据库中写入时出错:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>使用卷影复制服务时出错!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>不支持在WOW64上使用卷影复制. 请使用 FreeFileSync 64位版本.</target> - -<source>Could not determine volume name for file:</source> -<target>不能确定此文件的卷名称:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>卷名 %x 并非文件名 %y 的一部分!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x 分</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x 小时</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x 天</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>不能从如下XML节点读取数值:</target> - <source>Logging</source> <target>记录</target> @@ -471,9 +369,6 @@ The command line is executed each time: <source>Batch execution</source> <target>批处理执行</target> -<source>Log-messages:</source> -<target>日志信息:</target> - <source>Stop</source> <target>停止</target> @@ -600,6 +495,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>将被转移的总数据</target> +<source>Operation:</source> +<target>操作:</target> + +<source>Items found:</source> +<target>已找到的元素:</target> + +<source>Items remaining:</source> +<target>剩余的元素:</target> + +<source>Speed:</source> +<target>速度:</target> + +<source>Time remaining:</source> +<target>剩余时间:</target> + +<source>Time elapsed:</source> +<target>已用时间:</target> + <source>Batch job</source> <target>批处理作业</target> @@ -648,32 +561,14 @@ The command line is executed each time: <source>&Cancel</source> <target>取消(&C)</target> -<source>Operation:</source> -<target>操作:</target> - -<source>Items found:</source> -<target>已找到的元素:</target> - -<source>Items remaining:</source> -<target>剩余的元素:</target> - -<source>Speed:</source> -<target>速度:</target> - -<source>Time remaining:</source> -<target>剩余时间:</target> - -<source>Time elapsed:</source> -<target>已用时间:</target> - <source>Select variant:</source> <target>选择变化的:</target> <source><Automatic></source> <target><自动></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>使用数据库来识别和传送两边的改变. 自动检测删除和冲突状态.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>镜像 ->></target> @@ -900,22 +795,14 @@ Exclude: \stuff\temp\* <source>Copy locked files</source> <target>复制被锁定的文件</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -通过卷影复制服务复制共享或锁定的文件(需要管理员权限) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>通过卷影复制服务复制共享或锁定的文件(需要管理员权限)</target> <source>Copy file access permissions</source> <target>复制文件存取权限</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -转移文件和目录的权限(需要管理员权限) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>转移文件和目录的权限(需要管理员权限)</target> <source>Hidden dialogs:</source> <target>隐藏对话框:</target> @@ -947,6 +834,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>查找下一个(&F)</target> +<source>Operation aborted!</source> +<target>操作已取消!</target> + <source>Main bar</source> <target>主工具条</target> @@ -1124,6 +1014,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>文件清单已经导出!</target> +<source>Error writing file:</source> +<target>写入文件出错:</target> + <source>Batch file created successfully!</source> <target>批处理文件创建成功!</target> @@ -1219,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>过滤器:单一的配对</target> -<source>Ignore</source> -<target>忽略</target> - <source>Direct</source> <target>直接</target> @@ -1283,6 +1173,102 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>移动文件到时间标记子目录</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x 分</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x 小时</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x 天</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>不能初始化目录监视:</target> + +<source>Error when monitoring directories.</source> +<target>监视目录时出错.</target> + +<source>Conversion error:</source> +<target>转换错误:</target> + +<source>Error deleting file:</source> +<target>删除文件出错:</target> + +<source>Error moving file:</source> +<target>移动文件时出错:</target> + +<source>Target file already existing!</source> +<target>目标文件已经存在!</target> + +<source>Error moving directory:</source> +<target>移动目录时出错:</target> + +<source>Target directory already existing!</source> +<target>目标目录已经存在!</target> + +<source>Error deleting directory:</source> +<target>删除目录出错:</target> + +<source>Error changing modification time:</source> +<target>改变修改时间时出错:</target> + +<source>Error loading library function:</source> +<target>加载库函数出错:</target> + +<source>Error reading security context:</source> +<target>读取安全上下文时出错:</target> + +<source>Error writing security context:</source> +<target>写入安全上下文时出错:</target> + +<source>Error copying file permissions:</source> +<target>复制文件权限时出错:</target> + +<source>Error creating directory:</source> +<target>创建目录出错:</target> + +<source>Error copying symbolic link:</source> +<target>复制符号链接时出错:</target> + +<source>Error copying file:</source> +<target>复制文件出错:</target> + +<source>Error opening file:</source> +<target>打开文件出错:</target> + +<source>Error traversing directory:</source> +<target>遍历目录出错:</target> + +<source>Endless loop when traversing directory:</source> +<target>遍历目录时出现无限循环:</target> + +<source>Error setting privilege:</source> +<target>设置权限时出错:</target> + <source>Both sides have changed since last synchronization!</source> <target>在最后的同步之后两边均已改变!</target> @@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>目录有依赖性!在设立同步规则时请小心:</target> -<source>Comparing content of files %x</source> -<target>正在比较文件 %x 的内容</target> - <source>Memory allocation failed!</source> <target>内存分配失败!</target> @@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>符号连接 %x 有相同的日期但目标不同!</target> +<source>Comparing content of files %x</source> +<target>正在比较文件 %x 的内容</target> + <source>Comparing files by content failed.</source> <target>按文件内容比较失败.</target> <source>Generating file list...</source> <target>生成文件列表...</target> -<source>Multiple...</source> -<target>并联...</target> - <source>Both sides are equal</source> <target>两侧相等</target> @@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>删除右侧文件/文件夹</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>从右侧覆盖左侧的文件/文件夹</target> @@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>仅复制文件属性到右侧</target> +<source>Multiple...</source> +<target>并联...</target> + <source>Deleting file %x</source> <target>正删除文件 %x</target> diff --git a/BUILD/Languages/chinese_traditional.lng b/BUILD/Languages/chinese_traditional.lng index f872c6aa..380d2c9b 100644 --- a/BUILD/Languages/chinese_traditional.lng +++ b/BUILD/Languages/chinese_traditional.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>即時同步 - 自動同步</target> -<source>Browse</source> -<target>瀏覽</target> - -<source>Windows Error Code %x:</source> -<target>Windows 錯誤代碼 %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux 錯誤代碼 %x:</target> - -<source>Invalid command line: %x</source> -<target>無效的命令列:%x</target> - -<source>Error resolving symbolic link:</source> -<target>解析錯誤的符號連結:</target> - -<source>Show pop-up</source> -<target>顯示彈出視窗</target> - -<source>Show pop-up on errors or warnings</source> -<target>在彈出視窗上顯示錯誤或警告訊息</target> - -<source>Ignore errors</source> -<target>忽略錯誤</target> - -<source>Hide all error and warning messages</source> -<target>隱藏所有錯誤和警告訊息</target> - -<source>Exit instantly</source> -<target>立即退出</target> - -<source>Abort synchronization immediately</source> -<target>立即中止同步</target> - <source>Select alternate comparison settings</source> <target>選擇替代的比對設定</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>選擇時間範圍</target> +<source>Show pop-up</source> +<target>顯示彈出視窗</target> + +<source>Show pop-up on errors or warnings</source> +<target>在彈出視窗上顯示錯誤或警告訊息</target> + +<source>Ignore errors</source> +<target>忽略錯誤</target> + +<source>Hide all error and warning messages</source> +<target>隱藏所有錯誤和警告訊息</target> + +<source>Exit instantly</source> +<target>立即退出</target> + +<source>Abort synchronization immediately</source> +<target>立即中止同步</target> + +<source>Browse</source> +<target>瀏覽</target> + +<source>Error reading from synchronization database:</source> +<target>讀取同步資料庫錯誤:</target> + +<source>Error writing to synchronization database:</source> +<target>寫入同步資料庫錯誤:</target> + +<source>Invalid command line: %x</source> +<target>無效的命令列:%x</target> + +<source>Windows Error Code %x:</source> +<target>Windows 錯誤代碼 %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux 錯誤代碼 %x:</target> + +<source>Error resolving symbolic link:</source> +<target>解析錯誤的符號連結:</target> + <source>%x MB</source> <target>%x MB</target> @@ -162,17 +168,14 @@ <source>Comparison Result</source> <target>比對結果</target> -<source>Incompatible synchronization database format:</source> -<target>同步資料庫格式不相容:</target> - <source>Initial synchronization:</source> <target>初始化同步:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>其中一個 FreeFileSync 資料庫檔案不存在:</target> -<source>Error reading from synchronization database:</source> -<target>讀取同步資料庫錯誤:</target> +<source>Incompatible synchronization database format:</source> +<target>同步資料庫格式不相容:</target> <source>Database files do not share a common synchronization session:</source> <target>資料庫檔案不共享一個共同的同步連線:</target> @@ -197,12 +200,18 @@ <pluralform>%x 秒</pluralform> </target> +<source>Drag && drop</source> +<target>拖放</target> + <source>Info</source> <target>訊息</target> <source>Fatal Error</source> <target>嚴重錯誤</target> +<source>Error reading file:</source> +<target>讀取檔案錯誤:</target> + <source>Scanning:</source> <target>正在掃瞄:</target> @@ -220,15 +229,36 @@ <source>Invalid FreeFileSync config file!</source> <target>無效的 FreeFileSync 配置檔案!</target> -<source>File does not exist:</source> -<target>檔案不存在:</target> - <source>Error parsing configuration file:</source> <target>分析配置檔案錯誤:</target> +<source>Error moving to Recycle Bin:</source> +<target>移動到資源回收筒錯誤:</target> + +<source>Could not load a required DLL:</source> +<target>無法載入一個所需的DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>讀取卷影複製服務時錯誤!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>不支援製作 WOW64 上的卷影副本。請使用 FreeFileSync 64位元版本。</target> + +<source>Could not determine volume name for file:</source> +<target>無法判斷此檔案的卷標名稱:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>卷名 %x 並非檔名 %y 的一部份!</target> + <source>/sec</source> <target>/秒</target> +<source>File does not exist:</source> +<target>檔案不存在:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>無法讀取 XML 之後節點的值:</target> + <source>S&ave configuration...</source> <target>儲存配置(&A)...</target> @@ -321,138 +351,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>目錄輸入的欄位為空</target> -<source>Drag && drop</source> -<target>拖放</target> - -<source>Could not initialize directory monitoring:</source> -<target>無法初始化目錄監測:</target> - -<source>Error when monitoring directories.</source> -<target>監測目錄錯誤。</target> - -<source>Conversion error:</source> -<target>轉換錯誤:</target> - -<source>Error deleting file:</source> -<target>刪除檔案錯誤:</target> - -<source>Error moving file:</source> -<target>移動檔案錯誤:</target> - -<source>Target file already existing!</source> -<target>目標檔案已存在!</target> - -<source>Error moving directory:</source> -<target>移動目錄錯誤:</target> - -<source>Target directory already existing!</source> -<target>目標目錄已存在!</target> - -<source>Error deleting directory:</source> -<target>刪除目錄錯誤:</target> - -<source>Error changing modification time:</source> -<target>變更修改時間錯誤:</target> - -<source>Error loading library function:</source> -<target>載入函數庫錯誤:</target> - -<source>Error reading security context:</source> -<target>讀取安全內文錯誤:</target> - -<source>Error writing security context:</source> -<target>寫入安全性內容錯誤:</target> - -<source>Error copying file permissions:</source> -<target>複製檔案權限錯誤:</target> - -<source>Error creating directory:</source> -<target>新建目錄錯誤:</target> - -<source>Error copying symbolic link:</source> -<target>複製符號連結錯誤:</target> - -<source>Error copying file:</source> -<target>複製檔案錯誤:</target> - -<source>Error opening file:</source> -<target>開啟檔案錯誤:</target> - -<source>Error writing file:</source> -<target>寫入檔案錯誤:</target> - -<source>Error reading file:</source> -<target>讀取檔案錯誤:</target> - -<source>Operation aborted!</source> -<target>中止操作!</target> - -<source>Endless loop when traversing directory:</source> -<target>當遍歷目錄時無限循環:</target> - -<source>Error traversing directory:</source> -<target>遍歷目錄錯誤:</target> - -<source>Error setting privilege:</source> -<target>設定權限錯誤:</target> - -<source>Error moving to Recycle Bin:</source> -<target>移動到資源回收筒錯誤:</target> - -<source>Could not load a required DLL:</source> -<target>無法載入一個所需的DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>寫入同步資料庫錯誤:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>讀取卷影複製服務時錯誤!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>不支援製作 WOW64 上的卷影副本。請使用 FreeFileSync 64位元版本。</target> - -<source>Could not determine volume name for file:</source> -<target>無法判斷此檔案的卷標名稱:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>卷名 %x 並非檔名 %y 的一部份!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x 分</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x 小時</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x 天</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>無法讀取 XML 之後節點的值:</target> - <source>Logging</source> <target>日誌記錄</target> @@ -471,9 +369,6 @@ The command line is executed each time: <source>Batch execution</source> <target>批次處理執行</target> -<source>Log-messages:</source> -<target>日誌訊息:</target> - <source>Stop</source> <target>停止</target> @@ -600,6 +495,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>將要傳輸的全部資料量</target> +<source>Operation:</source> +<target>操作:</target> + +<source>Items found:</source> +<target>尋找要素:</target> + +<source>Items remaining:</source> +<target>剩餘要素:</target> + +<source>Speed:</source> +<target>速度:</target> + +<source>Time remaining:</source> +<target>剩餘時間:</target> + +<source>Time elapsed:</source> +<target>經過時間:</target> + <source>Batch job</source> <target>批次處理作業</target> @@ -648,31 +561,13 @@ The command line is executed each time: <source>&Cancel</source> <target>取消(&C)</target> -<source>Operation:</source> -<target>操作:</target> - -<source>Items found:</source> -<target>尋找要素:</target> - -<source>Items remaining:</source> -<target>剩餘要素:</target> - -<source>Speed:</source> -<target>速度:</target> - -<source>Time remaining:</source> -<target>剩餘時間:</target> - -<source>Time elapsed:</source> -<target>經過時間:</target> - <source>Select variant:</source> <target>選擇變數:</target> <source><Automatic></source> <target><自動></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> <target>對兩邊使用同一個資料庫的識別和傳送更改。自動檢測刪除和衝突部份。</target> <source>Mirror ->></source> @@ -886,27 +781,19 @@ Exclude: \stuff\temp\* <target>異動檔案副本</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>第一次將檔寫入到一個暫存 (*.ffs_tmp) 順便將它們重新命名。即使在嚴重錯誤的情況下,還可確保一致的狀態。</target> <source>Copy locked files</source> <target>複製被鎖定的檔案</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -複製共用或鎖定檔案使用使用卷影複製服務(需要管理員權限) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>複製共用或鎖定檔案使用使用卷影複製服務(需要管理員權限)</target> <source>Copy file access permissions</source> <target>複製檔案系統權限</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -傳輸檔案和目錄權限(需要管理員權限) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>傳輸檔案和目錄權限(需要管理員權限)</target> <source>Hidden dialogs:</source> <target>隱藏對話框:</target> @@ -938,6 +825,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>找下一個(&F)</target> +<source>Operation aborted!</source> +<target>中止操作!</target> + <source>Main bar</source> <target>主欄位</target> @@ -978,16 +868,16 @@ Transfer file and directory permissions (Requires Administrator rights) <target>自動調整欄寬</target> <source>Icon size:</source> -<target></target> +<target>圖示大小:</target> <source>Small</source> -<target></target> +<target>小</target> <source>Medium</source> -<target></target> +<target>中</target> <source>Large</source> -<target></target> +<target>大</target> <source>Include all rows</source> <target>包括所有行</target> @@ -1115,6 +1005,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>檔案清單已匯出!</target> +<source>Error writing file:</source> +<target>寫入檔案錯誤:</target> + <source>Batch file created successfully!</source> <target>批次檔新建成功!</target> @@ -1131,7 +1024,7 @@ Transfer file and directory permissions (Requires Administrator rights) <pluralform>%x directories</pluralform> </source> <target> -<pluralform>%x 目錄</pluralform> +<pluralform>%x 個目錄</pluralform> </target> <source> @@ -1139,7 +1032,7 @@ Transfer file and directory permissions (Requires Administrator rights) <pluralform>%x files</pluralform> </source> <target> -<pluralform>%x 檔案</pluralform> +<pluralform>%x 個檔案</pluralform> </target> <source> @@ -1210,9 +1103,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>篩選器:單對</target> -<source>Ignore</source> -<target>忽略</target> - <source>Direct</source> <target>直接</target> @@ -1274,6 +1164,102 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>移動檔案到一個時間標記的子目錄</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x 分</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x 小時</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x 天</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>無法初始化目錄監測:</target> + +<source>Error when monitoring directories.</source> +<target>監測目錄錯誤。</target> + +<source>Conversion error:</source> +<target>轉換錯誤:</target> + +<source>Error deleting file:</source> +<target>刪除檔案錯誤:</target> + +<source>Error moving file:</source> +<target>移動檔案錯誤:</target> + +<source>Target file already existing!</source> +<target>目標檔案已存在!</target> + +<source>Error moving directory:</source> +<target>移動目錄錯誤:</target> + +<source>Target directory already existing!</source> +<target>目標目錄已存在!</target> + +<source>Error deleting directory:</source> +<target>刪除目錄錯誤:</target> + +<source>Error changing modification time:</source> +<target>變更修改時間錯誤:</target> + +<source>Error loading library function:</source> +<target>載入函數庫錯誤:</target> + +<source>Error reading security context:</source> +<target>讀取安全內文錯誤:</target> + +<source>Error writing security context:</source> +<target>寫入安全性內容錯誤:</target> + +<source>Error copying file permissions:</source> +<target>複製檔案權限錯誤:</target> + +<source>Error creating directory:</source> +<target>新建目錄錯誤:</target> + +<source>Error copying symbolic link:</source> +<target>複製符號連結錯誤:</target> + +<source>Error copying file:</source> +<target>複製檔案錯誤:</target> + +<source>Error opening file:</source> +<target>開啟檔案錯誤:</target> + +<source>Error traversing directory:</source> +<target>遍歷目錄錯誤:</target> + +<source>Endless loop when traversing directory:</source> +<target>當遍歷目錄時無限循環:</target> + +<source>Error setting privilege:</source> +<target>設定權限錯誤:</target> + <source>Both sides have changed since last synchronization!</source> <target>自上次同步後,兩邊均已更改過!</target> @@ -1304,9 +1290,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>目錄有依靠性!請小心設定同步規則:</target> -<source>Comparing content of files %x</source> -<target>正在比對檔案内容的百分比 %x</target> - <source>Memory allocation failed!</source> <target>記憶體分配失敗!</target> @@ -1322,15 +1305,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>符號連結 %x 有相同日期但是不同目標!</target> +<source>Comparing content of files %x</source> +<target>正在比對檔案内容的百分比 %x</target> + <source>Comparing files by content failed.</source> <target>比對檔案內容失敗。</target> <source>Generating file list...</source> <target>產生檔案清單...</target> -<source>Multiple...</source> -<target>多個...</target> - <source>Both sides are equal</source> <target>兩邊都相同</target> @@ -1349,6 +1332,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>刪除右邊檔案/資料夾</target> +<source>Move file on left</source> +<target>移動左邊的檔案</target> + +<source>Move file on right</source> +<target>移動右邊的檔案</target> + <source>Overwrite left file/folder with right one</source> <target>用適合檔案/資料夾覆蓋左邊檔案/資料夾</target> @@ -1364,6 +1353,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>只複製檔案屬性到右邊</target> +<source>Multiple...</source> +<target>多個...</target> + <source>Deleting file %x</source> <target>正在刪除檔案 %x</target> diff --git a/BUILD/Languages/croatian.lng b/BUILD/Languages/croatian.lng new file mode 100644 index 00000000..cba3663a --- /dev/null +++ b/BUILD/Languages/croatian.lng @@ -0,0 +1,1490 @@ +<header> + <language name>Hrvatski</language name> + <translator>Slavko Blažević</translator> + <locale>hr_HR</locale> + <flag file>croatia.png</flag file> + <plural forms>3</plural forms> + <plural definition>n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2</plural definition> +</header> + +<source>Searching for directory %x...</source> +<target>Tražim direktorij %x...</target> + +<source>Show in Explorer</source> +<target>Prikaži u Exploreru</target> + +<source>Open with default application</source> +<target>Otvori s zadanom aplikacijom</target> + +<source>Browse directory</source> +<target>Odaberi direktorij</target> + +<source>RealtimeSync - Automated Synchronization</source> +<target>RealtimeSync - Automatska Sinkronizacija</target> + +<source>Select alternate comparison settings</source> +<target>Izaberite alternativne postavke usporedbe</target> + +<source>Select alternate synchronization settings</source> +<target>Izaberite alternativne postavke sinkronizacije</target> + +<source>No filter selected</source> +<target>Nijedan filter odabran</target> + +<source>Filter is active</source> +<target>Filter je aktivan</target> + +<source>Remove alternate settings</source> +<target>Ukloni alternativne postavke</target> + +<source>Clear filter settings</source> +<target>Počisti postavke filtera</target> + +<source>Create a batch job</source> +<target>Izradi batch zadatak</target> + +<source>Synchronization settings</source> +<target>Postavke sinkronizacije</target> + +<source>Comparison settings</source> +<target>Postavke usporedbe</target> + +<source>About</source> +<target>O programu</target> + +<source>Error</source> +<target>Greška</target> + +<source>Warning</source> +<target>Oprez</target> + +<source>Question</source> +<target>Pitanje</target> + +<source>Confirm</source> +<target>Potvrdi</target> + +<source>Configure filter</source> +<target>Konfiguriraj filter</target> + +<source>Customize columns</source> +<target>Uredi stupce</target> + +<source>Global settings</source> +<target>Globalne postavke</target> + +<source>Synchronization Preview</source> +<target>Pregled sinkronizacije</target> + +<source>Find</source> +<target>Pronađi</target> + +<source>Select time span</source> +<target>Izaberite mjerni raspon</target> + +<source>Show pop-up</source> +<target>Prikaži skočni prozor</target> + +<source>Show pop-up on errors or warnings</source> +<target>Prikaži skočni prozor pri greškama i upozorenjima</target> + +<source>Ignore errors</source> +<target>Ignoriraj greške</target> + +<source>Hide all error and warning messages</source> +<target>Sakrij sve greške i upozorenja</target> + +<source>Exit instantly</source> +<target>Izađi trenutno</target> + +<source>Abort synchronization immediately</source> +<target>Odmah prekini sinkronizaciju</target> + +<source>Browse</source> +<target>Odaberi</target> + +<source>Error reading from synchronization database:</source> +<target>Greška pri čitanju iz sinkronizacijske baze:</target> + +<source>Error writing to synchronization database:</source> +<target>Greška pri pisanju u sinkronizacijsku bazu:</target> + +<source>Invalid command line: %x</source> +<target>Netočna naredba: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows greška %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux greška %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Pogreška pri otvaranju poveznice simbola:</target> + +<source>%x MB</source> +<target>%x MB</target> + +<source>%x KB</source> +<target>%x KB</target> + +<source>%x GB</source> +<target>%x GB</target> + +<source> +<pluralform>1 Byte</pluralform> +<pluralform>%x Bytes</pluralform> +</source> +<target> +<pluralform>%x Bajt</pluralform> +<pluralform>%x Bajta</pluralform> +<pluralform>%x Bajtova</pluralform> +</target> + +<source><Symlink></source> +<target><Poveznica simbola></target> + +<source><Directory></source> +<target><Direktorij></target> + +<source>Size</source> +<target>Veličina</target> + +<source>Date</source> +<target>Datum</target> + +<source>Full path</source> +<target>Puna putanja</target> + +<source>Filename</source> +<target>Ime datoteke</target> + +<source>Relative path</source> +<target>Relativna Putanja</target> + +<source>Directory</source> +<target>Direktorij</target> + +<source>Extension</source> +<target>Ekstenzija</target> + +<source>Comparison Result</source> +<target>Rezultati usporedbe</target> + +<source>Initial synchronization:</source> +<target>Početna sinkronizacija:</target> + +<source>One of the FreeFileSync database files is not yet existing:</source> +<target>Jedna od FreeFileSync datoteka podatkovne baze još ne postoji:</target> + +<source>Incompatible synchronization database format:</source> +<target>Nekompatibilan format sinkronizacijske podatkovne baze:</target> + +<source>Database files do not share a common synchronization session:</source> +<target>Datoteke podatkovne baze ne dijele zajedničke sinkronizacijske sesije:</target> + +<source>An exception occurred!</source> +<target>Dogodilo se izuzeće!</target> + +<source>Error reading file attributes:</source> +<target>Greška pri čitanju atributa datoteke:</target> + +<source>Waiting while directory is locked (%x)...</source> +<target>Čekam dok se direktorij zaključava (%x)...</target> + +<source>Error setting directory lock:</source> +<target>Greška pri postavljanju zaključenja direktorija:</target> + +<source> +<pluralform>1 sec</pluralform> +<pluralform>%x sec</pluralform> +</source> +<target> +<pluralform>%x sek</pluralform> +<pluralform>%x sek</pluralform> +<pluralform>%x sek</pluralform> +</target> + +<source>Drag && drop</source> +<target>Povuci && ispusti</target> + +<source>Info</source> +<target>Info</target> + +<source>Fatal Error</source> +<target>Kritična greška</target> + +<source>Error reading file:</source> +<target>Greška pri čitanju datoteke:</target> + +<source>Scanning:</source> +<target>Pretražujem:</target> + +<source>Encoding extended time information: %x</source> +<target>:Spremam informacije o vremenu %x</target> + +<source> +<pluralform>[1 Thread]</pluralform> +<pluralform>[%x Threads]</pluralform> +</source> +<target> +<pluralform>%x Stavka</pluralform> +<pluralform>%x Stavke</pluralform> +<pluralform>% Stavki</pluralform> +</target> + +<source>Invalid FreeFileSync config file!</source> +<target>Nevaljana FreeFileSync konfiguracijska datoteka!</target> + +<source>Error parsing configuration file:</source> +<target>Greška pri raščlanjivanju datoteke postavki:</target> + +<source>Error moving to Recycle Bin:</source> +<target>Greška pri premještanju u Koš za smeće:</target> + +<source>Could not load a required DLL:</source> +<target>Nemože se pokrenuti potrebni DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Greška pri pristupu servisu particijskog kopiranja!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Stvaranje sjeničnih kopija na WOW63 nije podržano. Molimo koristite 64-bitnu FreeFileSync inačnicu.</target> + +<source>Could not determine volume name for file:</source> +<target>Nemože se odrediti naziv particije za datoteku:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Naziv particije %x dio naziva datoteke %y!</target> + +<source>/sec</source> +<target>/sek</target> + +<source>File does not exist:</source> +<target>Datoteka ne postoji:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Nemogu pročitati vrijednosti iz slijedećih XML središta:</target> + +<source>S&ave configuration...</source> +<target>&Spremi postavke...</target> + +<source>&Load configuration...</source> +<target>&Uvezi postavke...</target> + +<source>&Quit</source> +<target>&Izlaz</target> + +<source>&File</source> +<target>&Datoteka</target> + +<source>&Content</source> +<target>&Sadržaj</target> + +<source>&About...</source> +<target>&O programu...</target> + +<source>&Help</source> +<target>&Pomoć</target> + +<source>Usage:</source> +<target>Uporaba:</target> + +<source>1. Select directories to monitor.</source> +<target>1. Izaberite mape za nadziranje</target> + +<source>2. Enter a command line.</source> +<target>2. Unesite naredbu.</target> + +<source>3. Press 'Start'.</source> +<target>3. Pretisnite 'Start'.</target> + +<source> +The command line is executed each time: +- all directories become available (e.g. USB stick insert) +- files within these directories or subdirectories are modified +</source> +<target> +Naredba će biti izvršena kada: +- sve mape postanu dostupne (npr. USB stick je umetnut) +- datoteke unutar tih mapa ili podmapa budu mijenjane +</target> + +<source>Directories to watch</source> +<target>Mape za nadziranje</target> + +<source>Add folder</source> +<target>Dodaj mapu</target> + +<source>Remove folder</source> +<target>Ukloni mapu</target> + +<source>Select a folder</source> +<target>Izaberite mapu</target> + +<source>Command line</source> +<target>Naredbena linija</target> + +<source>Minimum Idle Time [seconds]</source> +<target>Minimalno vrijeme pripravnosti [sekunde]</target> + +<source>Idle time between detection of last change and execution of command line in seconds</source> +<target>Vrijeme pripravnosti između pronalaska zadnje promjene i izvršenja naredbe u sekundama</target> + +<source>Start</source> +<target>Start</target> + +<source>(Build: %x)</source> +<target>(Inačnica: %x)</target> + +<source>RealtimeSync configuration</source> +<target>RealtimeSync postavke</target> + +<source>File already exists. Overwrite?</source> +<target>Datoteka već postoji. Prepisati?</target> + +<source>&Restore</source> +<target>&Vrati</target> + +<source>&Exit</source> +<target>&Izlaz</target> + +<source>Monitoring active...</source> +<target>Nadziranje aktivno...</target> + +<source>Waiting for missing directories...</source> +<target>Čekam nedostajuće direktorije...</target> + +<source>A directory input field is empty.</source> +<target>Upisno polje za direktorij je prazno.</target> + +<source>Logging</source> +<target>Zapisivanje</target> + +<source>FreeFileSync batch file</source> +<target>FreeFileSync batch datoteka</target> + +<source>FreeFileSync configuration</source> +<target>FreeFileSync postavke</target> + +<source>FreeFileSync Batch Job</source> +<target>FreeFileSync Batch zadatak</target> + +<source>Unable to create logfile!</source> +<target>Nemogu napraviti zapisnik!</target> + +<source>Batch execution</source> +<target>Batch izvršavanje</target> + +<source>Stop</source> +<target>Zaustavi</target> + +<source>Total time:</source> +<target>Ukupno vrijeme:</target> + +<source>Synchronization aborted!</source> +<target>Sinkronizacija prekinuta!</target> + +<source>Synchronization completed with errors!</source> +<target>Sinkronizacija završena s greškama!</target> + +<source>Synchronization completed successfully!</source> +<target>Sinkronizacija uspješno završena!</target> + +<source>Press "Switch" to open FreeFileSync GUI mode.</source> +<target>Pretisnite "Zamjena", da otvorite FreeFileSync GUI način.</target> + +<source>Switching to FreeFileSync GUI mode...</source> +<target>Prelazim na FreeFileSync GUI način...</target> + +<source>Unable to connect to sourceforge.net!</source> +<target>Ne mogu se povezati na sourceforge.net!</target> + +<source>A newer version of FreeFileSync is available:</source> +<target>Dostupna je nova verzija FreeFileSync:</target> + +<source>Download now?</source> +<target>Preuzeti sada?</target> + +<source>Information</source> +<target>Informacija</target> + +<source>FreeFileSync is up to date!</source> +<target>FreeFileSync je ažuriran!</target> + +<source>Do you want FreeFileSync to automatically check for updates every week?</source> +<target>Dali želite da FreeFileSync automatski traži ažuriranja svaki tjedan?</target> + +<source>(Requires an Internet connection!)</source> +<target>(Zahtjeva vezu na Internet!)</target> + +<source>1. &Compare</source> +<target>1. &Usporedi</target> + +<source>2. &Synchronize...</source> +<target>2. &Sinkroniziraj...</target> + +<source>S&witch view</source> +<target>Pr&omjeni pogled</target> + +<source>&New</source> +<target>&Novo</target> + +<source>&Program</source> +<target>&Program</target> + +<source>&Language</source> +<target>&Jezik</target> + +<source>&Global settings...</source> +<target>&Globalne postavke...</target> + +<source>&Create batch job...</source> +<target>&Izradi batch zadatak...</target> + +<source>&Export file list...</source> +<target>&Izvoz liste datoteka...</target> + +<source>&Advanced</source> +<target>&Napredno</target> + +<source>&Check for new version</source> +<target>&Provjeri za novu verziju</target> + +<source>Compare</source> +<target>Usporedi</target> + +<source>Compare both sides</source> +<target>Usporedi obje strane</target> + +<source>&Abort</source> +<target>&Odustani</target> + +<source>Synchronize...</source> +<target>Sinkroniziraj...</target> + +<source>Start synchronization</source> +<target>Započni sinkronizaciju</target> + +<source>Add folder pair</source> +<target>Dodaj mapu</target> + +<source>Remove folder pair</source> +<target>Odstrani mapu</target> + +<source>Swap sides</source> +<target>Zamjeni strane</target> + +<source>Save current configuration to file</source> +<target>Spremi sadašnje postavke u datoteku</target> + +<source>Load configuration from file</source> +<target>Uvezi postavke iz datoteke</target> + +<source>Last used configurations (press DEL to remove from list)</source> +<target>Zadnje korištene postavke (pretisite DEL za ukloniti s liste)</target> + +<source>Hide excluded items</source> +<target>Sakrij isključene stavke</target> + +<source>Hide filtered or temporarily excluded files</source> +<target>Sakrij filtrirane ili trenutno isključene datoteke</target> + +<source>Number of files and directories that will be created</source> +<target>Broj datoteka i direktorija koji će biti napravljeni</target> + +<source>Number of files that will be overwritten</source> +<target>Broj datoteka koje će biti prepisane</target> + +<source>Number of files and directories that will be deleted</source> +<target>Broj datoteka i direktorija koji će biti izbrisani</target> + +<source>Total amount of data that will be transferred</source> +<target>Ukupna količina podataka koja će biti prebečana</target> + +<source>Operation:</source> +<target>Operacija:</target> + +<source>Items found:</source> +<target>Pronađene stavke:</target> + +<source>Items remaining:</source> +<target>Preostale stavke:</target> + +<source>Speed:</source> +<target>Brzina:</target> + +<source>Time remaining:</source> +<target>Vremena preostalo:</target> + +<source>Time elapsed:</source> +<target>Vremena prošlo:</target> + +<source>Batch job</source> +<target>Batch zadatak</target> + +<source>Create a batch file for automated synchronization. To start in batch mode simply double-click the file or execute via command line: FreeFileSync.exe <ffs_batch file>. This can also be scheduled in your operating system's task planner.</source> +<target>Napravite batch datoteku za automatsku sinkronizaciju. Da bi započeli batch mod dvostruki-klik na fajl ili izvršite pomoću komandne linije: FreeFileSync.exe <ffs_batch datoteka>. Ovo se također može zadati u planeru operacijskog sustava.</target> + +<source>Help</source> +<target>Pomoć</target> + +<source>Filter files</source> +<target>Filtriraj datoteke</target> + +<source>Error handling</source> +<target>Greška pri obradi</target> + +<source>Left</source> +<target>Lijevo</target> + +<source>Right</source> +<target>Desno</target> + +<source>Overview</source> +<target>Pregled</target> + +<source>Status feedback</source> +<target>Status veze</target> + +<source>Run minimized</source> +<target>Pokreni minimizirano</target> + +<source>Maximum number of logfiles:</source> +<target>Maksimalan broj izvješća:</target> + +<source>Select logfile directory:</source> +<target>Odaberite direktorij izvješća:</target> + +<source>Batch settings</source> +<target>Batch postavke</target> + +<source>&Save</source> +<target>&Spremi</target> + +<source>&Load</source> +<target>&Uvezi</target> + +<source>&Cancel</source> +<target>&Odustani</target> + +<source>Select variant:</source> +<target>Izaberite varijantu:</target> + +<source><Automatic></source> +<target><Automatski></target> + +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identificiraj i izvedi promjene na obje strane koristeći bazu podataka. Brisanja, preimenovanja i sukobi se automatski detektiraju</target> + +<source>Mirror ->></source> +<target>Zrcalno ->></target> + +<source>Mirror backup of left folder. Right folder is modified to exactly match left folder after synchronization.</source> +<target>Zrcalna pričuva lijeve mape. Desna mapa je uređena da bi bila jednaka lijevom folderu nakon sinkronizacije.</target> + +<source>Update -></source> +<target>Ažuriraj -></target> + +<source>Copy new or updated files to right folder.</source> +<target>Kopiraj nove ili ažurirane datoteke u desnu mapu.</target> + +<source>Custom</source> +<target>Uobičajeno</target> + +<source>Configure your own synchronization rules.</source> +<target>Konfigurirajte vaša vlastita sinkronizacijska pravila.</target> + +<source>Deletion handling</source> +<target>Upravljanje pri brisanju</target> + +<source>&OK</source> +<target>&U redu</target> + +<source>Configuration</source> +<target>Postavke</target> + +<source>Category</source> +<target>Kategorija</target> + +<source>Action</source> +<target>Radnja</target> + +<source>File/folder exists on left side only</source> +<target>Datoteka/mapa postoji samo na lijevoj strani</target> + +<source>File/folder exists on right side only</source> +<target>Datoteka/mapa postoji samo na desnoj strani</target> + +<source>Left file is newer</source> +<target>Lijeva datoteka je novija</target> + +<source>Right file is newer</source> +<target>Desna datoteka je novija</target> + +<source>Files have different content</source> +<target>Datoteke imaju različit sadržaj</target> + +<source>Conflict/file cannot be categorized</source> +<target>Konflikt/datoteka ne more biti kategorizirana</target> + +<source>Compare by...</source> +<target>Usporedi prema...</target> + +<source> +Files are found equal if + - last write time and date + - file size +are the same +</source> +<target> +Datoteke se smatraju jednake ako su im + - vrijeme zadnje promjene i datum + - veličina datoteke +jednaki +</target> + +<source>File time and size</source> +<target>Vrijeme i veličina datoteke</target> + +<source> +Files are found equal if + - file content +is the same +</source> +<target> +Datoteke se smatraju jednake ako im je + - sadržaj datoteke +jednak +</target> + +<source>File content</source> +<target>Sadržaj datoteke</target> + +<source>Symbolic Link handling</source> +<target>Upravljanje simboličnim poveznicama</target> + +<source>Synchronizing...</source> +<target>Sinkroniziram...</target> + +<source>Items processed:</source> +<target>Obrađeni elementi:</target> + +<source>&Pause</source> +<target>&Pauziraj</target> + +<source>Source code written in C++ utilizing:</source> +<target>Izvorni kod napisan u C++ uz korištenje:</target> + +<source>Big thanks for localizing FreeFileSync goes out to:</source> +<target>Zahvale za prijevod FreeFileSync idu:</target> + +<source>Feedback and suggestions are welcome at:</source> +<target>Povratne informacije i prijedlozi su dobrodošli na:</target> + +<source>FreeFileSync at Sourceforge</source> +<target>FreeFileSync na Sourceforge</target> + +<source>Homepage</source> +<target>Početna stranica</target> + +<source>If you like FFS</source> +<target>Ako volite FFS</target> + +<source>Donate with PayPal</source> +<target>Doniraj s PayPal</target> + +<source>Email</source> +<target>Email</target> + +<source>Report translation error</source> +<target>Prijavi grešku u prijevodu</target> + +<source>Published under the GNU General Public License:</source> +<target>Objavljeno pod licencom GNU General Public:</target> + +<source>Ignore subsequent errors</source> +<target>Ignoriraj naknadne greške</target> + +<source>Hide further error messages during the current process</source> +<target>Sakrij iduće poruke grešaka tokom slijedećeg procesa</target> + +<source>&Ignore</source> +<target>&Ignoriraj</target> + +<source>&Retry</source> +<target>&Ponovi</target> + +<source>Do not show this dialog again</source> +<target>Ne prikazuj ovaj prozor ponovno</target> + +<source>&Switch</source> +<target>&Zamjeni</target> + +<source>&Yes</source> +<target>&Da</target> + +<source>&No</source> +<target>&Ne</target> + +<source>Delete on both sides</source> +<target>Izbriši na obje strane</target> + +<source>Delete on both sides even if the file is selected on one side only</source> +<target>Izbriši na obje strane iako je označena datoteka samo na jednoj strani</target> + +<source>Use Recycle Bin</source> +<target>Uporabi Koš za smeće</target> + +<source> +Only files/directories that match all filter settings will be selected for synchronization. +Note: The name filter must be specified relative(!) to main synchronization directories. +</source> +<target> +Samo datoteke/direktorije koji odgovaraju svim filterskim postavkama će biti odabrane za sinkronizaciju. +Napomena: Ime filtra mora biti određeno relativno(!) prema glavnim sinkronizacijskim direktorijima. +</target> + +<source>Hints:</source> +<target>Savjeti:</target> + +<source>1. Enter relative file or directory names separated by ';' or a new line.</source> +<target>1. Unesite relativno ime datoteke ili naziva direktorija odvojeno ';' ili novim redom.</target> + +<source>2. Use wildcard characters '*' and '?'.</source> +<target>2. Uporabite znakove poput '*' ili '?'.</target> + +<source>3. Exclude files directly on main grid via context menu.</source> +<target>3. Isključite datoteke neposredno na glavnoj mreži s kontekstnog menija.</target> + +<source>Example</source> +<target>Primjer</target> + +<source> +Include: *.doc;*.zip;*.exe +Exclude: \stuff\temp\* +</source> +<target> +Uključi: *.doc;*.zip;*.exe +Isključi: \stuff\temp\* +</target> + +<source>Synchronize all .doc, .zip and .exe files except everything in subfolder "temp".</source> +<target>Sinkroniziraj sve .doc, .zip i .exe datoteke, izuzev svega iz podmape "temp".</target> + +<source>Include</source> +<target>Uključi</target> + +<source>Exclude</source> +<target>Isključi</target> + +<source>Minimum file size</source> +<target>Minimalna veličina datoteke</target> + +<source>Maximum file size</source> +<target>Maksimalna veličina datoteke</target> + +<source>&Default</source> +<target>&Zadano</target> + +<source>Move column up</source> +<target>Premakni stupac gore</target> + +<source>Move column down</source> +<target>Premakni stupac dolje</target> + +<source>Transactional file copy</source> +<target>Transakcijsko kopiranje datoteke</target> + +<source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> +<target>Zapiši u privremenu datoteku (*.ffs_tmp) najprije a onda ju preimenuj. Ovo garantira nepromjenjivost čak u slučaju kritične greške.</target> + +<source>Copy locked files</source> +<target>Kopiraj zaključane datoteke</target> + +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopiraj zajedničke ili zaključane datoteke koristeći Volume Shadow Copy Servis(Zahtjeva Administratorske ovlasti)</target> + +<source>Copy file access permissions</source> +<target>Kopiraj datotečna dopuštenja</target> + +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Prebaci datotečna dopuštenja (Zahtjeva Administratorske ovlasti)</target> + +<source>Hidden dialogs:</source> +<target>Skriveni prozori:</target> + +<source>Reset</source> +<target>Resetiraj</target> + +<source>Show hidden dialogs</source> +<target>Prikaži skrivene prozore</target> + +<source>External applications</source> +<target>Vanjske aplikacije</target> + +<source>Description</source> +<target>Opis</target> + +<source>Variant</source> +<target>Način</target> + +<source>Statistics</source> +<target>Statistika</target> + +<source>Find what:</source> +<target>Nađi što</target> + +<source>Match case</source> +<target>Poklopi se</target> + +<source>&Find next</source> +<target>&Nađi slijedeće</target> + +<source>Operation aborted!</source> +<target>Operacija otkazana!</target> + +<source>Main bar</source> +<target>Glavna traka</target> + +<source>Folder pairs</source> +<target>Par mape</target> + +<source>Select view</source> +<target>Izaberite pogled</target> + +<source>Set direction:</source> +<target>Odaberi smijer:</target> + +<source>Exclude temporarily</source> +<target>Trenutno izključi</target> + +<source>Include temporarily</source> +<target>Trenutno uključi</target> + +<source>Exclude via filter:</source> +<target>Isključi preko filtra:</target> + +<source><multiple selection></source> +<target><višestruki odabir></target> + +<source>D-Click</source> +<target>D-Klik</target> + +<source>Delete</source> +<target>Izbriši</target> + +<source>Customize...</source> +<target>Prilagodi...</target> + +<source>Select time span...</source> +<target>Izaberite vremenski raspon...</target> + +<source>Auto-adjust columns</source> +<target>Samo-prilagodi stupce</target> + +<source>Icon size:</source> +<target>Veličina Ikone</target> + +<source>Small</source> +<target>Malo</target> + +<source>Medium</source> +<target>Srednje</target> + +<source>Large</source> +<target>Veliko</target> + +<source>Include all rows</source> +<target>Uključi sve redove</target> + +<source>Exclude all rows</source> +<target>Isključi sve redove</target> + +<source>Reset view</source> +<target>Resetiraj pogled</target> + +<source>Show "%x"</source> +<target>Prikaži "%x"</target> + +<source><Last session></source> +<target><Zadnja sesija></target> + +<source>Configuration saved!</source> +<target>Postavke spremljene!</target> + +<source>Save changes to current configuration?</source> +<target>Spremiti promjene na trenutne postavke?</target> + +<source>Configuration loaded!</source> +<target>Postavke učitane!</target> + +<source>Folder Comparison and Synchronization</source> +<target>Usporedba i sinkronizacija mapa</target> + +<source>Hide files that exist on left side only</source> +<target>Sakrij datoteke koje postoje samo na lijevoj strani</target> + +<source>Show files that exist on left side only</source> +<target>Prikaži datoteke koje postoje samo na lijevoj strani</target> + +<source>Hide files that exist on right side only</source> +<target>Sakrij datoteke koje koje postoje samo na desnoj strani</target> + +<source>Show files that exist on right side only</source> +<target>Prikaži datoteke koje postoje samo na desnoj strani</target> + +<source>Hide files that are newer on left</source> +<target>Sakrij datoteke koje su novije lijevo</target> + +<source>Show files that are newer on left</source> +<target>Prikaži datoteke koje su novije lijevo</target> + +<source>Hide files that are newer on right</source> +<target>Skrij datoteke koje su novije desno</target> + +<source>Show files that are newer on right</source> +<target>Prikaži datoteke koje su novije desno</target> + +<source>Hide files that are equal</source> +<target>Skrij jednake datoteke</target> + +<source>Show files that are equal</source> +<target>Prikaži jednake datoteke</target> + +<source>Hide files that are different</source> +<target>Sakrij datoteke koje su različite</target> + +<source>Show files that are different</source> +<target>Prikaži datoteke koje su različite</target> + +<source>Hide conflicts</source> +<target>Sakrij sukobe</target> + +<source>Show conflicts</source> +<target>Prikaži spore</target> + +<source>Hide files that will be created on the left side</source> +<target>Sakrij datoteke koje će biti napravljene na lijevoj strani</target> + +<source>Show files that will be created on the left side</source> +<target>Prikaži datoteke koje će biti napravljene na lijevoj strani</target> + +<source>Hide files that will be created on the right side</source> +<target>Sakrij datoteke koje će biti napravljene na desnoj strani</target> + +<source>Show files that will be created on the right side</source> +<target>Prikaži datoteke koje će biti napravljene na desnoj strani</target> + +<source>Hide files that will be deleted on the left side</source> +<target>Sakrij datoteke koje će biti izbrisane na lijevoj strani</target> + +<source>Show files that will be deleted on the left side</source> +<target>Prikaži datoteke koje će biti izbrisane na lijevoj strani</target> + +<source>Hide files that will be deleted on the right side</source> +<target>Skrij datoteke koje će biti izbrisane na desnoj strani</target> + +<source>Show files that will be deleted on the right side</source> +<target>Prikaži datoteke koje će biti izbrisane na desnoj strani</target> + +<source>Hide files that will be overwritten on left side</source> +<target>Skrij datoteke koje će biti prepisane na lijevoj strani</target> + +<source>Show files that will be overwritten on left side</source> +<target>Prikaži datoteke koje će biti prepisane na lijevoj strani</target> + +<source>Hide files that will be overwritten on right side</source> +<target>Skrij datoteke koje će biti prepisane na desnoj strani</target> + +<source>Show files that will be overwritten on right side</source> +<target>Prikaži datoteke koje će biti prepisane na desnoj strani</target> + +<source>Hide files that won't be copied</source> +<target>Sakrij datoteke koje neće biti kopirane</target> + +<source>Show files that won't be copied</source> +<target>Prikaži datoteke koje neće biti kopirane</target> + +<source>All directories in sync!</source> +<target>Svi direktoriji su sinkronizirani!</target> + +<source>Please run a Compare first before synchronizing!</source> +<target>Molmo pokrenite Usporedbu prije sinkronizacije!</target> + +<source>Comma separated list</source> +<target>Zarezom odvojene liste</target> + +<source>Legend</source> +<target>Legenda</target> + +<source>File list exported!</source> +<target>Datotečna lista izvezena!</target> + +<source>Error writing file:</source> +<target>Napaka pri pisanju datoteke:</target> + +<source>Batch file created successfully!</source> +<target>Batch datoteka uspješno izrađena!</target> + +<source> +<pluralform>Object deleted successfully!</pluralform> +<pluralform>%x objects deleted successfully!</pluralform> +</source> +<target> +<pluralform>%x Objekt uspješno izbrisan!</pluralform> +<pluralform>%x objekta uspješno izbrisana!</pluralform> +<pluralform>%x objekata uspješno izbrisano!</pluralform> +</target> + +<source> +<pluralform>1 directory</pluralform> +<pluralform>%x directories</pluralform> +</source> +<target> +<pluralform>%x direktorij</pluralform> +<pluralform>%x direktorija</pluralform> +<pluralform>%x direktorija</pluralform> +</target> + +<source> +<pluralform>1 file</pluralform> +<pluralform>%x files</pluralform> +</source> +<target> +<pluralform>%x datoteka</pluralform> +<pluralform>%x datoteke</pluralform> +<pluralform>%x datoteka</pluralform> +</target> + +<source> +<pluralform>%x of 1 row in view</pluralform> +<pluralform>%x of %y rows in view</pluralform> +</source> +<target> +<pluralform>%x od %y red u prikazu</pluralform> +<pluralform>%x od %y reda u prikazu</pluralform> +<pluralform>%x od %y redova u prikazu</pluralform> +</target> + +<source>Scanning...</source> +<target>Pregledajem...</target> + +<source>Comparing content...</source> +<target>Uspoređujem sadržaj...</target> + +<source>Paused</source> +<target>Pauzirano</target> + +<source>Aborted</source> +<target>Prekinuto</target> + +<source>Completed</source> +<target>Završeno</target> + +<source>Abort requested: Waiting for current operation to finish...</source> +<target>Prekid zahtjevan: čekam da se trenutna akcija završi...</target> + +<source>Continue</source> +<target>Nastavi</target> + +<source>Pause</source> +<target>Pauziraj</target> + +<source>Cannot find %x</source> +<target>Nemogu pronać %x</target> + +<source>Inactive</source> +<target>Neaktivno</target> + +<source>Last x hours</source> +<target>Zadnjih x sati</target> + +<source>Today</source> +<target>Danas</target> + +<source>This week</source> +<target>Ovaj tjedan</target> + +<source>This month</source> +<target>Ovaj mjesec</target> + +<source>This year</source> +<target>Ove godine</target> + +<source>Byte</source> +<target>Bajt</target> + +<source>KB</source> +<target>KB</target> + +<source>MB</source> +<target>MB</target> + +<source>Filter: All pairs</source> +<target>Filtriraj: Sve parove</target> + +<source>Filter: Single pair</source> +<target>Filtriraj: Sam par</target> + +<source>Direct</source> +<target>Neposredno</target> + +<source>Follow</source> +<target>Slijedi</target> + +<source>Copy NTFS permissions</source> +<target>Kopiraj NTFS dopuštenja</target> + +<source>Integrate external applications into context menu. The following macros are available:</source> +<target>Integriraj vanjske aplikacije u kontekstni meni. Sljedeći makroi su dostupni:</target> + +<source>- full file or directory name</source> +<target>- puno ime datoteke ili direktorija</target> + +<source>- directory part only</source> +<target>- samo dio direktorija</target> + +<source>- Other side's counterpart to %name</source> +<target>- Duplikat s druge strane k %name</target> + +<source>- Other side's counterpart to %dir</source> +<target>- Duplikat s druge strane k %dir</target> + +<source>Restore all hidden dialogs?</source> +<target>Vrati sve skrivene prozore?</target> + +<source> +<pluralform>Do you really want to move the following object to the Recycle Bin?</pluralform> +<pluralform>Do you really want to move the following %x objects to the Recycle Bin?</pluralform> +</source> +<target> +<pluralform>Dali zaista želite prebaciti navedeni %x objekt u Koš za smeće?</pluralform> +<pluralform>Dali zaista želite prebaciti navedena %x objekta u Koš za smeće?</pluralform> +<pluralform>Dali zaista želite prebaciti navedenih %x objekata u Koš za smeće?</pluralform> +</target> + +<source> +<pluralform>Do you really want to delete the following object?</pluralform> +<pluralform>Do you really want to delete the following %x objects?</pluralform> +</source> +<target> +<pluralform>Dali zaista želite izbrisati navedeni %x objekt?</pluralform> +<pluralform>Dali zaista želite izbrisati navedena %x objekta?</pluralform> +<pluralform>Dali zaista želite izbrisati navedenih %x objekata?</pluralform> +</target> + +<source>Leave as unresolved conflict</source> +<target>Ostavi kao neriješeni sukob</target> + +<source>Delete permanently</source> +<target>Trajno izbriši</target> + +<source>Delete or overwrite files permanently</source> +<target>Trajno izbriši ili prepiši datoteke</target> + +<source>Use Recycle Bin when deleting or overwriting files</source> +<target>Koristi Koš za smeće pri brisanju ili prepisivanju datoteka</target> + +<source>Versioning</source> +<target>Verzija</target> + +<source>Move files into a time-stamped subdirectory</source> +<target>Premjesti datoteke u vremenski-označen podfolder</target> + +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x min</pluralform> +<pluralform>%x min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x sat</pluralform> +<pluralform>%x sata</pluralform> +<pluralform>%x sati</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x dan</pluralform> +<pluralform>%x dana</pluralform> +<pluralform>%x dana</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Ne mogu započeti nadziranje direktorija:</target> + +<source>Error when monitoring directories.</source> +<target>Greška pri nadziranju direktorija.</target> + +<source>Conversion error:</source> +<target>Greška pri pretvorbi:</target> + +<source>Error deleting file:</source> +<target>Greška pri brisanju datoteke:</target> + +<source>Error moving file:</source> +<target>Greška pri premještanju datoteke:</target> + +<source>Target file already existing!</source> +<target>Ciljna datoteka već postoji!</target> + +<source>Error moving directory:</source> +<target>Greška pri premještanju direktorija:</target> + +<source>Target directory already existing!</source> +<target>Ciljni direktorij već postoji!</target> + +<source>Error deleting directory:</source> +<target>Greška pri brisanju direktorija:</target> + +<source>Error changing modification time:</source> +<target>Greška pri promjeni vremena izmjene:</target> + +<source>Error loading library function:</source> +<target>Greška pri zadavanju funkcije iz knjižnice:</target> + +<source>Error reading security context:</source> +<target>Greška pri čitanju zaštićenog sadržaja:</target> + +<source>Error writing security context:</source> +<target>Greška pri pisanju zaštićenog sadržaja:</target> + +<source>Error copying file permissions:</source> +<target>Greška pri kopiranju datotečnih dopuštenja:</target> + +<source>Error creating directory:</source> +<target>Greška pri izradi direktorija:</target> + +<source>Error copying symbolic link:</source> +<target>Greška pri kopiranju poveznice simbola:</target> + +<source>Error copying file:</source> +<target>Greška pri kopiranju datoteke:</target> + +<source>Error opening file:</source> +<target>Greška pri otvaranju datoteke:</target> + +<source>Error traversing directory:</source> +<target>Greška pri prelasku direktorija:</target> + +<source>Endless loop when traversing directory:</source> +<target>Beskonačna petlja pri prelasku direktorija:</target> + +<source>Error setting privilege:</source> +<target>Greška pri postavljanju dopuštenja:</target> + +<source>Both sides have changed since last synchronization!</source> +<target>Obje su strane promjenjene od posljednje sinkronizacije!</target> + +<source>Cannot determine sync-direction:</source> +<target>Ne mogu odrediti smijer sinkronizacije.</target> + +<source>No change since last synchronization!</source> +<target>Nema promjena od zadnje sinkronizacije!</target> + +<source>Filter settings have changed!</source> +<target>Filterske postavke su promjenjene!</target> + +<source>The file was not processed by last synchronization!</source> +<target>Datoteka nije procesirana tokom prošle sinkronizacije !</target> + +<source>Setting default synchronization directions: Old files will be overwritten with newer files.</source> +<target>Postavljam zadani sinkronizacijski smijer: Stare datoteke će biti prepisane novim datotekama.</target> + +<source>The file does not contain a valid configuration:</source> +<target>Datoteka ne sadrži ispravne postavke:</target> + +<source>You can ignore this error to consider the directory as empty.</source> +<target>Možete ignorirati ovu grešku uzimajući datoteku kao praznu .</target> + +<source>Directory does not exist:</source> +<target>Direktorij ne postoji:</target> + +<source>Directories are dependent! Be careful when setting up synchronization rules:</source> +<target>Direktoriji su u ovisnosti! Budite oprezni pri postavljanju sinkronizacijskih pravila:</target> + +<source>Memory allocation failed!</source> +<target>Neuspješno dodjeljivanje memorije!</target> + +<source>File %x has an invalid date!</source> +<target>Datoteka %x ima nevaljan datum!</target> + +<source>Conflict detected:</source> +<target>Sukob pronađen:</target> + +<source>Files %x have the same date but a different size!</source> +<target>Datoteke %x imaju isti datum ali drugačiju veličinu!</target> + +<source>Symlinks %x have the same date but a different target!</source> +<target>Simbolične poveznice %x imaju isti datum ali drugačiji cilj!</target> + +<source>Comparing content of files %x</source> +<target>Uspoređujem sadržaj datoteka %x</target> + +<source>Comparing files by content failed.</source> +<target>Usporedba datoteka prema sadržaju nije uspjela.</target> + +<source>Generating file list...</source> +<target>Generiram listu datoteka...</target> + +<source>Both sides are equal</source> +<target>Obje strane su jednake</target> + +<source>Files/folders differ in attributes only</source> +<target>Datoteke/mape se razlikuju samo u atributima</target> + +<source>Copy new file/folder to left</source> +<target>Kopiraj novu datoteku/mapu na lijevo</target> + +<source>Copy new file/folder to right</source> +<target>Kopiraj novu datoteku/mapu na desno</target> + +<source>Delete left file/folder</source> +<target>Izbriši lijevu datoteku/mapu</target> + +<source>Delete right file/folder</source> +<target>Izbriši desnu datoteku/mapu</target> + +<source>Move file on left</source> +<target>Premjesti datoteku lijevo</target> + +<source>Move file on right</source> +<target>Premjest datoteku desno</target> + +<source>Overwrite left file/folder with right one</source> +<target>Prepiši lijevu datoteku/mapu s onom sa desne strane</target> + +<source>Overwrite right file/folder with left one</source> +<target>Prepiši desnu datoteku/mapu s onom sa lijeve strane</target> + +<source>Do nothing</source> +<target>Ne radi ništa</target> + +<source>Copy file attributes only to left</source> +<target>Kopiraj atribute datoteke samo na levo</target> + +<source>Copy file attributes only to right</source> +<target>Kopiraj atribute datoteke samo na desno</target> + +<source>Multiple...</source> +<target>Mnogostruko...</target> + +<source>Deleting file %x</source> +<target>Brisanje datoteke %x</target> + +<source>Deleting folder %x</source> +<target>Brisanje mape %x</target> + +<source>Deleting symbolic link %x</source> +<target>Brisanje simboličnih poveznica %x</target> + +<source>Moving file %x to recycle bin</source> +<target>Premještam datoteku %x u Koš za smeće</target> + +<source>Moving folder %x to recycle bin</source> +<target>Premještam mapu %x u Koš za smeće</target> + +<source>Moving symbolic link %x to recycle bin</source> +<target>Premještam simboličnu poveznicu %x u Koš za smeće</target> + +<source>Moving file %x to %y</source> +<target>Premještam datoteku %x u %y</target> + +<source>Moving folder %x to %y</source> +<target>Premještam mapu %x u %y</target> + +<source>Moving symbolic link %x to %y</source> +<target>Premještam simboličnu poveznicu %x u %y</target> + +<source>Creating file %x</source> +<target>Izrađujem datoteku %x</target> + +<source>Creating symbolic link %x</source> +<target>Izrađujem simboličnu poveznicu %x</target> + +<source>Creating folder %x</source> +<target>Izrađujem mapu %x</target> + +<source>Overwriting file %x</source> +<target>Prepisujem datoteku %x</target> + +<source>Overwriting symbolic link %x</source> +<target>Prepisujem simboličnu poveznicu %x</target> + +<source>Verifying file %x</source> +<target>Provjeravam datoteku %x</target> + +<source>Updating attributes of %x</source> +<target>Obnavljam atribute od %x</target> + +<source>Target directory name must not be empty!</source> +<target>Ime ciljnog direktorija ne smije biti prazno!</target> + +<source>User-defined directory for deletion was not specified!</source> +<target>Korisnički definiran direktorij za brisanje nije definiran!</target> + +<source>Source directory does not exist anymore:</source> +<target>Izvorni direktorij više ne postoji:</target> + +<source>Unresolved conflicts existing!</source> +<target>Nerješivi sukob postoji!</target> + +<source>You can ignore conflicts and continue synchronization.</source> +<target>Možete ignorirati sukob i nastaviti s sinkronizacijom.</target> + +<source>Significant difference detected:</source> +<target>Značajna razlika opažena:</target> + +<source>More than 50% of the total number of files will be copied or deleted!</source> +<target>Više od 50% od ukupnog broja datoteka će biti kopirano ili izbrisano!</target> + +<source>Not enough free disk space available in:</source> +<target>Nedovoljno prostora na disku:</target> + +<source>Free disk space required:</source> +<target>Potreban prostor na disku:</target> + +<source>Free disk space available:</source> +<target>Prostor na disku dostupan:</target> + +<source>Recycle Bin is not available for the following paths! Files will be deleted permanently instead:</source> +<target>Koš za smeće nije dostupan za navedene putanje! Umjesto toga datoteke će biti trajno izbrisane:</target> + +<source>A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!</source> +<target>Direktorij će biti mjenjan koji je dio više parova mapa! Molimo pogledajte postavke sinkronizacije!</target> + +<source>Processing folder pair:</source> +<target>Obrađujem parove mapa:</target> + +<source>Generating database...</source> +<target>Izrađujem bazu podataka...</target> + +<source>Nothing to synchronize according to configuration!</source> +<target>Po trenutnim postavkama nema ništa za sinkroniziranje!</target> + +<source>Error copying locked file %x!</source> +<target>Greška pri kopiranju zaključane datoteke %x!</target> + +<source>Data verification error: Source and target file have different content!</source> +<target>Greška pri provjeravanju podataka: Izvorna i ciljna datoteka imaju različit sadržaj!</target> + diff --git a/BUILD/Languages/czech.lng b/BUILD/Languages/czech.lng index d3dd805e..fb72c119 100644 --- a/BUILD/Languages/czech.lng +++ b/BUILD/Languages/czech.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Automatická synchronizace</target> -<source>Browse</source> -<target>Procházet</target> - -<source>Windows Error Code %x:</source> -<target>Chybový kód Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Chybový kód Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Neplatný příkaz: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Chyba odkazu zástupce:</target> - -<source>Show pop-up</source> -<target>Zobrazit okno</target> - -<source>Show pop-up on errors or warnings</source> -<target>Zobrazit hlášení při chybě nebo varování</target> - -<source>Ignore errors</source> -<target>Přeskočit chyby</target> - -<source>Hide all error and warning messages</source> -<target>Skrýt všechny chyby a varování</target> - -<source>Exit instantly</source> -<target>Ukončit ihned</target> - -<source>Abort synchronization immediately</source> -<target>Přerušit synchronizaci ihned</target> - <source>Select alternate comparison settings</source> <target>Změnit nastavení porovnání</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Časové rozmezí</target> +<source>Show pop-up</source> +<target>Zobrazit okno</target> + +<source>Show pop-up on errors or warnings</source> +<target>Zobrazit hlášení při chybě nebo varování</target> + +<source>Ignore errors</source> +<target>Přeskočit chyby</target> + +<source>Hide all error and warning messages</source> +<target>Skrýt všechny chyby a varování</target> + +<source>Exit instantly</source> +<target>Ukončit ihned</target> + +<source>Abort synchronization immediately</source> +<target>Přerušit synchronizaci ihned</target> + +<source>Browse</source> +<target>Procházet</target> + +<source>Error reading from synchronization database:</source> +<target>Chyba čtení synchronizační databáze:</target> + +<source>Error writing to synchronization database:</source> +<target>Chyba zápisu synchronizační databáze:</target> + +<source>Invalid command line: %x</source> +<target>Neplatný příkaz: %x</target> + +<source>Windows Error Code %x:</source> +<target>Chybový kód Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Chybový kód Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Chyba odkazu zástupce:</target> + <source>%x MB</source> <target>%x MB</target> @@ -164,17 +170,14 @@ <source>Comparison Result</source> <target>Výsledek porovnání</target> -<source>Incompatible synchronization database format:</source> -<target>Chyba formátu synchronizační databáze:</target> - <source>Initial synchronization:</source> <target>Prvotní synchronizace:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Některý z databázových souborů FreeFileSync neexistuje:</target> -<source>Error reading from synchronization database:</source> -<target>Chyba čtení synchronizační databáze:</target> +<source>Incompatible synchronization database format:</source> +<target>Chyba formátu synchronizační databáze:</target> <source>Database files do not share a common synchronization session:</source> <target>Databázové soubory nejsou navzájem komplementární</target> @@ -201,12 +204,18 @@ <pluralform>%x sekund</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && Drop</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Závažná chyba</target> +<source>Error reading file:</source> +<target>Chyba čtení souboru:</target> + <source>Scanning:</source> <target>Zpracováváno:</target> @@ -226,15 +235,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Chybný konfigurační soubor FreeFileSync!</target> -<source>File does not exist:</source> -<target>Soubor neexistuje:</target> - <source>Error parsing configuration file:</source> <target>Chyba zpracování konfigurace:</target> +<source>Error moving to Recycle Bin:</source> +<target>Chyba přesunu do Koše:</target> + +<source>Could not load a required DLL:</source> +<target>Nelze načíst požadovanou knihovnu DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Chyba přístupu ke službě Volume Shadow Copy Service!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Vytváření stínových kopií na WOW64 není podporováno. Prosím použijte 64 bitovou verzi FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Není možné zjistit jméno jednotky souboru:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Disk %x není součástí jména souboru %y!</target> + <source>/sec</source> <target>/s</target> +<source>File does not exist:</source> +<target>Soubor neexistuje:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Nelze načíst hodnoty následujících XML elementy:</target> + <source>S&ave configuration...</source> <target>&Uložení konfigurace...</target> @@ -327,144 +357,6 @@ Příkazová řádka je spuštěna pokaždé když: <source>A directory input field is empty.</source> <target>Není zadán vstupní adresář.</target> -<source>Drag && drop</source> -<target>Drag && Drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Nelze nastavit monitorování adresáře:</target> - -<source>Error when monitoring directories.</source> -<target>Chyba při sledování adresářů.</target> - -<source>Conversion error:</source> -<target>Chyba konverze:</target> - -<source>Error deleting file:</source> -<target>Chyba mazání souboru:</target> - -<source>Error moving file:</source> -<target>Chyba přesouvání souboru:</target> - -<source>Target file already existing!</source> -<target>Cílový soubor již existuje!</target> - -<source>Error moving directory:</source> -<target>Chyba přesouvání adresáře:</target> - -<source>Target directory already existing!</source> -<target>Cílový adresář již existuje!</target> - -<source>Error deleting directory:</source> -<target>Chyba mazání adresáře:</target> - -<source>Error changing modification time:</source> -<target>Chyba nastavení času změny:</target> - -<source>Error loading library function:</source> -<target>Chyba načtení knihovny funkcí:</target> - -<source>Error reading security context:</source> -<target>Chyba při čtení přístupových práv:</target> - -<source>Error writing security context:</source> -<target>Chyba při zápisu přístupových práv:</target> - -<source>Error copying file permissions:</source> -<target>Chyba kopírování oprávnění souborů:</target> - -<source>Error creating directory:</source> -<target>Chyba vytvoření adresáře:</target> - -<source>Error copying symbolic link:</source> -<target>Chyba kopírování zástupce:</target> - -<source>Error copying file:</source> -<target>Chyba kopírování souboru:</target> - -<source>Error opening file:</source> -<target>Chyba otevření souboru:</target> - -<source>Error writing file:</source> -<target>Chyba zápisu souboru:</target> - -<source>Error reading file:</source> -<target>Chyba čtení souboru:</target> - -<source>Operation aborted!</source> -<target>Operace zrušena!</target> - -<source>Endless loop when traversing directory:</source> -<target>Zacyklení při procházení adresáře:</target> - -<source>Error traversing directory:</source> -<target>Chyba procházení adresáře:</target> - -<source>Error setting privilege:</source> -<target>Chyba nastavení práv:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Chyba přesunu do Koše:</target> - -<source>Could not load a required DLL:</source> -<target>Nelze načíst požadovanou knihovnu DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Chyba zápisu synchronizační databáze:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Chyba přístupu ke službě Volume Shadow Copy Service!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Vytváření stínových kopií na WOW64 není podporováno. Prosím použijte 64 bitovou verzi FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Není možné zjistit jméno jednotky souboru:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Disk %x není součástí jména souboru %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 minuta</pluralform> -<pluralform>%x minuty</pluralform> -<pluralform>%x minut</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 hodina</pluralform> -<pluralform>%x hodiny</pluralform> -<pluralform>%x hodin</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 den</pluralform> -<pluralform>%x dny</pluralform> -<pluralform>%x dnů</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Nelze načíst hodnoty následujících XML elementy:</target> - <source>Logging</source> <target>Zaznamenávání</target> @@ -483,9 +375,6 @@ Příkazová řádka je spuštěna pokaždé když: <source>Batch execution</source> <target>Spuštění dávky</target> -<source>Log-messages:</source> -<target>Záznamy:</target> - <source>Stop</source> <target>Stop</target> @@ -612,6 +501,24 @@ Příkazová řádka je spuštěna pokaždé když: <source>Total amount of data that will be transferred</source> <target>Celkový objem dat, který bude přenesen</target> +<source>Operation:</source> +<target>Operace:</target> + +<source>Items found:</source> +<target>Nalezeno položek:</target> + +<source>Items remaining:</source> +<target>Zbývá položek:</target> + +<source>Speed:</source> +<target>Rychlost:</target> + +<source>Time remaining:</source> +<target>Zbývající čas:</target> + +<source>Time elapsed:</source> +<target>Uplynulý čas:</target> + <source>Batch job</source> <target>Dávkový soubor</target> @@ -660,32 +567,14 @@ Příkazová řádka je spuštěna pokaždé když: <source>&Cancel</source> <target>&Zrušit</target> -<source>Operation:</source> -<target>Operace:</target> - -<source>Items found:</source> -<target>Nalezeno položek:</target> - -<source>Items remaining:</source> -<target>Zbývá položek:</target> - -<source>Speed:</source> -<target>Rychlost:</target> - -<source>Time remaining:</source> -<target>Zbývající čas:</target> - -<source>Time elapsed:</source> -<target>Uplynulý čas:</target> - <source>Select variant:</source> <target>Vyberte variantu:</target> <source><Automatic></source> <target><- Automaticky -></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Rozpoznat a provést změny na obou stranách pomocí databáze. Odstraněné soubory a konflikty budou detekovány automaticky.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Rozpoznat a provést změny na obou stranách pomocí databáze. Odstraněné nebo přejmenované soubory a konflikty budou detekovány automaticky.</target> <source>Mirror ->></source> <target>Zrcadlení ->></target> @@ -907,27 +796,19 @@ Vynechat: \někde\něco\* <target>Bezpečné kopírování souborů</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Kopíruje data nejprve do pomocného souboru (*.ffs_tmp) a poté teprve soubor přejmenuje. Tento postup zajišťuje bezpečné chování i v případě chyby během přenosu</target> <source>Copy locked files</source> <target>Kopírovat zamčené soubory</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopírovat sdílené nebo zamčené soubory pomocí Volume Shadow Copy Service (Vyžaduje administrátorské oprávnění) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopírovat sdílené nebo zamčené soubory pomocí Volume Shadow Copy Service (Vyžaduje administrátorské oprávnění)</target> <source>Copy file access permissions</source> <target>Kopírovat přístupová oprávnění k souborům</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administrátorké oprávnění) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administrátorké oprávnění)</target> <source>Hidden dialogs:</source> <target>Skryté dialogy:</target> @@ -959,6 +840,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>&Find next</source> <target>&Najít další</target> +<source>Operation aborted!</source> +<target>Operace zrušena!</target> + <source>Main bar</source> <target>Hlavní lišta</target> @@ -999,16 +883,16 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <target>Automaticky přizpůsobit šířku</target> <source>Icon size:</source> -<target></target> +<target>Velikost ikon:</target> <source>Small</source> -<target></target> +<target>Malé</target> <source>Medium</source> -<target></target> +<target>Střední</target> <source>Large</source> -<target></target> +<target>Velké</target> <source>Include all rows</source> <target>Použít všechny řádky</target> @@ -1136,6 +1020,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>File list exported!</source> <target>Seznam souborů exportován!</target> +<source>Error writing file:</source> +<target>Chyba zápisu souboru:</target> + <source>Batch file created successfully!</source> <target>Dávka úspěšně vytvořena!</target> @@ -1239,9 +1126,6 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Filter: Single pair</source> <target>Filtr: Jeden pár</target> -<source>Ignore</source> -<target>Přeskočit</target> - <source>Direct</source> <target>Zachovat</target> @@ -1307,6 +1191,108 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Move files into a time-stamped subdirectory</source> <target>Přesunout soubory do časově označeného podadresáře</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 minuta</pluralform> +<pluralform>%x minuty</pluralform> +<pluralform>%x minut</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 hodina</pluralform> +<pluralform>%x hodiny</pluralform> +<pluralform>%x hodin</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 den</pluralform> +<pluralform>%x dny</pluralform> +<pluralform>%x dnů</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Nelze nastavit monitorování adresáře:</target> + +<source>Error when monitoring directories.</source> +<target>Chyba při sledování adresářů.</target> + +<source>Conversion error:</source> +<target>Chyba konverze:</target> + +<source>Error deleting file:</source> +<target>Chyba mazání souboru:</target> + +<source>Error moving file:</source> +<target>Chyba přesouvání souboru:</target> + +<source>Target file already existing!</source> +<target>Cílový soubor již existuje!</target> + +<source>Error moving directory:</source> +<target>Chyba přesouvání adresáře:</target> + +<source>Target directory already existing!</source> +<target>Cílový adresář již existuje!</target> + +<source>Error deleting directory:</source> +<target>Chyba mazání adresáře:</target> + +<source>Error changing modification time:</source> +<target>Chyba nastavení času změny:</target> + +<source>Error loading library function:</source> +<target>Chyba načtení knihovny funkcí:</target> + +<source>Error reading security context:</source> +<target>Chyba při čtení přístupových práv:</target> + +<source>Error writing security context:</source> +<target>Chyba při zápisu přístupových práv:</target> + +<source>Error copying file permissions:</source> +<target>Chyba kopírování oprávnění souborů:</target> + +<source>Error creating directory:</source> +<target>Chyba vytvoření adresáře:</target> + +<source>Error copying symbolic link:</source> +<target>Chyba kopírování zástupce:</target> + +<source>Error copying file:</source> +<target>Chyba kopírování souboru:</target> + +<source>Error opening file:</source> +<target>Chyba otevření souboru:</target> + +<source>Error traversing directory:</source> +<target>Chyba procházení adresáře:</target> + +<source>Endless loop when traversing directory:</source> +<target>Zacyklení při procházení adresáře:</target> + +<source>Error setting privilege:</source> +<target>Chyba nastavení práv:</target> + <source>Both sides have changed since last synchronization!</source> <target>Došlo ke změně obou stran od poslední synchronizace!</target> @@ -1337,9 +1323,6 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Adresáře jsou závislé! Buďte opatrní s definicí synchronizačních pravidel:</target> -<source>Comparing content of files %x</source> -<target>Porovnávání obsahu souborů %x</target> - <source>Memory allocation failed!</source> <target>Chyba přidělení paměti!</target> @@ -1355,15 +1338,15 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Symlinks %x have the same date but a different target!</source> <target>Symbolický odkaz %x má stejné datum ale jiný cíl!</target> +<source>Comparing content of files %x</source> +<target>Porovnávání obsahu souborů %x</target> + <source>Comparing files by content failed.</source> <target>Porovnání obsahu souborů se nezdařilo.</target> <source>Generating file list...</source> <target>Vytváření seznamu souborů...</target> -<source>Multiple...</source> -<target>Různé...</target> - <source>Both sides are equal</source> <target>Obě strany jsou shodné</target> @@ -1382,6 +1365,12 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Delete right file/folder</source> <target>Smazat soubor/adresáře z prava</target> +<source>Move file on left</source> +<target>Přesunout soubor nalevo</target> + +<source>Move file on right</source> +<target>Přesunout soubor napravo</target> + <source>Overwrite left file/folder with right one</source> <target>Přepsat levý soubor/adresář tím z prava</target> @@ -1397,6 +1386,9 @@ Přenést přístupová oprávnění souborů a adresářů (Vyžaduje administr <source>Copy file attributes only to right</source> <target>Kopírovat vlastnosti souboru pouze do prava</target> +<source>Multiple...</source> +<target>Různé...</target> + <source>Deleting file %x</source> <target>Mazání souboru %x</target> diff --git a/BUILD/Languages/danish.lng b/BUILD/Languages/danish.lng index d13de994..cc3d8536 100644 --- a/BUILD/Languages/danish.lng +++ b/BUILD/Languages/danish.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSynk - Automatisk Synkronisering</target> -<source>Browse</source> -<target>Gennemse</target> - -<source>Windows Error Code %x:</source> -<target>Windows Fejl kode %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux Fejl kode %x:</target> - -<source>Invalid command line: %x</source> -<target>Ugyldig kommando: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Fejl i at finde link:</target> - -<source>Show pop-up</source> -<target>Vis pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Vis pop-up ved fejl eller advarsler</target> - -<source>Ignore errors</source> -<target>Ignorer fejl</target> - -<source>Hide all error and warning messages</source> -<target>Skjul beskeder om fejl og advarsler</target> - -<source>Exit instantly</source> -<target>Afslut med det samme</target> - -<source>Abort synchronization immediately</source> -<target>Abort synkronisering med det samme</target> - <source>Select alternate comparison settings</source> <target>Vælg alternative sammenlignings indstillinger</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Vælg tids område</target> +<source>Show pop-up</source> +<target>Vis pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Vis pop-up ved fejl eller advarsler</target> + +<source>Ignore errors</source> +<target>Ignorer fejl</target> + +<source>Hide all error and warning messages</source> +<target>Skjul beskeder om fejl og advarsler</target> + +<source>Exit instantly</source> +<target>Afslut med det samme</target> + +<source>Abort synchronization immediately</source> +<target>Abort synkronisering med det samme</target> + +<source>Browse</source> +<target>Gennemse</target> + +<source>Error reading from synchronization database:</source> +<target>Fejl i læsning fra synkroniserings databasen:</target> + +<source>Error writing to synchronization database:</source> +<target>Fejl i skrivning til synkroniserings databasen:</target> + +<source>Invalid command line: %x</source> +<target>Ugyldig kommando: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows Fejl kode %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux Fejl kode %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Fejl i at finde link:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Sammenlignings Resultat</target> -<source>Incompatible synchronization database format:</source> -<target>Ukompatibelt synkroniserings database format:</target> - <source>Initial synchronization:</source> <target>Indledende synkronisering:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>En af FreeFileSync database filerne findes ikke endnu:</target> -<source>Error reading from synchronization database:</source> -<target>Fejl i læsning fra synkroniserings databasen:</target> +<source>Incompatible synchronization database format:</source> +<target>Ukompatibelt synkroniserings database format:</target> <source>Database files do not share a common synchronization session:</source> <target>Database filer deler ikke en fælles synkroniserings session</target> @@ -199,12 +202,18 @@ <pluralform>%x sek</pluralform> </target> +<source>Drag && drop</source> +<target>Træk && slip</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Uoprettelig Fejl</target> +<source>Error reading file:</source> +<target>Fejl i læsning af fil:</target> + <source>Scanning:</source> <target>Skanner:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Ugyldig FreeFileSync config fil!</target> -<source>File does not exist:</source> -<target>Filen findes ikke:</target> - <source>Error parsing configuration file:</source> <target>Fejl i at lave konfigurations filen:</target> +<source>Error moving to Recycle Bin:</source> +<target>Fejl i at flytte til skraldespand:</target> + +<source>Could not load a required DLL:</source> +<target>Kunne ikke hente en krævet DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Fejl i adgang til Enhedens Kopi Service</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>At lave spejl kopier af WOW64 er ikke understøttet. Brug venligst FreeFileSync 64-bit version.</target> + +<source>Could not determine volume name for file:</source> +<target>Kunne ikke finde drev navn til filen:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Drev navn %x ikke en del af filnavn %y!</target> + <source>/sec</source> <target>/sek</target> +<source>File does not exist:</source> +<target>Filen findes ikke:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Kunne ikke læse værdierne for følgende XML punkter:</target> + <source>S&ave configuration...</source> <target>G&em konfiguration...</target> @@ -324,141 +354,6 @@ Kommando linjen bliver afviklet hver gang: <source>A directory input field is empty.</source> <target>Et biblioteks felt er tomt.</target> -<source>Drag && drop</source> -<target>Træk && slip</target> - -<source>Could not initialize directory monitoring:</source> -<target>Kunne ikke initialiserer biblioteks overvågningen:</target> - -<source>Error when monitoring directories.</source> -<target>Fejl i overvågning af biblioteker.</target> - -<source>Conversion error:</source> -<target>Konverterings fejl:</target> - -<source>Error deleting file:</source> -<target>Fejl i sletning af fil:</target> - -<source>Error moving file:</source> -<target>Fejl i flytning af fil:</target> - -<source>Target file already existing!</source> -<target>Filen findes i forvejen!</target> - -<source>Error moving directory:</source> -<target>Fejl i flytning af bibliotek:</target> - -<source>Target directory already existing!</source> -<target>Bibliotek findes i forvejen!</target> - -<source>Error deleting directory:</source> -<target>Fejl i sletning af bibliotek:</target> - -<source>Error changing modification time:</source> -<target>Fejl i ændring af modificerings tiden:</target> - -<source>Error loading library function:</source> -<target>Fejl i biblioteks funktionen:</target> - -<source>Error reading security context:</source> -<target>Fejl i læsning af sikkerhedstilladelser:</target> - -<source>Error writing security context:</source> -<target>Fejl i skrivning af sikkerhedstilladelser:</target> - -<source>Error copying file permissions:</source> -<target>Fejl i kopiering af filtilladelser:</target> - -<source>Error creating directory:</source> -<target>Fejl i oprettelse af bibliotek:</target> - -<source>Error copying symbolic link:</source> -<target>Fejl i kopiering af link:</target> - -<source>Error copying file:</source> -<target>Fejl i kopiering af fil:</target> - -<source>Error opening file:</source> -<target>Fejl i åbning af fil:</target> - -<source>Error writing file:</source> -<target>Fejl i at skrive fil:</target> - -<source>Error reading file:</source> -<target>Fejl i læsning af fil:</target> - -<source>Operation aborted!</source> -<target>Operation afbrudt!</target> - -<source>Endless loop when traversing directory:</source> -<target>Uendelig løkke ved gennemgang af bibliotek:</target> - -<source>Error traversing directory:</source> -<target>Fejl i gennemgang af bibliotek:</target> - -<source>Error setting privilege:</source> -<target>Fejl i at sætte privilegier:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Fejl i at flytte til skraldespand:</target> - -<source>Could not load a required DLL:</source> -<target>Kunne ikke hente en krævet DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Fejl i skrivning til synkroniserings databasen:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Fejl i adgang til Enhedens Kopi Service</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>At lave spejl kopier af WOW64 er ikke understøttet. Brug venligst FreeFileSync 64-bit version.</target> - -<source>Could not determine volume name for file:</source> -<target>Kunne ikke finde drev navn til filen:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Drev navn %x ikke en del af filnavn %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 timer</pluralform> -<pluralform>%x timer</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dag</pluralform> -<pluralform>%x dage</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Kunne ikke læse værdierne for følgende XML punkter:</target> - <source>Logging</source> <target>Logger</target> @@ -477,9 +372,6 @@ Kommando linjen bliver afviklet hver gang: <source>Batch execution</source> <target>Batch afvikling</target> -<source>Log-messages:</source> -<target>Log-beskeder:</target> - <source>Stop</source> <target>Stop</target> @@ -606,6 +498,24 @@ Kommando linjen bliver afviklet hver gang: <source>Total amount of data that will be transferred</source> <target>Samlet antal data der vil blive overført</target> +<source>Operation:</source> +<target>Igang:</target> + +<source>Items found:</source> +<target>Enheder fundet:</target> + +<source>Items remaining:</source> +<target>Enheder tilbage:</target> + +<source>Speed:</source> +<target>Hastighed:</target> + +<source>Time remaining:</source> +<target>Tid tilbage:</target> + +<source>Time elapsed:</source> +<target>Tid gået:</target> + <source>Batch job</source> <target>Batch job</target> @@ -654,32 +564,14 @@ Kommando linjen bliver afviklet hver gang: <source>&Cancel</source> <target>&Anuller</target> -<source>Operation:</source> -<target>Igang:</target> - -<source>Items found:</source> -<target>Enheder fundet:</target> - -<source>Items remaining:</source> -<target>Enheder tilbage:</target> - -<source>Speed:</source> -<target>Hastighed:</target> - -<source>Time remaining:</source> -<target>Tid tilbage:</target> - -<source>Time elapsed:</source> -<target>Tid gået:</target> - <source>Select variant:</source> <target>Vælg variant:</target> <source><Automatic></source> <target><Automatisk></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Indentifiser og udbred ændringer på begge sider via. database. Sletninger og konflikter opdages automatisk.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>find ændringer på begge sider via. database. Sletninger, omdøbninger og konflikter bliver automatisk fundet.</target> <source>Mirror ->></source> <target>Spejl ->></target> @@ -901,27 +793,19 @@ Udeluk: \ting\temp\* <target>Transaktionel fil kopiering</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Skriv til en midlertidig fil (*.ffs_tmp) først så omdøb den. Dette garanterer sikkerheden selv ved en kritisk fejl.</target> <source>Copy locked files</source> <target>Kopier låste filer</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopier delte eller låste filer ved hjælp af Drev Kopi Servicen (Kræver Administrator rettigheder) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopier delte eller låste filer ved hjælp af Drev Kopi Servicen (Kræver Administrator rettigheder)</target> <source>Copy file access permissions</source> <target>Kopier fil adgangs tilladelser</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder)</target> <source>Hidden dialogs:</source> <target>Skjulte dialoger:</target> @@ -953,6 +837,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>&Find next</source> <target>&Find næste</target> +<source>Operation aborted!</source> +<target>Operation afbrudt!</target> + <source>Main bar</source> <target>Hoved værktøjslinjen</target> @@ -993,16 +880,16 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <target>Auto-juster kolonner</target> <source>Icon size:</source> -<target></target> +<target>Ikon størrelse:</target> <source>Small</source> -<target></target> +<target>Lille</target> <source>Medium</source> -<target></target> +<target>Mellem</target> <source>Large</source> -<target></target> +<target>Stor</target> <source>Include all rows</source> <target>Inkluder alle rækker</target> @@ -1130,6 +1017,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>File list exported!</source> <target>Fil listen er eksporteret!</target> +<source>Error writing file:</source> +<target>Fejl i at skrive fil:</target> + <source>Batch file created successfully!</source> <target>Batch fil oprettet!</target> @@ -1229,9 +1119,6 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Filter: Single pair</source> <target>Filter: Par</target> -<source>Ignore</source> -<target>Ignorer</target> - <source>Direct</source> <target>Direkte</target> @@ -1295,6 +1182,105 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Move files into a time-stamped subdirectory</source> <target>Flyt filer til et datomærket underbibliotek</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 timer</pluralform> +<pluralform>%x timer</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dag</pluralform> +<pluralform>%x dage</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Kunne ikke initialiserer biblioteks overvågningen:</target> + +<source>Error when monitoring directories.</source> +<target>Fejl i overvågning af biblioteker.</target> + +<source>Conversion error:</source> +<target>Konverterings fejl:</target> + +<source>Error deleting file:</source> +<target>Fejl i sletning af fil:</target> + +<source>Error moving file:</source> +<target>Fejl i flytning af fil:</target> + +<source>Target file already existing!</source> +<target>Filen findes i forvejen!</target> + +<source>Error moving directory:</source> +<target>Fejl i flytning af bibliotek:</target> + +<source>Target directory already existing!</source> +<target>Bibliotek findes i forvejen!</target> + +<source>Error deleting directory:</source> +<target>Fejl i sletning af bibliotek:</target> + +<source>Error changing modification time:</source> +<target>Fejl i ændring af modificerings tiden:</target> + +<source>Error loading library function:</source> +<target>Fejl i biblioteks funktionen:</target> + +<source>Error reading security context:</source> +<target>Fejl i læsning af sikkerhedstilladelser:</target> + +<source>Error writing security context:</source> +<target>Fejl i skrivning af sikkerhedstilladelser:</target> + +<source>Error copying file permissions:</source> +<target>Fejl i kopiering af filtilladelser:</target> + +<source>Error creating directory:</source> +<target>Fejl i oprettelse af bibliotek:</target> + +<source>Error copying symbolic link:</source> +<target>Fejl i kopiering af link:</target> + +<source>Error copying file:</source> +<target>Fejl i kopiering af fil:</target> + +<source>Error opening file:</source> +<target>Fejl i åbning af fil:</target> + +<source>Error traversing directory:</source> +<target>Fejl i gennemgang af bibliotek:</target> + +<source>Endless loop when traversing directory:</source> +<target>Uendelig løkke ved gennemgang af bibliotek:</target> + +<source>Error setting privilege:</source> +<target>Fejl i at sætte privilegier:</target> + <source>Both sides have changed since last synchronization!</source> <target>Begge sider er ændret siden sidste synkronisering!</target> @@ -1325,9 +1311,6 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Biblioteker er afhængige! Vær forsigtig når du laver synkroniserings reglerne:</target> -<source>Comparing content of files %x</source> -<target>Sammenligner indhold af filer %x</target> - <source>Memory allocation failed!</source> <target>Hukommelses fejl!</target> @@ -1343,15 +1326,15 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Symlinks %x have the same date but a different target!</source> <target>Links %x har den samme dato men forskellige destinationerl!</target> +<source>Comparing content of files %x</source> +<target>Sammenligner indhold af filer %x</target> + <source>Comparing files by content failed.</source> <target>Fejl i sammenligning af filernes indhold.</target> <source>Generating file list...</source> <target>Laver fil liste...</target> -<source>Multiple...</source> -<target>Flere...</target> - <source>Both sides are equal</source> <target>Begge sider er ens</target> @@ -1370,6 +1353,12 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Delete right file/folder</source> <target>Slet højre fil/mappe</target> +<source>Move file on left</source> +<target>Flyt filen til venstre</target> + +<source>Move file on right</source> +<target>flyt filen til højre</target> + <source>Overwrite left file/folder with right one</source> <target>Overskriv venstre fil/mappe med højre</target> @@ -1385,6 +1374,9 @@ Overfør fil og biblioteks tilladelser (Kræver Administrator rettigheder) <source>Copy file attributes only to right</source> <target>Kopiere fil attributter kun til højre</target> +<source>Multiple...</source> +<target>Flere...</target> + <source>Deleting file %x</source> <target>Sletter fil %x</target> diff --git a/BUILD/Languages/dutch.lng b/BUILD/Languages/dutch.lng index 17519715..8c9d8a33 100644 --- a/BUILD/Languages/dutch.lng +++ b/BUILD/Languages/dutch.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Geautomatiseerde Synchronisatie</target> -<source>Browse</source> -<target>Verkennen</target> - -<source>Windows Error Code %x:</source> -<target>Windows Fout Code %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux Fout Code %x:</target> - -<source>Invalid command line: %x</source> -<target></target> - -<source>Error resolving symbolic link:</source> -<target>Fout tijdens opzoeken van symbolische koppeling:</target> - -<source>Show pop-up</source> -<target></target> - -<source>Show pop-up on errors or warnings</source> -<target></target> - -<source>Ignore errors</source> -<target>Negeer foutmeldingen</target> - -<source>Hide all error and warning messages</source> -<target>Verberg alle fout- en waarschuwingsberichten</target> - -<source>Exit instantly</source> -<target>Sluit meteen af</target> - -<source>Abort synchronization immediately</source> -<target>Stop synchronisatie onmiddelijk</target> - <source>Select alternate comparison settings</source> <target></target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target></target> +<source>Show pop-up</source> +<target></target> + +<source>Show pop-up on errors or warnings</source> +<target></target> + +<source>Ignore errors</source> +<target>Negeer foutmeldingen</target> + +<source>Hide all error and warning messages</source> +<target>Verberg alle fout- en waarschuwingsberichten</target> + +<source>Exit instantly</source> +<target>Sluit meteen af</target> + +<source>Abort synchronization immediately</source> +<target>Stop synchronisatie onmiddelijk</target> + +<source>Browse</source> +<target>Verkennen</target> + +<source>Error reading from synchronization database:</source> +<target>Fout tijdens uitlezen van synchronisatie-database:</target> + +<source>Error writing to synchronization database:</source> +<target>Fout tijdens schrijven naar synchronisatie-database:</target> + +<source>Invalid command line: %x</source> +<target></target> + +<source>Windows Error Code %x:</source> +<target>Windows Fout Code %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux Fout Code %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Fout tijdens opzoeken van symbolische koppeling:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Resultaat vergelijken</target> -<source>Incompatible synchronization database format:</source> -<target>Opmaak van synchronisatie-database komt niet overeen:</target> - <source>Initial synchronization:</source> <target>Initiële synchronisatie:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Eén van de FreeFileSync database bestanden bestaat nog niet:</target> -<source>Error reading from synchronization database:</source> -<target>Fout tijdens uitlezen van synchronisatie-database:</target> +<source>Incompatible synchronization database format:</source> +<target>Opmaak van synchronisatie-database komt niet overeen:</target> <source>Database files do not share a common synchronization session:</source> <target></target> @@ -199,12 +202,18 @@ <pluralform>%x sec</pluralform> </target> +<source>Drag && drop</source> +<target>Drag en drop</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Fatale fout</target> +<source>Error reading file:</source> +<target>Fout tijdens lezen van bestand:</target> + <source>Scanning:</source> <target>Doorzoekt:</target> @@ -220,15 +229,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Foutief FreeFileSync configuratiebestand!</target> -<source>File does not exist:</source> -<target>Bestand bestaat niet:</target> - <source>Error parsing configuration file:</source> <target>Fout tijdens verwerking configuratiebestand:</target> +<source>Error moving to Recycle Bin:</source> +<target>Fout tijdens verplaatsen naar prullenbak:</target> + +<source>Could not load a required DLL:</source> +<target>Kon een benodigde DLL niet laden:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target></target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Het aanmaken van schaduwkopieën op WOW64 wordt niet ondersteund. Gebruik alstublieft de 64-bit versie van FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Kon de schijfnaam niet vaststellen van bestand:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Schijfnaam %x maakt geen deel uit van bestandsnaam %y!</target> + <source>/sec</source> <target>/sec</target> +<source>File does not exist:</source> +<target>Bestand bestaat niet:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Kon geen waarden inlezen voor de volgende XML punten:</target> + <source>S&ave configuration...</source> <target>Sl&a configuratie op...</target> @@ -321,141 +351,6 @@ De opdrachtregel wordt telkens uitgevoerd indien: <source>A directory input field is empty.</source> <target>Een tekstveld over de map is leeg.</target> -<source>Drag && drop</source> -<target>Drag en drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Initaliseren van map-observatie niet mogelijk:</target> - -<source>Error when monitoring directories.</source> -<target>Fout tijdens observeren van mappen.</target> - -<source>Conversion error:</source> -<target>Converteer fout:</target> - -<source>Error deleting file:</source> -<target>Fout tijdens verwijderen van bestand:</target> - -<source>Error moving file:</source> -<target>Fout tijdens verplaatsen van bestand:</target> - -<source>Target file already existing!</source> -<target>Doelbestand bestaat al!</target> - -<source>Error moving directory:</source> -<target>Fout tijdens verplaatsen van map:</target> - -<source>Target directory already existing!</source> -<target>Doelmap bestaat al!</target> - -<source>Error deleting directory:</source> -<target>Fout tijdens het verwijderen van map:</target> - -<source>Error changing modification time:</source> -<target>Fout tijdens aanpassing van de wijzigingstijd:</target> - -<source>Error loading library function:</source> -<target>Fout tijdens laden van bibliotheek functie:</target> - -<source>Error reading security context:</source> -<target>Fout tijdens lezen van beveiligingscontext:</target> - -<source>Error writing security context:</source> -<target>Fout tijdens schrijven van beveiligingscontext:</target> - -<source>Error copying file permissions:</source> -<target>Fout tijdens kopiëren van bestandspermissies:</target> - -<source>Error creating directory:</source> -<target>Fout tijdens het aanmaken van map:</target> - -<source>Error copying symbolic link:</source> -<target>Fout tijdens kopiëren van symbolische koppeling:</target> - -<source>Error copying file:</source> -<target>Fout tijdens kopiëren van bestand:</target> - -<source>Error opening file:</source> -<target>Fout tijdens openen van bestand:</target> - -<source>Error writing file:</source> -<target>Fout tijdens schrijven van bestand:</target> - -<source>Error reading file:</source> -<target>Fout tijdens lezen van bestand:</target> - -<source>Operation aborted!</source> -<target>Bewerking afgebroken!</target> - -<source>Endless loop when traversing directory:</source> -<target>Oneindige lus bij het doorlopen van map:</target> - -<source>Error traversing directory:</source> -<target>Fout tijdens doorzoeken van map:</target> - -<source>Error setting privilege:</source> -<target>Fout tijdens instellen van privileges:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Fout tijdens verplaatsen naar prullenbak:</target> - -<source>Could not load a required DLL:</source> -<target>Kon een benodigde DLL niet laden:</target> - -<source>Error writing to synchronization database:</source> -<target>Fout tijdens schrijven naar synchronisatie-database:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target></target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Het aanmaken van schaduwkopieën op WOW64 wordt niet ondersteund. Gebruik alstublieft de 64-bit versie van FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Kon de schijfnaam niet vaststellen van bestand:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Schijfnaam %x maakt geen deel uit van bestandsnaam %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 uur</pluralform> -<pluralform>%x uren</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dag</pluralform> -<pluralform>%x dagen</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Kon geen waarden inlezen voor de volgende XML punten:</target> - <source>Logging</source> <target>Loggen</target> @@ -474,9 +369,6 @@ De opdrachtregel wordt telkens uitgevoerd indien: <source>Batch execution</source> <target>Taak uitvoeren</target> -<source>Log-messages:</source> -<target>Logberichten:</target> - <source>Stop</source> <target>Stop</target> @@ -603,6 +495,24 @@ De opdrachtregel wordt telkens uitgevoerd indien: <source>Total amount of data that will be transferred</source> <target>Totale hoeveelheid data die verplaatst wordt</target> +<source>Operation:</source> +<target>Bewerking:</target> + +<source>Items found:</source> +<target>Onderdelen gevonden:</target> + +<source>Items remaining:</source> +<target>Onderdelen te gaan:</target> + +<source>Speed:</source> +<target>Snelheid:</target> + +<source>Time remaining:</source> +<target>Benodigde tijd:</target> + +<source>Time elapsed:</source> +<target>Verstreken tijd:</target> + <source>Batch job</source> <target>Taaklijst</target> @@ -651,32 +561,14 @@ De opdrachtregel wordt telkens uitgevoerd indien: <source>&Cancel</source> <target>&Annuleren</target> -<source>Operation:</source> -<target>Bewerking:</target> - -<source>Items found:</source> -<target>Onderdelen gevonden:</target> - -<source>Items remaining:</source> -<target>Onderdelen te gaan:</target> - -<source>Speed:</source> -<target>Snelheid:</target> - -<source>Time remaining:</source> -<target>Benodigde tijd:</target> - -<source>Time elapsed:</source> -<target>Verstreken tijd:</target> - <source>Select variant:</source> <target>Selecteer een variant:</target> <source><Automatic></source> <target><Automatisch></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identificeer en verwerk veranderingen aan beide zijdes dmv een database. Verwijderingen en conflicten worden automatisch gedetecteerd.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>Spiegelen ->></target> @@ -898,22 +790,14 @@ Uitsluiten: \stuff\temp\* <source>Copy locked files</source> <target>Kopieer vergrendelde bestanden</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopieer gedeelde of vergrendelde bestanden met Volume Shadow Copy Service (Vereist Administrator rechten) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopieer gedeelde of vergrendelde bestanden met Volume Shadow Copy Service (Vereist Administrator rechten)</target> <source>Copy file access permissions</source> <target></target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Zet bestand en map permissies over (Vereist Administrator rechten) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Zet bestand en map permissies over (Vereist Administrator rechten)</target> <source>Hidden dialogs:</source> <target>Verborgen dialogen:</target> @@ -945,6 +829,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>&Find next</source> <target>&Vind volgende</target> +<source>Operation aborted!</source> +<target>Bewerking afgebroken!</target> + <source>Main bar</source> <target>Hoofdbalk</target> @@ -1122,6 +1009,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>File list exported!</source> <target>Bestandslijst geëxporteerd!</target> +<source>Error writing file:</source> +<target>Fout tijdens schrijven van bestand:</target> + <source>Batch file created successfully!</source> <target>Taakbestand is succesvol aangemaakt!</target> @@ -1221,9 +1111,6 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Filter: Single pair</source> <target>Filter: Enkel paar</target> -<source>Ignore</source> -<target>Negeer</target> - <source>Direct</source> <target>Direct</target> @@ -1287,6 +1174,105 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Move files into a time-stamped subdirectory</source> <target>Verplaats de bestanden naar een tijd-gemarkeerde submap</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 uur</pluralform> +<pluralform>%x uren</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dag</pluralform> +<pluralform>%x dagen</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Initaliseren van map-observatie niet mogelijk:</target> + +<source>Error when monitoring directories.</source> +<target>Fout tijdens observeren van mappen.</target> + +<source>Conversion error:</source> +<target>Converteer fout:</target> + +<source>Error deleting file:</source> +<target>Fout tijdens verwijderen van bestand:</target> + +<source>Error moving file:</source> +<target>Fout tijdens verplaatsen van bestand:</target> + +<source>Target file already existing!</source> +<target>Doelbestand bestaat al!</target> + +<source>Error moving directory:</source> +<target>Fout tijdens verplaatsen van map:</target> + +<source>Target directory already existing!</source> +<target>Doelmap bestaat al!</target> + +<source>Error deleting directory:</source> +<target>Fout tijdens het verwijderen van map:</target> + +<source>Error changing modification time:</source> +<target>Fout tijdens aanpassing van de wijzigingstijd:</target> + +<source>Error loading library function:</source> +<target>Fout tijdens laden van bibliotheek functie:</target> + +<source>Error reading security context:</source> +<target>Fout tijdens lezen van beveiligingscontext:</target> + +<source>Error writing security context:</source> +<target>Fout tijdens schrijven van beveiligingscontext:</target> + +<source>Error copying file permissions:</source> +<target>Fout tijdens kopiëren van bestandspermissies:</target> + +<source>Error creating directory:</source> +<target>Fout tijdens het aanmaken van map:</target> + +<source>Error copying symbolic link:</source> +<target>Fout tijdens kopiëren van symbolische koppeling:</target> + +<source>Error copying file:</source> +<target>Fout tijdens kopiëren van bestand:</target> + +<source>Error opening file:</source> +<target>Fout tijdens openen van bestand:</target> + +<source>Error traversing directory:</source> +<target>Fout tijdens doorzoeken van map:</target> + +<source>Endless loop when traversing directory:</source> +<target>Oneindige lus bij het doorlopen van map:</target> + +<source>Error setting privilege:</source> +<target>Fout tijdens instellen van privileges:</target> + <source>Both sides have changed since last synchronization!</source> <target>Beide zijdes zijn veranderd sinds de laatste synchronisatie!</target> @@ -1317,9 +1303,6 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Mappen zijn afhankelijk van elkaar! Wees voorzichtig met het maken van synchronisatieregels:</target> -<source>Comparing content of files %x</source> -<target>De inhoud van %x bestanden wordt vergeleken</target> - <source>Memory allocation failed!</source> <target>RAM geheugen error!</target> @@ -1335,15 +1318,15 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Symlinks %x have the same date but a different target!</source> <target>Symbolische koppeling %x heeft dezelfde datum maar een ander doel!</target> +<source>Comparing content of files %x</source> +<target>De inhoud van %x bestanden wordt vergeleken</target> + <source>Comparing files by content failed.</source> <target>Bestand-inhoudvergelijking mislukt.</target> <source>Generating file list...</source> <target>Genereren van bestandslijst...</target> -<source>Multiple...</source> -<target>Meerdere...</target> - <source>Both sides are equal</source> <target>Beide kanten zijn gelijk</target> @@ -1362,6 +1345,12 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Delete right file/folder</source> <target>Verwijder rechter bestand/map</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>Overschrijf linker bestand/map met de rechter</target> @@ -1377,6 +1366,9 @@ Zet bestand en map permissies over (Vereist Administrator rechten) <source>Copy file attributes only to right</source> <target>Kopieer bestandsattributen allen naar rechts</target> +<source>Multiple...</source> +<target>Meerdere...</target> + <source>Deleting file %x</source> <target>Verwijderen van bestand %x</target> diff --git a/BUILD/Languages/english_uk.lng b/BUILD/Languages/english_uk.lng index a562a229..bea82597 100644 --- a/BUILD/Languages/english_uk.lng +++ b/BUILD/Languages/english_uk.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Automated Synchronisation</target> -<source>Browse</source> -<target>Browse</target> - -<source>Windows Error Code %x:</source> -<target>Windows Error Code %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux Error Code %x:</target> - -<source>Invalid command line: %x</source> -<target>Invalid command line: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Error resolving symbolic link:</target> - -<source>Show pop-up</source> -<target>Show pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Show pop-up on errors or warnings</target> - -<source>Ignore errors</source> -<target>Ignore errors</target> - -<source>Hide all error and warning messages</source> -<target>Hide all error and warning messages</target> - -<source>Exit instantly</source> -<target>Exit instantly</target> - -<source>Abort synchronization immediately</source> -<target>Abort synchronisation immediately</target> - <source>Select alternate comparison settings</source> <target>Select alternate comparison settings</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Select time span</target> +<source>Show pop-up</source> +<target>Show pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Show pop-up on errors or warnings</target> + +<source>Ignore errors</source> +<target>Ignore errors</target> + +<source>Hide all error and warning messages</source> +<target>Hide all error and warning messages</target> + +<source>Exit instantly</source> +<target>Exit instantly</target> + +<source>Abort synchronization immediately</source> +<target>Abort synchronisation immediately</target> + +<source>Browse</source> +<target>Browse</target> + +<source>Error reading from synchronization database:</source> +<target>Error reading from synchronisation database:</target> + +<source>Error writing to synchronization database:</source> +<target>Error writing to synchronisation database:</target> + +<source>Invalid command line: %x</source> +<target>Invalid command line: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows Error Code %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux Error Code %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Error resolving symbolic link:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Comparison Result</target> -<source>Incompatible synchronization database format:</source> -<target>Incompatible synchronisation database format:</target> - <source>Initial synchronization:</source> <target>Initial synchronisation:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>One of the FreeFileSync database files is not yet existing:</target> -<source>Error reading from synchronization database:</source> -<target>Error reading from synchronisation database:</target> +<source>Incompatible synchronization database format:</source> +<target>Incompatible synchronisation database format:</target> <source>Database files do not share a common synchronization session:</source> <target>Database files do not share a common synchronisation session:</target> @@ -199,12 +202,18 @@ <pluralform>%x sec</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && drop</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Fatal Error</target> +<source>Error reading file:</source> +<target>Error reading file:</target> + <source>Scanning:</source> <target>Scanning:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Invalid FreeFileSync config file!</target> -<source>File does not exist:</source> -<target>File does not exist:</target> - <source>Error parsing configuration file:</source> <target>Error parsing configuration file:</target> +<source>Error moving to Recycle Bin:</source> +<target>Error moving to Recycle Bin:</target> + +<source>Could not load a required DLL:</source> +<target>Could not load a required DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Error accessing Volume Shadow Copy Service!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</target> + +<source>Could not determine volume name for file:</source> +<target>Could not determine volume name for file:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Volume name %x not part of filename %y!</target> + <source>/sec</source> <target>/sec</target> +<source>File does not exist:</source> +<target>File does not exist:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Could not read values for the following XML nodes:</target> + <source>S&ave configuration...</source> <target>S&ave configuration...</target> @@ -324,141 +354,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>A directory input field is empty.</target> -<source>Drag && drop</source> -<target>Drag && drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Could not initialise directory monitoring:</target> - -<source>Error when monitoring directories.</source> -<target>Error when monitoring directories.</target> - -<source>Conversion error:</source> -<target>Conversion error:</target> - -<source>Error deleting file:</source> -<target>Error deleting file:</target> - -<source>Error moving file:</source> -<target>Error moving file:</target> - -<source>Target file already existing!</source> -<target>Target file already existing!</target> - -<source>Error moving directory:</source> -<target>Error moving directory:</target> - -<source>Target directory already existing!</source> -<target>Target directory already existing!</target> - -<source>Error deleting directory:</source> -<target>Error deleting directory:</target> - -<source>Error changing modification time:</source> -<target>Error changing modification time:</target> - -<source>Error loading library function:</source> -<target>Error loading library function:</target> - -<source>Error reading security context:</source> -<target>Error reading security context:</target> - -<source>Error writing security context:</source> -<target>Error writing security context:</target> - -<source>Error copying file permissions:</source> -<target>Error copying file permissions:</target> - -<source>Error creating directory:</source> -<target>Error creating directory:</target> - -<source>Error copying symbolic link:</source> -<target>Error copying symbolic link:</target> - -<source>Error copying file:</source> -<target>Error copying file:</target> - -<source>Error opening file:</source> -<target>Error opening file:</target> - -<source>Error writing file:</source> -<target>Error writing file:</target> - -<source>Error reading file:</source> -<target>Error reading file:</target> - -<source>Operation aborted!</source> -<target>Operation aborted!</target> - -<source>Endless loop when traversing directory:</source> -<target>Endless loop when traversing directory:</target> - -<source>Error traversing directory:</source> -<target>Error traversing directory:</target> - -<source>Error setting privilege:</source> -<target>Error setting privilege:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Error moving to Recycle Bin:</target> - -<source>Could not load a required DLL:</source> -<target>Could not load a required DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Error writing to synchronisation database:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Error accessing Volume Shadow Copy Service!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</target> - -<source>Could not determine volume name for file:</source> -<target>Could not determine volume name for file:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Volume name %x not part of filename %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Could not read values for the following XML nodes:</target> - <source>Logging</source> <target>Logging</target> @@ -477,9 +372,6 @@ The command line is executed each time: <source>Batch execution</source> <target>Batch execution</target> -<source>Log-messages:</source> -<target>Log-messages:</target> - <source>Stop</source> <target>Stop</target> @@ -606,6 +498,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>Total amount of data that will be transferred</target> +<source>Operation:</source> +<target>Operation:</target> + +<source>Items found:</source> +<target>Elements found:</target> + +<source>Items remaining:</source> +<target>Elements remaining:</target> + +<source>Speed:</source> +<target>Speed:</target> + +<source>Time remaining:</source> +<target>Time remaining:</target> + +<source>Time elapsed:</source> +<target>Time elapsed:</target> + <source>Batch job</source> <target>Batch job</target> @@ -654,32 +564,14 @@ The command line is executed each time: <source>&Cancel</source> <target>&Cancel</target> -<source>Operation:</source> -<target>Operation:</target> - -<source>Items found:</source> -<target>Elements found:</target> - -<source>Items remaining:</source> -<target>Elements remaining:</target> - -<source>Speed:</source> -<target>Speed:</target> - -<source>Time remaining:</source> -<target>Time remaining:</target> - -<source>Time elapsed:</source> -<target>Time elapsed:</target> - <source>Select variant:</source> <target>Select variant:</target> <source><Automatic></source> <target><Automatic></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</target> <source>Mirror ->></source> <target>Mirror ->></target> @@ -901,27 +793,19 @@ Exclude: \stuff\temp\* <target>Transactional file copy</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</target> <source>Copy locked files</source> <target>Copy locked files</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</target> <source>Copy file access permissions</source> <target>Copy file access permissions</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transfer file and directory permissions (Requires Administrator rights) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transfer file and directory permissions (Requires Administrator rights)</target> <source>Hidden dialogs:</source> <target>Hidden dialogues:</target> @@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>&Find next</target> +<source>Operation aborted!</source> +<target>Operation aborted!</target> + <source>Main bar</source> <target>Main bar</target> @@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights) <target>Auto-adjust columns</target> <source>Icon size:</source> -<target></target> +<target>Icon size:</target> <source>Small</source> -<target></target> +<target>Small</target> <source>Medium</source> -<target></target> +<target>Medium</target> <source>Large</source> -<target></target> +<target>Large</target> <source>Include all rows</source> <target>Include all rows</target> @@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>File list exported!</target> +<source>Error writing file:</source> +<target>Error writing file:</target> + <source>Batch file created successfully!</source> <target>Batch file created successfully!</target> @@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>Filter: Single pair</target> -<source>Ignore</source> -<target>Ignore</target> - <source>Direct</source> <target>Direct</target> @@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>Move files into a time-stamped subdirectory</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Could not initialise directory monitoring:</target> + +<source>Error when monitoring directories.</source> +<target>Error when monitoring directories.</target> + +<source>Conversion error:</source> +<target>Conversion error:</target> + +<source>Error deleting file:</source> +<target>Error deleting file:</target> + +<source>Error moving file:</source> +<target>Error moving file:</target> + +<source>Target file already existing!</source> +<target>Target file already existing!</target> + +<source>Error moving directory:</source> +<target>Error moving directory:</target> + +<source>Target directory already existing!</source> +<target>Target directory already existing!</target> + +<source>Error deleting directory:</source> +<target>Error deleting directory:</target> + +<source>Error changing modification time:</source> +<target>Error changing modification time:</target> + +<source>Error loading library function:</source> +<target>Error loading library function:</target> + +<source>Error reading security context:</source> +<target>Error reading security context:</target> + +<source>Error writing security context:</source> +<target>Error writing security context:</target> + +<source>Error copying file permissions:</source> +<target>Error copying file permissions:</target> + +<source>Error creating directory:</source> +<target>Error creating directory:</target> + +<source>Error copying symbolic link:</source> +<target>Error copying symbolic link:</target> + +<source>Error copying file:</source> +<target>Error copying file:</target> + +<source>Error opening file:</source> +<target>Error opening file:</target> + +<source>Error traversing directory:</source> +<target>Error traversing directory:</target> + +<source>Endless loop when traversing directory:</source> +<target>Endless loop when traversing directory:</target> + +<source>Error setting privilege:</source> +<target>Error setting privilege:</target> + <source>Both sides have changed since last synchronization!</source> <target>Both sides have changed since last synchronisation!</target> @@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Directories are dependent! Be careful when setting up synchronisation rules:</target> -<source>Comparing content of files %x</source> -<target>Comparing content of files %x</target> - <source>Memory allocation failed!</source> <target>Memory allocation failed!</target> @@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>Symlinks %x have the same date but a different target!</target> +<source>Comparing content of files %x</source> +<target>Comparing content of files %x</target> + <source>Comparing files by content failed.</source> <target>Comparing files by content failed.</target> <source>Generating file list...</source> <target>Generating file list...</target> -<source>Multiple...</source> -<target>Multiple...</target> - <source>Both sides are equal</source> <target>Both sides are equal</target> @@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>Delete right file/folder</target> +<source>Move file on left</source> +<target>Move file on left</target> + +<source>Move file on right</source> +<target>Move file on right</target> + <source>Overwrite left file/folder with right one</source> <target>Overwrite left file/folder with right one</target> @@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>Copy file attributes only to right</target> +<source>Multiple...</source> +<target>Multiple...</target> + <source>Deleting file %x</source> <target>Deleting file %x</target> diff --git a/BUILD/Languages/finnish.lng b/BUILD/Languages/finnish.lng index 8b2012f6..942fbc33 100644 --- a/BUILD/Languages/finnish.lng +++ b/BUILD/Languages/finnish.lng @@ -169,15 +169,15 @@ <source>Comparison Result</source> <target>Vertailun tulos</target> -<source>Incompatible synchronization database format:</source> -<target>Täsmäytyksen tietokannan muoto on virheellinen:</target> - <source>Initial synchronization:</source> <target>Ensi täsmäytys:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Jokin FreeFileSynk tietokannan tiedostoista puuttuu vielä:</target> +<source>Incompatible synchronization database format:</source> +<target>Täsmäytyksen tietokannan muoto on virheellinen:</target> + <source>Database files do not share a common synchronization session:</source> <target>Kannan tiedostot ovat eri sessioista:</target> @@ -232,9 +232,6 @@ <source>Invalid FreeFileSync config file!</source> <target>Virheellinen FreeFileSync asetustiedosto!</target> -<source>File does not exist:</source> -<target>Tiedosto puuttuu:</target> - <source>Error parsing configuration file:</source> <target>Virhe jäsentäessä asetustiedostoa:</target> @@ -259,6 +256,9 @@ <source>/sec</source> <target>/s</target> +<source>File does not exist:</source> +<target>Tiedosto puuttuu:</target> + <source>Could not read values for the following XML nodes:</source> <target>Tietoja lukeminen epäonnistui, XML jäsen:</target> @@ -372,9 +372,6 @@ Komento suoritetaan kun: <source>Batch execution</source> <target>Eräajon suoritus</target> -<source>Log-messages:</source> -<target>Lokin viestit:</target> - <source>Stop</source> <target>Seis</target> @@ -501,6 +498,24 @@ Komento suoritetaan kun: <source>Total amount of data that will be transferred</source> <target>Siirrettävän datan määrä</target> +<source>Operation:</source> +<target>Toiminto:</target> + +<source>Items found:</source> +<target>Osia löytyi:</target> + +<source>Items remaining:</source> +<target>Osia jäljellä:</target> + +<source>Speed:</source> +<target>Nopeus:</target> + +<source>Time remaining:</source> +<target>Aikaa jäljellä:</target> + +<source>Time elapsed:</source> +<target>Kulunut aika:</target> + <source>Batch job</source> <target>Eräajo</target> @@ -549,32 +564,14 @@ Komento suoritetaan kun: <source>&Cancel</source> <target>&Lopeta</target> -<source>Operation:</source> -<target>Toiminto:</target> - -<source>Items found:</source> -<target>Osia löytyi:</target> - -<source>Items remaining:</source> -<target>Osia jäljellä:</target> - -<source>Speed:</source> -<target>Nopeus:</target> - -<source>Time remaining:</source> -<target>Aikaa jäljellä:</target> - -<source>Time elapsed:</source> -<target>Kulunut aika:</target> - <source>Select variant:</source> <target>Valitse vaihtoehto:</target> <source><Automatic></source> <target><- Automaattinen -></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Tunnista ja monista muutokset molemmilla puolilla tietokannalla. Poistot ja ristiriidat hoidetaan automaattisesti.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>Peilaava ->></target> @@ -801,22 +798,14 @@ Sulje pois: \stuff\temp\* <source>Copy locked files</source> <target>Kopioi lukitut tiedostot</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopioi jaetut/lukitut tiedostot Volume Shadow Copy prosessilla (Vaatii Järjestelmävalvojan oikeuksia) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopioi jaetut/lukitut tiedostot Volume Shadow Copy prosessilla (Vaatii Järjestelmävalvojan oikeuksia)</target> <source>Copy file access permissions</source> <target>Kopioi tiedoston käyttöoikeuksia</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia)</target> <source>Hidden dialogs:</source> <target>Piilotetut ikkunat:</target> @@ -1130,9 +1119,6 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Filter: Single pair</source> <target>Suodata: Yksi pari</target> -<source>Ignore</source> -<target>Sivuta</target> - <source>Direct</source> <target>Suoraan</target> @@ -1286,12 +1272,12 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Error opening file:</source> <target>Virhe avatessa tiedostoa:</target> -<source>Endless loop when traversing directory:</source> -<target>Suorita hakemiston läpikulku jatkuvana:</target> - <source>Error traversing directory:</source> <target>Virhe hakemistoa läpikäydessä:</target> +<source>Endless loop when traversing directory:</source> +<target>Suorita hakemiston läpikulku jatkuvana:</target> + <source>Error setting privilege:</source> <target>Virhe, asettaessa oikeuksia:</target> @@ -1325,9 +1311,6 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Hakemistot riippuvuussuhteessa! Aseta täsmäyssääntöjä varovasti:</target> -<source>Comparing content of files %x</source> -<target>Vertaa tiedostojen %x tietosisältöä</target> - <source>Memory allocation failed!</source> <target>Muistin varaus epäonnistui!</target> @@ -1343,15 +1326,15 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Symlinks %x have the same date but a different target!</source> <target>Pikakuvakkeilla %x on sama päiväys mutta kohde on toinen!</target> +<source>Comparing content of files %x</source> +<target>Vertaa tiedostojen %x tietosisältöä</target> + <source>Comparing files by content failed.</source> <target>Tietosisällön vertailu epäonnistui.</target> <source>Generating file list...</source> <target>Luodaan tiedostolista...</target> -<source>Multiple...</source> -<target>Moninkertainen...</target> - <source>Both sides are equal</source> <target>Puolet ovat denttiset</target> @@ -1370,6 +1353,12 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Delete right file/folder</source> <target>Poista tiedosto/hakemisto oikealta</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>Ylikirjoita oikea tiedosto/hakemista vasemanpuolisella</target> @@ -1385,6 +1374,9 @@ Siirrä tiedosto- ja hakemisto-oikeuksia (Vaatii Järjestelmävalvojan oikeuksia <source>Copy file attributes only to right</source> <target>Monista tiedosto-ominaisuudet oikealle</target> +<source>Multiple...</source> +<target>Moninkertainen...</target> + <source>Deleting file %x</source> <target>Poista tiedosto %x</target> diff --git a/BUILD/Languages/french.lng b/BUILD/Languages/french.lng index 0fc97f8c..c81fa341 100644 --- a/BUILD/Languages/french.lng +++ b/BUILD/Languages/french.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Synchronisation Automatisée</target> -<source>Browse</source> -<target>Parcourir</target> - -<source>Windows Error Code %x:</source> -<target>Code erreur Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Code erreur Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Ligne de commande incorrecte : %x</target> - -<source>Error resolving symbolic link:</source> -<target>Erreur lors de la résolution du lien symbolique :</target> - -<source>Show pop-up</source> -<target>Montrer les boîtes de dialogue</target> - -<source>Show pop-up on errors or warnings</source> -<target>Montrer les messages d'avertissement ou d'erreur</target> - -<source>Ignore errors</source> -<target>Ignorer les erreurs</target> - -<source>Hide all error and warning messages</source> -<target>Masquer tous les messages d'erreurs et les avertissements</target> - -<source>Exit instantly</source> -<target>Sortie immédiate</target> - -<source>Abort synchronization immediately</source> -<target>Abandon immédiat de la synchronisation</target> - <source>Select alternate comparison settings</source> <target>Choisir d'autres paramètres de comparaison</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>choisir un intervalle de temps</target> +<source>Show pop-up</source> +<target>Montrer les boîtes de dialogue</target> + +<source>Show pop-up on errors or warnings</source> +<target>Montrer les messages d'avertissement ou d'erreur</target> + +<source>Ignore errors</source> +<target>Ignorer les erreurs</target> + +<source>Hide all error and warning messages</source> +<target>Masquer tous les messages d'erreurs et les avertissements</target> + +<source>Exit instantly</source> +<target>Sortie immédiate</target> + +<source>Abort synchronization immediately</source> +<target>Abandon immédiat de la synchronisation</target> + +<source>Browse</source> +<target>Parcourir</target> + +<source>Error reading from synchronization database:</source> +<target>Erreur lors de la lecture de la base de données de synchro :</target> + +<source>Error writing to synchronization database:</source> +<target>Erreur lors de l'écriture de la base de données de synchro :</target> + +<source>Invalid command line: %x</source> +<target>Ligne de commande incorrecte : %x</target> + +<source>Windows Error Code %x:</source> +<target>Code erreur Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Code erreur Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Erreur lors de la résolution du lien symbolique :</target> + <source>%x MB</source> <target>%x Mo</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Résultat de la comparaison</target> -<source>Incompatible synchronization database format:</source> -<target>Format de la base de données de synchro incompatible :</target> - <source>Initial synchronization:</source> <target>Première synchronisation :</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>L'un des fichiers de la base de données FreeFileSync n'existe plus :</target> -<source>Error reading from synchronization database:</source> -<target>Erreur lors de la lecture de la base de données de synchro :</target> +<source>Incompatible synchronization database format:</source> +<target>Format de la base de données de synchro incompatible :</target> <source>Database files do not share a common synchronization session:</source> <target>Les fichiers de la base de données ne font pas partie de la même session de synchronisation</target> @@ -199,12 +202,18 @@ <pluralform>%x sec</pluralform> </target> +<source>Drag && drop</source> +<target>Glisser && Déposer</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Erreur Fatale</target> +<source>Error reading file:</source> +<target>Erreur lors de la lecture du fichier :</target> + <source>Scanning:</source> <target>Lecture en cours :</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Fichier de configuration FreeFileSync invalide !</target> -<source>File does not exist:</source> -<target>Le fichier n'existe pas :</target> - <source>Error parsing configuration file:</source> <target>Erreur lors de l'analyse du fichier de configuration :</target> +<source>Error moving to Recycle Bin:</source> +<target>Erreur lors du déplacement dans la Corbeille :</target> + +<source>Could not load a required DLL:</source> +<target>Impossible de charger une DLL :</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Erreur lors de l'accès au Volume Shadow Copy Service !</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>La copie en tâche de fond sur WOW64 n'est pas possible. Utilisez pour cela la version 64 bits de FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Impossible de trouver le nom de volume pour le fichier :</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Le nom de volume %x ne fait pas partie du nom de fichier %y !</target> + <source>/sec</source> <target>/sec</target> +<source>File does not exist:</source> +<target>Le fichier n'existe pas :</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Impossible de lire les valeurs des noeuds XML suivants :</target> + <source>S&ave configuration...</source> <target>S&auvegarder la configuration...</target> @@ -324,141 +354,6 @@ La ligne de commande est exécutée chaque fois que : <source>A directory input field is empty.</source> <target>Un champ répertoire est vide</target> -<source>Drag && drop</source> -<target>Glisser && Déposer</target> - -<source>Could not initialize directory monitoring:</source> -<target>Impossible d'initialiser la surveillance des dossiers :</target> - -<source>Error when monitoring directories.</source> -<target>Erreur lors de la surveillance des répertoires.</target> - -<source>Conversion error:</source> -<target>Erreur de conversion :</target> - -<source>Error deleting file:</source> -<target>Erreur lors de la suppression d'un fichier :</target> - -<source>Error moving file:</source> -<target>Erreur lors du déplacement du fichier :</target> - -<source>Target file already existing!</source> -<target>Le fichier de destination existe déjà !</target> - -<source>Error moving directory:</source> -<target>Erreur lors du déplacement du répertoire :</target> - -<source>Target directory already existing!</source> -<target>Le répertoire de destination existe déjà !</target> - -<source>Error deleting directory:</source> -<target>Erreur lors de la suppression d'un répertoire :</target> - -<source>Error changing modification time:</source> -<target>Erreur lors du changement de la date de modification :</target> - -<source>Error loading library function:</source> -<target>Erreur lors du chargement de la bibliothèque de fonctions :</target> - -<source>Error reading security context:</source> -<target>Erreur de lecture du contexte de sécurité:</target> - -<source>Error writing security context:</source> -<target>Erreur d'écriture du contexte de sécurité:</target> - -<source>Error copying file permissions:</source> -<target>Erreur lors de la copie des attributs système</target> - -<source>Error creating directory:</source> -<target>Erreur lors de la création d'un répertoire :</target> - -<source>Error copying symbolic link:</source> -<target>Erreur lors de la copie du lien symbolique :</target> - -<source>Error copying file:</source> -<target>Erreur lors de la copie du fichier :</target> - -<source>Error opening file:</source> -<target>Erreur lors de l'ouverture du fichier :</target> - -<source>Error writing file:</source> -<target>Erreur lors de l'écriture du fichier :</target> - -<source>Error reading file:</source> -<target>Erreur lors de la lecture du fichier :</target> - -<source>Operation aborted!</source> -<target>Opération abandonnée !</target> - -<source>Endless loop when traversing directory:</source> -<target>Boucle sans fin lors du parcours du répertoire :</target> - -<source>Error traversing directory:</source> -<target>Erreur lors du parcours du répertoire :</target> - -<source>Error setting privilege:</source> -<target>Erreur de paramétrage de privilège</target> - -<source>Error moving to Recycle Bin:</source> -<target>Erreur lors du déplacement dans la Corbeille :</target> - -<source>Could not load a required DLL:</source> -<target>Impossible de charger une DLL :</target> - -<source>Error writing to synchronization database:</source> -<target>Erreur lors de l'écriture de la base de données de synchro :</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Erreur lors de l'accès au Volume Shadow Copy Service !</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>La copie en tâche de fond sur WOW64 n'est pas possible. Utilisez pour cela la version 64 bits de FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Impossible de trouver le nom de volume pour le fichier :</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Le nom de volume %x ne fait pas partie du nom de fichier %y !</target> - -<source>%x TB</source> -<target>%x To</target> - -<source>%x PB</source> -<target>%x Po</target> - -<source>%x%</source> -<target>%x %</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x heure</pluralform> -<pluralform>%x heures</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x jour</pluralform> -<pluralform>%x jours</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Impossible de lire les valeurs des noeuds XML suivants :</target> - <source>Logging</source> <target>Connexion</target> @@ -477,9 +372,6 @@ La ligne de commande est exécutée chaque fois que : <source>Batch execution</source> <target>Exécution du traitement batch</target> -<source>Log-messages:</source> -<target>Messages log :</target> - <source>Stop</source> <target>Arrêt</target> @@ -606,6 +498,24 @@ La ligne de commande est exécutée chaque fois que : <source>Total amount of data that will be transferred</source> <target>Volume de données à transférer</target> +<source>Operation:</source> +<target>Opération :</target> + +<source>Items found:</source> +<target>Elements trouvés :</target> + +<source>Items remaining:</source> +<target>Elements restants :</target> + +<source>Speed:</source> +<target>Vitesse :</target> + +<source>Time remaining:</source> +<target>Temps restant :</target> + +<source>Time elapsed:</source> +<target>Temps écoulé :</target> + <source>Batch job</source> <target>Fichier de commandes</target> @@ -654,32 +564,14 @@ La ligne de commande est exécutée chaque fois que : <source>&Cancel</source> <target>&Annuler</target> -<source>Operation:</source> -<target>Opération :</target> - -<source>Items found:</source> -<target>Elements trouvés :</target> - -<source>Items remaining:</source> -<target>Elements restants :</target> - -<source>Speed:</source> -<target>Vitesse :</target> - -<source>Time remaining:</source> -<target>Temps restant :</target> - -<source>Time elapsed:</source> -<target>Temps écoulé :</target> - <source>Select variant:</source> <target>Choisissez une variante :</target> <source><Automatic></source> <target><Automatique></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identifier et propager les modifications des deux côtés en utilisant une base de données. Les suppressions et les conflits sont détectés automatiquement.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>Miroir ->></target> @@ -906,22 +798,14 @@ Exclude: \stuff\temp\* <source>Copy locked files</source> <target>Copier les fichiers verrouillés</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -La copie des fichiers partagés ou verrouillés nécessite le Service Volume Shadow Copy (avec les droits administrateur) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>La copie des fichiers partagés ou verrouillés nécessite le Service Volume Shadow Copy (avec les droits administrateur)</target> <source>Copy file access permissions</source> <target>Copie des droits d'accès aux fichiers</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transfert des attributs système des fichiers et des répertoires (avec les droits administrateur) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transfert des attributs système des fichiers et des répertoires (avec les droits administrateur)</target> <source>Hidden dialogs:</source> <target>Boîtes de dialogue masquées :</target> @@ -953,6 +837,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>&Find next</source> <target>&Chercher le suivant</target> +<source>Operation aborted!</source> +<target>Opération abandonnée !</target> + <source>Main bar</source> <target>Barre principale</target> @@ -1130,6 +1017,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>File list exported!</source> <target>Liste des fichiers exportée !</target> +<source>Error writing file:</source> +<target>Erreur lors de l'écriture du fichier :</target> + <source>Batch file created successfully!</source> <target>Fichier de traitement batch créé avec succès !</target> @@ -1229,9 +1119,6 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Filter: Single pair</source> <target>Filtre : Une seule paire</target> -<source>Ignore</source> -<target>Ignorer</target> - <source>Direct</source> <target>Direct</target> @@ -1295,6 +1182,105 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Move files into a time-stamped subdirectory</source> <target>Déplacer les fichiers vers un sous-répertoire daté</target> +<source>%x TB</source> +<target>%x To</target> + +<source>%x PB</source> +<target>%x Po</target> + +<source>%x%</source> +<target>%x %</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x heure</pluralform> +<pluralform>%x heures</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x jour</pluralform> +<pluralform>%x jours</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Impossible d'initialiser la surveillance des dossiers :</target> + +<source>Error when monitoring directories.</source> +<target>Erreur lors de la surveillance des répertoires.</target> + +<source>Conversion error:</source> +<target>Erreur de conversion :</target> + +<source>Error deleting file:</source> +<target>Erreur lors de la suppression d'un fichier :</target> + +<source>Error moving file:</source> +<target>Erreur lors du déplacement du fichier :</target> + +<source>Target file already existing!</source> +<target>Le fichier de destination existe déjà !</target> + +<source>Error moving directory:</source> +<target>Erreur lors du déplacement du répertoire :</target> + +<source>Target directory already existing!</source> +<target>Le répertoire de destination existe déjà !</target> + +<source>Error deleting directory:</source> +<target>Erreur lors de la suppression d'un répertoire :</target> + +<source>Error changing modification time:</source> +<target>Erreur lors du changement de la date de modification :</target> + +<source>Error loading library function:</source> +<target>Erreur lors du chargement de la bibliothèque de fonctions :</target> + +<source>Error reading security context:</source> +<target>Erreur de lecture du contexte de sécurité:</target> + +<source>Error writing security context:</source> +<target>Erreur d'écriture du contexte de sécurité:</target> + +<source>Error copying file permissions:</source> +<target>Erreur lors de la copie des attributs système</target> + +<source>Error creating directory:</source> +<target>Erreur lors de la création d'un répertoire :</target> + +<source>Error copying symbolic link:</source> +<target>Erreur lors de la copie du lien symbolique :</target> + +<source>Error copying file:</source> +<target>Erreur lors de la copie du fichier :</target> + +<source>Error opening file:</source> +<target>Erreur lors de l'ouverture du fichier :</target> + +<source>Error traversing directory:</source> +<target>Erreur lors du parcours du répertoire :</target> + +<source>Endless loop when traversing directory:</source> +<target>Boucle sans fin lors du parcours du répertoire :</target> + +<source>Error setting privilege:</source> +<target>Erreur de paramétrage de privilège</target> + <source>Both sides have changed since last synchronization!</source> <target>Les deux côtés ont changé depuis la dernière synchronisation !</target> @@ -1325,9 +1311,6 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Les répertoires sont imbriqués ! Attention à la mise à jour des règles de synchronisation :</target> -<source>Comparing content of files %x</source> -<target>Comparaison du contenu des fichiers %x</target> - <source>Memory allocation failed!</source> <target>Erreur d'allocation de mémoire!</target> @@ -1343,15 +1326,15 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Symlinks %x have the same date but a different target!</source> <target>Le lien symbolique %x a la même date mais une destination différente !</target> +<source>Comparing content of files %x</source> +<target>Comparaison du contenu des fichiers %x</target> + <source>Comparing files by content failed.</source> <target>La comparaison des fichiers par leur contenu a échoué.</target> <source>Generating file list...</source> <target>Génération de la liste des fichiers...</target> -<source>Multiple...</source> -<target>Multiple...</target> - <source>Both sides are equal</source> <target>Les deux cotés sont identiques</target> @@ -1370,6 +1353,12 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Delete right file/folder</source> <target>Supprimer les fichiers/dossiers de droite</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>Remplacer le fichier/dossier de gauche avec celui de droite</target> @@ -1385,6 +1374,9 @@ Transfert des attributs système des fichiers et des répertoires (avec les droi <source>Copy file attributes only to right</source> <target>Copier seulement les attributs du fichier à droite</target> +<source>Multiple...</source> +<target>Multiple...</target> + <source>Deleting file %x</source> <target>Suppression du fichier %x</target> diff --git a/BUILD/Languages/german.lng b/BUILD/Languages/german.lng index 78c9ee8f..3b260354 100644 --- a/BUILD/Languages/german.lng +++ b/BUILD/Languages/german.lng @@ -169,15 +169,15 @@ <source>Comparison Result</source> <target>Ergebnis des Vergleichs</target> -<source>Incompatible synchronization database format:</source> -<target>Inkompatibles Datenbankformat:</target> - <source>Initial synchronization:</source> <target>Erstmalige Synchronisation:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Eine der FreeFileSync Datenbankdateien existiert noch nicht:</target> +<source>Incompatible synchronization database format:</source> +<target>Inkompatibles Datenbankformat:</target> + <source>Database files do not share a common synchronization session:</source> <target>Die Datenbankdateien enthalten keine gemeinsame Synchronisationssitzung:</target> @@ -372,9 +372,6 @@ Die Befehlszeile wird ausgeführt wenn: <source>Batch execution</source> <target>Batchlauf</target> -<source>Log-messages:</source> -<target>Meldungen:</target> - <source>Stop</source> <target>Stop</target> @@ -501,6 +498,24 @@ Die Befehlszeile wird ausgeführt wenn: <source>Total amount of data that will be transferred</source> <target>Gesamtmenge der zu übertragenden Daten</target> +<source>Operation:</source> +<target>Vorgang:</target> + +<source>Items found:</source> +<target>Gefundene Elemente:</target> + +<source>Items remaining:</source> +<target>Verbleibende Elemente:</target> + +<source>Speed:</source> +<target>Geschwindigkeit:</target> + +<source>Time remaining:</source> +<target>Verbleibende Zeit:</target> + +<source>Time elapsed:</source> +<target>Vergangene Zeit:</target> + <source>Batch job</source> <target>Batch-Job</target> @@ -549,32 +564,14 @@ Die Befehlszeile wird ausgeführt wenn: <source>&Cancel</source> <target>&Abbrechen</target> -<source>Operation:</source> -<target>Vorgang:</target> - -<source>Items found:</source> -<target>Gefundene Elemente:</target> - -<source>Items remaining:</source> -<target>Verbleibende Elemente:</target> - -<source>Speed:</source> -<target>Geschwindigkeit:</target> - -<source>Time remaining:</source> -<target>Verbleibende Zeit:</target> - -<source>Time elapsed:</source> -<target>Vergangene Zeit:</target> - <source>Select variant:</source> <target>Variante auswählen:</target> <source><Automatic></source> <target><Automatik></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identifiziere und propagiere Änderungen auf beiden Seiten mit Hilfe einer Datenbank. Löschungen und Konflikte werden automatisch erkannt.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identifiziere und propagiere Änderungen auf beiden Seiten mit Hilfe einer Datenbank. Löschungen, Umbenennungen und Konflikte werden automatisch erkannt.</target> <source>Mirror ->></source> <target>Spiegeln ->></target> @@ -1122,9 +1119,6 @@ Ausschließen: \stuff\temp\* <source>Filter: Single pair</source> <target>Filter: Einzelnes Verzeichnispaar</target> -<source>Ignore</source> -<target>Ignorieren</target> - <source>Direct</source> <target>Direkt</target> @@ -1278,12 +1272,12 @@ Ausschließen: \stuff\temp\* <source>Error opening file:</source> <target>Fehler beim Öffnen der Datei:</target> -<source>Endless loop when traversing directory:</source> -<target>Endlosschleife beim Lesen des Verzeichnisses:</target> - <source>Error traversing directory:</source> <target>Fehler beim Durchsuchen des Verzeichnisses:</target> +<source>Endless loop when traversing directory:</source> +<target>Endlosschleife beim Lesen des Verzeichnisses:</target> + <source>Error setting privilege:</source> <target>Fehler beim Setzen des Privilegs:</target> @@ -1317,9 +1311,6 @@ Ausschließen: \stuff\temp\* <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Die Verzeichnisse sind voneinander abhängig! Achtung beim Festlegen der Synchronisationseinstellungen:</target> -<source>Comparing content of files %x</source> -<target>Vergleiche Inhalt der Dateien %x</target> - <source>Memory allocation failed!</source> <target>Speicherallokation fehlgeschlagen!</target> @@ -1335,15 +1326,15 @@ Ausschließen: \stuff\temp\* <source>Symlinks %x have the same date but a different target!</source> <target>Die Symbolischen Links %x haben dasselbe Datum, aber ein unterschiedliches Ziel!</target> +<source>Comparing content of files %x</source> +<target>Vergleiche Inhalt der Dateien %x</target> + <source>Comparing files by content failed.</source> <target>Vergleich nach Dateiinhalt ist fehlgeschlagen.</target> <source>Generating file list...</source> <target>Erzeuge Dateiliste...</target> -<source>Multiple...</source> -<target>Verschiedene...</target> - <source>Both sides are equal</source> <target>Beide Seiten sind gleich</target> @@ -1362,6 +1353,12 @@ Ausschließen: \stuff\temp\* <source>Delete right file/folder</source> <target>Lösche rechte Datei</target> +<source>Move file on left</source> +<target>Verschiebe linke Datei</target> + +<source>Move file on right</source> +<target>Verschiebe rechte Datei</target> + <source>Overwrite left file/folder with right one</source> <target>Überschreibe linke Datei mit rechter</target> @@ -1377,6 +1374,9 @@ Ausschließen: \stuff\temp\* <source>Copy file attributes only to right</source> <target>Kopiere nur die Dateiattribute nach rechts</target> +<source>Multiple...</source> +<target>Verschiedene...</target> + <source>Deleting file %x</source> <target>Lösche Datei %x</target> diff --git a/BUILD/Languages/greek.lng b/BUILD/Languages/greek.lng index c3a9a44a..1b883921 100644 --- a/BUILD/Languages/greek.lng +++ b/BUILD/Languages/greek.lng @@ -169,15 +169,15 @@ <source>Comparison Result</source> <target>Αποτέλεσμα της σύγκρισης</target> -<source>Incompatible synchronization database format:</source> -<target>Η μορφή της βάσης δεδομένων συγχρονισμού δεν είναι συμβατή:</target> - <source>Initial synchronization:</source> <target>Αρχικός συγχρονισμός:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Μια από τις βάσεις δεδομένων του FreeFileSync δεν υπάρχει ακόμα:</target> +<source>Incompatible synchronization database format:</source> +<target>Η μορφή της βάσης δεδομένων συγχρονισμού δεν είναι συμβατή:</target> + <source>Database files do not share a common synchronization session:</source> <target>Οι βάσεις δεδομένων δεν έχουν δημιουργηθεί από τον ίδιο συγχρονισμό:</target> @@ -206,7 +206,7 @@ <target>Μεταφορά && Απόθεση</target> <source>Info</source> -<target>Πληροφορίες</target> +<target>Πληροφορία</target> <source>Fatal Error</source> <target>Σημαντικό Σφάλμα</target> @@ -372,9 +372,6 @@ The command line is executed each time: <source>Batch execution</source> <target>Εκτέλεση δέσμης ενεργειών</target> -<source>Log-messages:</source> -<target>Αποθηκευμένα μηνύματα:</target> - <source>Stop</source> <target>Λήξη</target> @@ -501,6 +498,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>Συνολικός όγκος δεδομένων που θα μεταφερθούν</target> +<source>Operation:</source> +<target>Λειτουργία:</target> + +<source>Items found:</source> +<target>Βρέθηκαν στοιχεία:</target> + +<source>Items remaining:</source> +<target>Περισσεύουν στοιχεία:</target> + +<source>Speed:</source> +<target>Ταχύτητα:</target> + +<source>Time remaining:</source> +<target>Απομένει χρόνος:</target> + +<source>Time elapsed:</source> +<target>Πέρασε χρόνος:</target> + <source>Batch job</source> <target>Δέσμη ενεργειών</target> @@ -549,32 +564,14 @@ The command line is executed each time: <source>&Cancel</source> <target>&Άκυρο</target> -<source>Operation:</source> -<target>Λειτουργία:</target> - -<source>Items found:</source> -<target>Βρέθηκαν στοιχεία:</target> - -<source>Items remaining:</source> -<target>Περισσεύουν στοιχεία:</target> - -<source>Speed:</source> -<target>Ταχύτητα:</target> - -<source>Time remaining:</source> -<target>Απομένει χρόνος:</target> - -<source>Time elapsed:</source> -<target>Πέρασε χρόνος:</target> - <source>Select variant:</source> <target>Επιλέξτε μια μέθοδο:</target> <source><Automatic></source> <target><Αυτόματα></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Ανίχνευση και εφαρμογή των αλλαγών και στις δυο πλευρές με τη χρήση βάσης δεδομένων. Διαγραφές και διενέξεις ανιχνεύονται αυτόματα.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Αναγνώριση και αναπαραγωγή των αλλαγών και στις δύο πλευρές με τη χρήση μιας βάσης δεδομένων. Διαγραφές, μετονομασίες και διενέξεις ανιχνεύονται αυτόματα.</target> <source>Mirror ->></source> <target>Κατοπτρισμός ->></target> @@ -1122,9 +1119,6 @@ Exclude: \stuff\temp\* <source>Filter: Single pair</source> <target>Φίλτρο: Ένα ζεύγος</target> -<source>Ignore</source> -<target>Παράβλεψη</target> - <source>Direct</source> <target>Ως δεσμό</target> @@ -1278,12 +1272,12 @@ Exclude: \stuff\temp\* <source>Error opening file:</source> <target>Σφάλμα κατά το άνοιγμα του αρχείου:</target> -<source>Endless loop when traversing directory:</source> -<target>Ατέρμονος βρόχος κατά την την ανάλυση του υποκαταλόγου:</target> - <source>Error traversing directory:</source> <target>Σφάλμα κατά την ανάλυση του υποκαταλόγου:</target> +<source>Endless loop when traversing directory:</source> +<target>Ατέρμονος βρόχος κατά την την ανάλυση του υποκαταλόγου:</target> + <source>Error setting privilege:</source> <target>Σφάλμα κατά τον ορισμό δικαιωμάτων:</target> @@ -1317,9 +1311,6 @@ Exclude: \stuff\temp\* <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Οι υποκατάλογοι είναι εξαρτώμενοι. Προσοχή κατά την εισαγωγή των κανόνων συγχρονισμού:</target> -<source>Comparing content of files %x</source> -<target>Σύγκριση του περιεχομένου των αρχείων %x</target> - <source>Memory allocation failed!</source> <target>Η δέσμευση χώρου μνήμης απέτυχε!</target> @@ -1335,15 +1326,15 @@ Exclude: \stuff\temp\* <source>Symlinks %x have the same date but a different target!</source> <target>Οι συμβολικοί δεσμοί %x έχουν την ίδια ημερομηνία αλλά διαφορετικό προορισμό!</target> +<source>Comparing content of files %x</source> +<target>Σύγκριση του περιεχομένου των αρχείων %x</target> + <source>Comparing files by content failed.</source> <target>Η σύγκριση του περιεχομένου των αρχείων απέτυχε.</target> <source>Generating file list...</source> <target>Δημιουργία καταλόγου αρχείων...</target> -<source>Multiple...</source> -<target>Πολλαπλές ρυθμίσεις...</target> - <source>Both sides are equal</source> <target>Οι δυο πλευρές είναι ίδιες</target> @@ -1362,6 +1353,12 @@ Exclude: \stuff\temp\* <source>Delete right file/folder</source> <target>Διαγραφή του αρχείου/υποκαταλόγου στα δεξιά</target> +<source>Move file on left</source> +<target>Μεταφορά του αρχείου που βρίσκεται αριστερά</target> + +<source>Move file on right</source> +<target>Μεταφορά του αρχείου που βρίσκεται δεξιά</target> + <source>Overwrite left file/folder with right one</source> <target>Αντικατάσταση του αρχείου/υποκαταλόγου στα αριστερά από το(ν) αντίστοιχο στα δεξιά</target> @@ -1377,6 +1374,9 @@ Exclude: \stuff\temp\* <source>Copy file attributes only to right</source> <target>Αντιγραφή μόνο των χαρακτηριστικών του αρχείου στα δεξιά</target> +<source>Multiple...</source> +<target>Πολλαπλές ρυθμίσεις...</target> + <source>Deleting file %x</source> <target>Διαγραφή του αρχείου %x</target> diff --git a/BUILD/Languages/hebrew.lng b/BUILD/Languages/hebrew.lng index 40b6721a..b15dfc56 100644 --- a/BUILD/Languages/hebrew.lng +++ b/BUILD/Languages/hebrew.lng @@ -2,7 +2,7 @@ <language name>עברית</language name> <translator>nitnit</translator> <locale>he_IL</locale> - <flag file>isreal.png</flag file> + <flag file>israel.png</flag file> <plural forms>2</plural forms> <plural definition>n == 1 ? 0 : 1</plural definition> </header> @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - סינכרון אוטומטי</target> -<source>Browse</source> -<target>עיין</target> - -<source>Windows Error Code %x:</source> -<target>קוד שגיאת חלונות %x:</target> - -<source>Linux Error Code %x:</source> -<target>קוד שגיאת לינוקס %x:</target> - -<source>Invalid command line: %x</source> -<target>שורת פקודה בלתי חוקית: %x</target> - -<source>Error resolving symbolic link:</source> -<target>שגיאה בפענוח קישור סימבולי (Symbolic Link)</target> - -<source>Show pop-up</source> -<target>הראה חלונות מוקפצים</target> - -<source>Show pop-up on errors or warnings</source> -<target>הראה חלונות מוקפצים עבור שגיאות או אזהרות</target> - -<source>Ignore errors</source> -<target>התעלם מטעויות</target> - -<source>Hide all error and warning messages</source> -<target>הסתר את כל הודעות ההזהרה והשגיאה</target> - -<source>Exit instantly</source> -<target>צא מידית</target> - -<source>Abort synchronization immediately</source> -<target>הפסק סנכרון מידית</target> - <source>Select alternate comparison settings</source> <target>בחר הגדרות השוואה חליפיות</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>בחר תחום זמן</target> +<source>Show pop-up</source> +<target>הראה חלונות מוקפצים</target> + +<source>Show pop-up on errors or warnings</source> +<target>הראה חלונות מוקפצים עבור שגיאות או אזהרות</target> + +<source>Ignore errors</source> +<target>התעלם מטעויות</target> + +<source>Hide all error and warning messages</source> +<target>הסתר את כל הודעות ההזהרה והשגיאה</target> + +<source>Exit instantly</source> +<target>צא מידית</target> + +<source>Abort synchronization immediately</source> +<target>הפסק סנכרון מידית</target> + +<source>Browse</source> +<target>עיין</target> + +<source>Error reading from synchronization database:</source> +<target>שגיאה בקריאה מבסיס הנתונים של הסנכרון:</target> + +<source>Error writing to synchronization database:</source> +<target>שגיאה ברישום לבסיס נתוני סנכרון:</target> + +<source>Invalid command line: %x</source> +<target>שורת פקודה בלתי חוקית: %x</target> + +<source>Windows Error Code %x:</source> +<target>קוד שגיאת חלונות %x:</target> + +<source>Linux Error Code %x:</source> +<target>קוד שגיאת לינוקס %x:</target> + +<source>Error resolving symbolic link:</source> +<target>שגיאה בפענוח קישור סימבולי (Symbolic Link)</target> + <source>%x MB</source> <target>%x מגה בייט</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>תוצאות ההשוואה</target> -<source>Incompatible synchronization database format:</source> -<target>מסד נתונים של הסנכרון לא תואם:</target> - <source>Initial synchronization:</source> <target>סנכרון ראשוני:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>אחד מקובצי בסיס הנתונים הבא עדיין לא קיים</target> -<source>Error reading from synchronization database:</source> -<target>שגיאה בקריאה מבסיס הנתונים של הסנכרון:</target> +<source>Incompatible synchronization database format:</source> +<target>מסד נתונים של הסנכרון לא תואם:</target> <source>Database files do not share a common synchronization session:</source> <target>קבצי בסיס הנתונים אינם חולקים ארוע סנכרון משותף:</target> @@ -199,12 +202,18 @@ <pluralform>%x שניות</pluralform> </target> +<source>Drag && drop</source> +<target>גרור והשלך</target> + <source>Info</source> <target>מידע</target> <source>Fatal Error</source> <target>שגיאה פטלית</target> +<source>Error reading file:</source> +<target>שגיאה בקריאת קובץ:</target> + <source>Scanning:</source> <target>סורק:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>קובץ תצורה בלתי חוקי!</target> -<source>File does not exist:</source> -<target>קובץ לא קיים:</target> - <source>Error parsing configuration file:</source> <target>שגיאה בניתוח קובץ תצורה:</target> +<source>Error moving to Recycle Bin:</source> +<target>שגיאה בהעברה לסל המיחזור:</target> + +<source>Could not load a required DLL:</source> +<target>:נדרש DLL לא יכל לטעון</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>שגיאה בגישה לשרות Volume Shadow Copy Service</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>לא נתמכת בגרסה זאת אנא התקן גרסה 64 WOW64 העתקת צל ב</target> + +<source>Could not determine volume name for file:</source> +<target>לא יכול לקבוע שם כרך לקובץ:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>כנונן %x לא בנתיב של קובץ %y!</target> + <source>/sec</source> <target>/שנ</target> +<source>File does not exist:</source> +<target>קובץ לא קיים:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>XML לא יכול לקרא ערכים מצמתי :</target> + <source>S&ave configuration...</source> <target>&שמור תצורה...</target> @@ -324,141 +354,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>שדה כניסת מחיצה ריק.</target> -<source>Drag && drop</source> -<target>גרור והשלך</target> - -<source>Could not initialize directory monitoring:</source> -<target>לא יכול לאתחל ניטור מחיצה:</target> - -<source>Error when monitoring directories.</source> -<target>שגיאה בזמן ניטור מחיצות.</target> - -<source>Conversion error:</source> -<target>שגיאה בהסבה:</target> - -<source>Error deleting file:</source> -<target>שגיאה במחיקת קובץ:</target> - -<source>Error moving file:</source> -<target>שגיאה בהעברת קובץ:</target> - -<source>Target file already existing!</source> -<target>קובץ מטרה כבר קיים!</target> - -<source>Error moving directory:</source> -<target>שגיאה בהעברת מחיצה:</target> - -<source>Target directory already existing!</source> -<target>מחיצת מטרה כבר קיימת!</target> - -<source>Error deleting directory:</source> -<target>שגיאה במחיקת מחיצה:</target> - -<source>Error changing modification time:</source> -<target>שגיאה בשינוי זמן:</target> - -<source>Error loading library function:</source> -<target>שגיאה בטעינת ספרית פונקציות:</target> - -<source>Error reading security context:</source> -<target>שגיאה בכתיבת הקשר בטיחות:</target> - -<source>Error writing security context:</source> -<target>שגיאה בכתיבת הקשר בטיחות:</target> - -<source>Error copying file permissions:</source> -<target>שגיאה בהעתקת הרשאות קובץ:</target> - -<source>Error creating directory:</source> -<target>שגיאה ביצירת מחיצה:</target> - -<source>Error copying symbolic link:</source> -<target>שגיאה בהעתקת קישור :</target> - -<source>Error copying file:</source> -<target>שגיאה בהעתקת קובץ:</target> - -<source>Error opening file:</source> -<target>שגיאה בפתיחת קובץ:</target> - -<source>Error writing file:</source> -<target>שגיאה בכתיבת קובץ:</target> - -<source>Error reading file:</source> -<target>שגיאה בקריאת קובץ:</target> - -<source>Operation aborted!</source> -<target>הפעולה בוטלה!</target> - -<source>Endless loop when traversing directory:</source> -<target>נוצרת לולאה אינסופית בחצית מחיצות</target> - -<source>Error traversing directory:</source> -<target>שגיאה בהצלבת מחיצות</target> - -<source>Error setting privilege:</source> -<target>שגיאה בהשמת פריווילגיה</target> - -<source>Error moving to Recycle Bin:</source> -<target>שגיאה בהעברה לסל המיחזור:</target> - -<source>Could not load a required DLL:</source> -<target>:נדרש DLL לא יכל לטעון</target> - -<source>Error writing to synchronization database:</source> -<target>שגיאה ברישום לבסיס נתוני סנכרון:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>שגיאה בגישה לשרות Volume Shadow Copy Service</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>לא נתמכת בגרסה זאת אנא התקן גרסה 64 WOW64 העתקת צל ב</target> - -<source>Could not determine volume name for file:</source> -<target>לא יכול לקבוע שם כרך לקובץ:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>כנונן %x לא בנתיב של קובץ %y!</target> - -<source>%x TB</source> -<target>%x טרה בייט</target> - -<source>%x PB</source> -<target>%x פטה בייט</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 דקה</pluralform> -<pluralform>%x דקות</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 שעה</pluralform> -<pluralform>%x שעות</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 יום</pluralform> -<pluralform>%x ימים</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>XML לא יכול לקרא ערכים מצמתי :</target> - <source>Logging</source> <target>רישום ביומן</target> @@ -477,9 +372,6 @@ The command line is executed each time: <source>Batch execution</source> <target>פעולת אצווה</target> -<source>Log-messages:</source> -<target>הודעת יומן:</target> - <source>Stop</source> <target>עצור</target> @@ -606,6 +498,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>סך הכל נתונים להעברה</target> +<source>Operation:</source> +<target>פעולה:</target> + +<source>Items found:</source> +<target>אלמנטים נמצאו:</target> + +<source>Items remaining:</source> +<target>אלמנתים נותרו:</target> + +<source>Speed:</source> +<target>מהירות:</target> + +<source>Time remaining:</source> +<target>זמן נותר:</target> + +<source>Time elapsed:</source> +<target>זמן עבר:</target> + <source>Batch job</source> <target>עבודת אצווה</target> @@ -654,32 +564,14 @@ The command line is executed each time: <source>&Cancel</source> <target>&בטל</target> -<source>Operation:</source> -<target>פעולה:</target> - -<source>Items found:</source> -<target>אלמנטים נמצאו:</target> - -<source>Items remaining:</source> -<target>אלמנתים נותרו:</target> - -<source>Speed:</source> -<target>מהירות:</target> - -<source>Time remaining:</source> -<target>זמן נותר:</target> - -<source>Time elapsed:</source> -<target>זמן עבר:</target> - <source>Select variant:</source> <target>בחר משתנה:</target> <source><Automatic></source> <target><אוטומטי></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>זהה והפץ שינויים בשני הצדדים בעזרת בסיס נתונים. מחיקות וקונפליקטים מזוהים באופן אוטומטי.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>זהה והפץ שינויים בשני הצדדים באמצעות שימוש בבסיס נתונים. מחיקות, שינויי שמות וסתירות מתגלים באופן אוטומטי.</target> <source>Mirror ->></source> <target><<- מראה</target> @@ -901,27 +793,19 @@ Exclude: \stuff\temp\* <target>העתקת קובץ בעסקה</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>רשום לקובץ זמני (*.ffs_tmp) תחילה ושנה שם. פעולה זו מבטיחה עקביות המצב גם במקרה של שגיאה חמורה.</target> <source>Copy locked files</source> <target>העתק קבצים נעולים</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -העתק קבצים בשיתוף או נעולים באמצעות שרות Volume Shadow Copy Service (דורש הרשאות מנהל מערכת) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>העתק קבצים בשיתוף או נעולים באמצעות שרות Volume Shadow Copy Service (דורש הרשאות מנהל מערכת)</target> <source>Copy file access permissions</source> <target>העתק הרשאות גישה של הקובץ</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -העבר הרשאות קבצים ומחיצות (דורש הרשאות מנהל מערכת) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>העבר הרשאות קבצים ומחיצות (דורש הרשאות מנהל מערכת)</target> <source>Hidden dialogs:</source> <target>דיאלוגים מוסתרים:</target> @@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>&מצא הבא</target> +<source>Operation aborted!</source> +<target>הפעולה בוטלה!</target> + <source>Main bar</source> <target>סרגל ראשי</target> @@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights) <target>עימוד אוטומטי</target> <source>Icon size:</source> -<target></target> +<target>גודל סמל:</target> <source>Small</source> -<target></target> +<target>קטן</target> <source>Medium</source> -<target></target> +<target>בינוני</target> <source>Large</source> -<target></target> +<target>גדול</target> <source>Include all rows</source> <target>כלול את כל השורות</target> @@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>רשימת קבצים יוצאה!</target> +<source>Error writing file:</source> +<target>שגיאה בכתיבת קובץ:</target> + <source>Batch file created successfully!</source> <target>קובץ אצווה נוצר בהצלחה!</target> @@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>זוג אחד :מסונן</target> -<source>Ignore</source> -<target>התעלם</target> - <source>Direct</source> <target>כוון</target> @@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>העבר קבצים לתוך מחיצות עם שם המכיל טביעת זמן ותאריך</target> +<source>%x TB</source> +<target>%x טרה בייט</target> + +<source>%x PB</source> +<target>%x פטה בייט</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 דקה</pluralform> +<pluralform>%x דקות</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 שעה</pluralform> +<pluralform>%x שעות</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 יום</pluralform> +<pluralform>%x ימים</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>לא יכול לאתחל ניטור מחיצה:</target> + +<source>Error when monitoring directories.</source> +<target>שגיאה בזמן ניטור מחיצות.</target> + +<source>Conversion error:</source> +<target>שגיאה בהסבה:</target> + +<source>Error deleting file:</source> +<target>שגיאה במחיקת קובץ:</target> + +<source>Error moving file:</source> +<target>שגיאה בהעברת קובץ:</target> + +<source>Target file already existing!</source> +<target>קובץ מטרה כבר קיים!</target> + +<source>Error moving directory:</source> +<target>שגיאה בהעברת מחיצה:</target> + +<source>Target directory already existing!</source> +<target>מחיצת מטרה כבר קיימת!</target> + +<source>Error deleting directory:</source> +<target>שגיאה במחיקת מחיצה:</target> + +<source>Error changing modification time:</source> +<target>שגיאה בשינוי זמן:</target> + +<source>Error loading library function:</source> +<target>שגיאה בטעינת ספרית פונקציות:</target> + +<source>Error reading security context:</source> +<target>שגיאה בכתיבת הקשר בטיחות:</target> + +<source>Error writing security context:</source> +<target>שגיאה בכתיבת הקשר בטיחות:</target> + +<source>Error copying file permissions:</source> +<target>שגיאה בהעתקת הרשאות קובץ:</target> + +<source>Error creating directory:</source> +<target>שגיאה ביצירת מחיצה:</target> + +<source>Error copying symbolic link:</source> +<target>שגיאה בהעתקת קישור :</target> + +<source>Error copying file:</source> +<target>שגיאה בהעתקת קובץ:</target> + +<source>Error opening file:</source> +<target>שגיאה בפתיחת קובץ:</target> + +<source>Error traversing directory:</source> +<target>שגיאה בהצלבת מחיצות</target> + +<source>Endless loop when traversing directory:</source> +<target>נוצרת לולאה אינסופית בחצית מחיצות</target> + +<source>Error setting privilege:</source> +<target>שגיאה בהשמת פריווילגיה</target> + <source>Both sides have changed since last synchronization!</source> <target>שני הצדדים שונו מאז הסנכרון האחרון!</target> @@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>מחיצות תלויות! זהירות בהגדרת כללי סנכרון:</target> -<source>Comparing content of files %x</source> -<target>השווה תכולה של קבצים %x</target> - <source>Memory allocation failed!</source> <target>הקצאת זכרון נכשלה!</target> @@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>קשור סימבולי %x בעל תאריך זהה אך מטרה שונה!</target> +<source>Comparing content of files %x</source> +<target>השווה תכולה של קבצים %x</target> + <source>Comparing files by content failed.</source> <target>השוואת קבצים באמצעות תכולה נכשלה.</target> <source>Generating file list...</source> <target>מייצר רשימת קבצים...</target> -<source>Multiple...</source> -<target>הכפל...</target> - <source>Both sides are equal</source> <target>שני הצדדים שווים</target> @@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>מחק קובץ\מחיצה בצד ימין</target> +<source>Move file on left</source> +<target>העבר קובץ בצד שמאל</target> + +<source>Move file on right</source> +<target>העבר קובץ בצד ימין</target> + <source>Overwrite left file/folder with right one</source> <target>העתק ודרוס קובץ\מחיצה מימין לשמאל</target> @@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>העתק תכונות קובץ בלבד משמאל לימין</target> +<source>Multiple...</source> +<target>הכפל...</target> + <source>Deleting file %x</source> <target>מוחק קובץ %x</target> diff --git a/BUILD/Languages/hungarian.lng b/BUILD/Languages/hungarian.lng index b5a14889..c21d5efd 100644 --- a/BUILD/Languages/hungarian.lng +++ b/BUILD/Languages/hungarian.lng @@ -169,15 +169,15 @@ <source>Comparison Result</source> <target>Az összehasonlítás eredménye</target> -<source>Incompatible synchronization database format:</source> -<target>Inkompatibilis szinkronizációs adatbázis formátum:</target> - <source>Initial synchronization:</source> <target>Első szinkronizáció:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>A FreeFileSync egyik adatbázisfájlja nem létezik:</target> +<source>Incompatible synchronization database format:</source> +<target>Inkompatibilis szinkronizációs adatbázis formátum:</target> + <source>Database files do not share a common synchronization session:</source> <target>Az adatbázisfájlok nem osztoznak egy közös szinkronizációs munkameneten:</target> @@ -372,9 +372,6 @@ A parancssor végrehajtódik minden alkalommal, ha: <source>Batch execution</source> <target>Kötegelt végrehajtás</target> -<source>Log-messages:</source> -<target>Naplóbejegyzések:</target> - <source>Stop</source> <target>Megállítás</target> @@ -501,6 +498,24 @@ A parancssor végrehajtódik minden alkalommal, ha: <source>Total amount of data that will be transferred</source> <target>A mozgatandó adatok összmérete</target> +<source>Operation:</source> +<target>Művelet:</target> + +<source>Items found:</source> +<target>Talált elemek száma:</target> + +<source>Items remaining:</source> +<target>Hátralévő elemek száma:</target> + +<source>Speed:</source> +<target>Sebesség:</target> + +<source>Time remaining:</source> +<target>Hátralévő idő:</target> + +<source>Time elapsed:</source> +<target>Eltelt idő:</target> + <source>Batch job</source> <target>Kötegelt feladat</target> @@ -549,32 +564,14 @@ A parancssor végrehajtódik minden alkalommal, ha: <source>&Cancel</source> <target>&Mégsem</target> -<source>Operation:</source> -<target>Művelet:</target> - -<source>Items found:</source> -<target>Talált elemek száma:</target> - -<source>Items remaining:</source> -<target>Hátralévő elemek száma:</target> - -<source>Speed:</source> -<target>Sebesség:</target> - -<source>Time remaining:</source> -<target>Hátralévő idő:</target> - -<source>Time elapsed:</source> -<target>Eltelt idő:</target> - <source>Select variant:</source> <target>Változat kiválasztása:</target> <source><Automatic></source> <target><Automatikus></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Mindkét oldal változásainak azonosítása és tárolása adatbázis segítségével. A törlések és ütközések automatikusan észlelődnek.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>Tükrözés ->></target> @@ -1123,9 +1120,6 @@ Kizárni: \stuff\temp\* <source>Filter: Single pair</source> <target>Szűrő: Egy pár</target> -<source>Ignore</source> -<target>Figyelmen kívül hagy</target> - <source>Direct</source> <target>Közvetlen</target> @@ -1279,12 +1273,12 @@ Kizárni: \stuff\temp\* <source>Error opening file:</source> <target>A fájl megnyitása sikertelen:</target> -<source>Endless loop when traversing directory:</source> -<target>Végtelen hurok a mappák bejárásakor:</target> - <source>Error traversing directory:</source> <target>A mappa átnézése sikertelen:</target> +<source>Endless loop when traversing directory:</source> +<target>Végtelen hurok a mappák bejárásakor:</target> + <source>Error setting privilege:</source> <target>Hiba történt a jogok beállítása közben:</target> @@ -1318,9 +1312,6 @@ Kizárni: \stuff\temp\* <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>A mappák függenek egymástól! Legyen óvatos, amikor megadja a szinkronizálási szabályokat:</target> -<source>Comparing content of files %x</source> -<target>%x fájlok tartalmának összehasonlítása</target> - <source>Memory allocation failed!</source> <target>Sikertelen memóriafoglalás!</target> @@ -1336,15 +1327,15 @@ Kizárni: \stuff\temp\* <source>Symlinks %x have the same date but a different target!</source> <target>A(z) %x symlinknek megegyezik a dátuma, de a célpontja nem!</target> +<source>Comparing content of files %x</source> +<target>%x fájlok tartalmának összehasonlítása</target> + <source>Comparing files by content failed.</source> <target>Sikertelen a fájlok összehasonlítása tartalom alapján.</target> <source>Generating file list...</source> <target>Fájllista generálása...</target> -<source>Multiple...</source> -<target>Sokszorosítás</target> - <source>Both sides are equal</source> <target>Mindkét oldal egyforma</target> @@ -1363,6 +1354,12 @@ Kizárni: \stuff\temp\* <source>Delete right file/folder</source> <target>Jobb oldali fájl/mappa törlése</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>Bal oldali fájl/mappa felülírása a jobb oldalival</target> @@ -1378,6 +1375,9 @@ Kizárni: \stuff\temp\* <source>Copy file attributes only to right</source> <target>Fájl attribútumok másolása csak a jobb oldalra</target> +<source>Multiple...</source> +<target>Sokszorosítás</target> + <source>Deleting file %x</source> <target>Fájl törlése %x</target> diff --git a/BUILD/Languages/italian.lng b/BUILD/Languages/italian.lng index cdf4ef83..97aff271 100644 --- a/BUILD/Languages/italian.lng +++ b/BUILD/Languages/italian.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Sincronizzazione Automatizzata</target> -<source>Browse</source> -<target>Sfoglia</target> - -<source>Windows Error Code %x:</source> -<target>Errore Windows Codice %x:</target> - -<source>Linux Error Code %x:</source> -<target>Errore Linux Codice %x:</target> - -<source>Invalid command line: %x</source> -<target>Linea di comando non valida: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Errore nella risoluzione di collegamento simbolico:</target> - -<source>Show pop-up</source> -<target>Mostra pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Mostra pop-up di errori o avvisi</target> - -<source>Ignore errors</source> -<target>Ignora gli errori</target> - -<source>Hide all error and warning messages</source> -<target>Nascondi tutti gli errori e i messaggi d'avviso</target> - -<source>Exit instantly</source> -<target>Esci istantaneamente</target> - -<source>Abort synchronization immediately</source> -<target>Interrompi immediatamente la sincronizzazione</target> - <source>Select alternate comparison settings</source> <target>Seleziona impostazioni di comparazione alternative</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Seleziona intervallo di tempo</target> +<source>Show pop-up</source> +<target>Mostra pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Mostra pop-up di errori o avvisi</target> + +<source>Ignore errors</source> +<target>Ignora gli errori</target> + +<source>Hide all error and warning messages</source> +<target>Nascondi tutti gli errori e i messaggi d'avviso</target> + +<source>Exit instantly</source> +<target>Esci istantaneamente</target> + +<source>Abort synchronization immediately</source> +<target>Interrompi immediatamente la sincronizzazione</target> + +<source>Browse</source> +<target>Sfoglia</target> + +<source>Error reading from synchronization database:</source> +<target>Errore in lettura dal database di sincronizzione:</target> + +<source>Error writing to synchronization database:</source> +<target>Errore in scrittura sul database di sincronizzazione:</target> + +<source>Invalid command line: %x</source> +<target>Linea di comando non valida: %x</target> + +<source>Windows Error Code %x:</source> +<target>Errore Windows Codice %x:</target> + +<source>Linux Error Code %x:</source> +<target>Errore Linux Codice %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Errore nella risoluzione di collegamento simbolico:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Risultato della comparazione</target> -<source>Incompatible synchronization database format:</source> -<target>Formato database di sincronizzazione incompatibile:</target> - <source>Initial synchronization:</source> <target>Prima sincronizzazione:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Un file database di FreeFileSync non è ancora stato creato:</target> -<source>Error reading from synchronization database:</source> -<target>Errore in lettura dal database di sincronizzione:</target> +<source>Incompatible synchronization database format:</source> +<target>Formato database di sincronizzazione incompatibile:</target> <source>Database files do not share a common synchronization session:</source> <target>I file database non condividono una comune sessione di sincronizzazione:</target> @@ -199,12 +202,18 @@ <pluralform>%x sec</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && drop</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Errore Fatale</target> +<source>Error reading file:</source> +<target>Errore durante la lettura del file:</target> + <source>Scanning:</source> <target>Analisi in corso:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>File di configurazione FreeFileSync non valido!</target> -<source>File does not exist:</source> -<target>Il file non esiste:</target> - <source>Error parsing configuration file:</source> <target>Errore nell'analisi del file di configurazione:</target> +<source>Error moving to Recycle Bin:</source> +<target>Errore durante lo spostamento nel Cestino:</target> + +<source>Could not load a required DLL:</source> +<target>Impossibile caricare una DLL richiesta:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Errore in accesso al Servizio Volume Shadow Copy</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>La creazione di copie shadow su WOW64 non e' supportata. Utilizzare FreeFileSync in versione 64-bit.</target> + +<source>Could not determine volume name for file:</source> +<target>Impossibile determinare il nome volume per il file:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Il nome volume %x non è parte del nome file %y!</target> + <source>/sec</source> <target>/sec</target> +<source>File does not exist:</source> +<target>Il file non esiste:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Impossibile leggere i valori per i seguenti nodi XML:</target> + <source>S&ave configuration...</source> <target>S&alva la configurazione...</target> @@ -324,141 +354,6 @@ La linea di comando è eseguita ogni volta che: <source>A directory input field is empty.</source> <target>Un campo directory di input è vuoto.</target> -<source>Drag && drop</source> -<target>Drag && drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Monitoraggio directory non inizializzabile:</target> - -<source>Error when monitoring directories.</source> -<target>Errore durante il monitoraggio directory.</target> - -<source>Conversion error:</source> -<target>Errore di conversione:</target> - -<source>Error deleting file:</source> -<target>Errore durante l'eliminazione del file:</target> - -<source>Error moving file:</source> -<target>Errore nello spostamento file:</target> - -<source>Target file already existing!</source> -<target>File destinazione già esistente!</target> - -<source>Error moving directory:</source> -<target>Errore nello spostamento directory:</target> - -<source>Target directory already existing!</source> -<target>Directory di destinazione già esistente!</target> - -<source>Error deleting directory:</source> -<target>Errore durante l'eliminazione delle directory:</target> - -<source>Error changing modification time:</source> -<target>Errore durante la modifica della data:</target> - -<source>Error loading library function:</source> -<target>Errore nel caricamento della funzione libreria:</target> - -<source>Error reading security context:</source> -<target>Errore in lettura del contesto di sicurezza:</target> - -<source>Error writing security context:</source> -<target>Errore in scrittura del contesto di sicurezza:</target> - -<source>Error copying file permissions:</source> -<target>Errore durante la copia dei permessi su file:</target> - -<source>Error creating directory:</source> -<target>Errore durante la creazione della directory:</target> - -<source>Error copying symbolic link:</source> -<target>Errore durante la copia del link simbolico:</target> - -<source>Error copying file:</source> -<target>Errore durante la copia del file:</target> - -<source>Error opening file:</source> -<target>Errore in apertura file:</target> - -<source>Error writing file:</source> -<target>Errore durante la scrittura del file:</target> - -<source>Error reading file:</source> -<target>Errore durante la lettura del file:</target> - -<source>Operation aborted!</source> -<target>Operazione abortita!</target> - -<source>Endless loop when traversing directory:</source> -<target>Loop senza fine attraverso le directory:</target> - -<source>Error traversing directory:</source> -<target>Errore nel percorso della directory:</target> - -<source>Error setting privilege:</source> -<target>Errore nell'impostazione dei privilegi:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Errore durante lo spostamento nel Cestino:</target> - -<source>Could not load a required DLL:</source> -<target>Impossibile caricare una DLL richiesta:</target> - -<source>Error writing to synchronization database:</source> -<target>Errore in scrittura sul database di sincronizzazione:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Errore in accesso al Servizio Volume Shadow Copy</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>La creazione di copie shadow su WOW64 non e' supportata. Utilizzare FreeFileSync in versione 64-bit.</target> - -<source>Could not determine volume name for file:</source> -<target>Impossibile determinare il nome volume per il file:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Il nome volume %x non è parte del nome file %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 ora</pluralform> -<pluralform>%x ore</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 giorno</pluralform> -<pluralform>%x giorni</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Impossibile leggere i valori per i seguenti nodi XML:</target> - <source>Logging</source> <target>Logging</target> @@ -477,9 +372,6 @@ La linea di comando è eseguita ogni volta che: <source>Batch execution</source> <target>Esecuzione in batch</target> -<source>Log-messages:</source> -<target>Log-messages:</target> - <source>Stop</source> <target>Stop</target> @@ -606,6 +498,24 @@ La linea di comando è eseguita ogni volta che: <source>Total amount of data that will be transferred</source> <target>Volume dei dati che verranno trasferiti</target> +<source>Operation:</source> +<target>Operazione:</target> + +<source>Items found:</source> +<target>Elementi trovati:</target> + +<source>Items remaining:</source> +<target>Elementi rimanenti:</target> + +<source>Speed:</source> +<target>Velocita':</target> + +<source>Time remaining:</source> +<target>Tempo rimanente:</target> + +<source>Time elapsed:</source> +<target>Tempo trascorso:</target> + <source>Batch job</source> <target>Batch job</target> @@ -654,32 +564,14 @@ La linea di comando è eseguita ogni volta che: <source>&Cancel</source> <target>&Annulla</target> -<source>Operation:</source> -<target>Operazione:</target> - -<source>Items found:</source> -<target>Elementi trovati:</target> - -<source>Items remaining:</source> -<target>Elementi rimanenti:</target> - -<source>Speed:</source> -<target>Velocita':</target> - -<source>Time remaining:</source> -<target>Tempo rimanente:</target> - -<source>Time elapsed:</source> -<target>Tempo trascorso:</target> - <source>Select variant:</source> <target>Selezionare una variante:</target> <source><Automatic></source> <target><Automatico></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identifica e propaga cambiamenti su entrambi i lati usando un database. Cancellazioni e conflitti sono riconosciuti automaticamente.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identifica e propaga modifiche su entrambi i lati usando un database. Cancellazioni, ridenominazioni e conflitti sono rilevati automaticamente.</target> <source>Mirror ->></source> <target>Mirror ->></target> @@ -901,27 +793,19 @@ Escludi: \stuff\temp\* <target>Copia transazionale file</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Scrivi su un file temporaneo (*.ffs_tmp) prima di rinominarlo. Ciò garantisce uno stato consistente anche in caso di errore fatale.</target> <source>Copy locked files</source> <target>Copia file bloccati</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copia file condivisi o bloccati usando il Servizio Volume Shadow Copy (Richiede diritti di Administrator) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Copia file condivisi o bloccati usando il Servizio Volume Shadow Copy (Richiede diritti di Administrator)</target> <source>Copy file access permissions</source> <target>Copia permessi di accesso file</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator)</target> <source>Hidden dialogs:</source> <target>Messaggi nascosti:</target> @@ -953,6 +837,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>&Find next</source> <target>&Trova successivo</target> +<source>Operation aborted!</source> +<target>Operazione abortita!</target> + <source>Main bar</source> <target>Barra principale</target> @@ -993,16 +880,16 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <target>Larghezza automatica colonne</target> <source>Icon size:</source> -<target></target> +<target>Dimensione icona:</target> <source>Small</source> -<target></target> +<target>Piccola</target> <source>Medium</source> -<target></target> +<target>Media</target> <source>Large</source> -<target></target> +<target>Grande</target> <source>Include all rows</source> <target>Includi tutte le righe</target> @@ -1130,6 +1017,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>File list exported!</source> <target>Lista dei file esportata!</target> +<source>Error writing file:</source> +<target>Errore durante la scrittura del file:</target> + <source>Batch file created successfully!</source> <target>Creazione batch file riuscita!</target> @@ -1229,9 +1119,6 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Filter: Single pair</source> <target>Filtro: Singola coppia</target> -<source>Ignore</source> -<target>Ignora</target> - <source>Direct</source> <target>Diretto</target> @@ -1295,6 +1182,105 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Move files into a time-stamped subdirectory</source> <target>Sposta file in una sotto-cartella datata</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 ora</pluralform> +<pluralform>%x ore</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 giorno</pluralform> +<pluralform>%x giorni</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Monitoraggio directory non inizializzabile:</target> + +<source>Error when monitoring directories.</source> +<target>Errore durante il monitoraggio directory.</target> + +<source>Conversion error:</source> +<target>Errore di conversione:</target> + +<source>Error deleting file:</source> +<target>Errore durante l'eliminazione del file:</target> + +<source>Error moving file:</source> +<target>Errore nello spostamento file:</target> + +<source>Target file already existing!</source> +<target>File destinazione già esistente!</target> + +<source>Error moving directory:</source> +<target>Errore nello spostamento directory:</target> + +<source>Target directory already existing!</source> +<target>Directory di destinazione già esistente!</target> + +<source>Error deleting directory:</source> +<target>Errore durante l'eliminazione delle directory:</target> + +<source>Error changing modification time:</source> +<target>Errore durante la modifica della data:</target> + +<source>Error loading library function:</source> +<target>Errore nel caricamento della funzione libreria:</target> + +<source>Error reading security context:</source> +<target>Errore in lettura del contesto di sicurezza:</target> + +<source>Error writing security context:</source> +<target>Errore in scrittura del contesto di sicurezza:</target> + +<source>Error copying file permissions:</source> +<target>Errore durante la copia dei permessi su file:</target> + +<source>Error creating directory:</source> +<target>Errore durante la creazione della directory:</target> + +<source>Error copying symbolic link:</source> +<target>Errore durante la copia del link simbolico:</target> + +<source>Error copying file:</source> +<target>Errore durante la copia del file:</target> + +<source>Error opening file:</source> +<target>Errore in apertura file:</target> + +<source>Error traversing directory:</source> +<target>Errore nel percorso della directory:</target> + +<source>Endless loop when traversing directory:</source> +<target>Loop senza fine attraverso le directory:</target> + +<source>Error setting privilege:</source> +<target>Errore nell'impostazione dei privilegi:</target> + <source>Both sides have changed since last synchronization!</source> <target>Entrambi i lati sono cambiati dall'ultima sincronizzazione!</target> @@ -1325,9 +1311,6 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Le directory sono dipendenti! Fai attenzione quando configuri le regole di sincronizzazione:</target> -<source>Comparing content of files %x</source> -<target>Comparazione contenuto del file %x</target> - <source>Memory allocation failed!</source> <target>Allocazione di memoria fallita!</target> @@ -1343,15 +1326,15 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Symlinks %x have the same date but a different target!</source> <target>Symlinks %x hanno stessa data ma differente target!</target> +<source>Comparing content of files %x</source> +<target>Comparazione contenuto del file %x</target> + <source>Comparing files by content failed.</source> <target>Comparazione file in base al contenuto fallita.</target> <source>Generating file list...</source> <target>Generazione lista dei file...</target> -<source>Multiple...</source> -<target>Multiplo...</target> - <source>Both sides are equal</source> <target>Entrambi i lati sono uguali</target> @@ -1370,6 +1353,12 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Delete right file/folder</source> <target>Cancella file/cartella di destra</target> +<source>Move file on left</source> +<target>Sposta il file a sinistra</target> + +<source>Move file on right</source> +<target>Sposta il file a destra</target> + <source>Overwrite left file/folder with right one</source> <target>Sovrascrivi file/cartella di sinistra con quello di destra</target> @@ -1385,6 +1374,9 @@ Trasferisci file e permessi sulle cartelle (Richiede diritti di Administrator) <source>Copy file attributes only to right</source> <target>Copia i soli attributi file verso destra</target> +<source>Multiple...</source> +<target>Multiplo...</target> + <source>Deleting file %x</source> <target>Eliminazione file %x</target> diff --git a/BUILD/Languages/japanese.lng b/BUILD/Languages/japanese.lng index fb788c8d..b3f3e1d1 100644 --- a/BUILD/Languages/japanese.lng +++ b/BUILD/Languages/japanese.lng @@ -80,7 +80,7 @@ <target>検索</target> <source>Select time span</source> -<target></target> +<target>タイムスパンを選択</target> <source>Show pop-up</source> <target>ポップアップ表示</target> @@ -148,7 +148,7 @@ <target>サイズ</target> <source>Date</source> -<target>データ</target> +<target>日付</target> <source>Full path</source> <target>フルパス</target> @@ -168,15 +168,15 @@ <source>Comparison Result</source> <target>比較結果</target> -<source>Incompatible synchronization database format:</source> -<target>同期データベースの書式に互換性がありません:</target> - <source>Initial synchronization:</source> <target>同期処理の初期化:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>FreeFileSync データベースファイルが存在しません:</target> +<source>Incompatible synchronization database format:</source> +<target>同期データベースの書式に互換性がありません:</target> + <source>Database files do not share a common synchronization session:</source> <target>データベースファイルは一般的な同期セッションを共有しません:</target> @@ -239,7 +239,7 @@ <target>必要なDLLを読み込めません:</target> <source>Error accessing Volume Shadow Copy Service!</source> -<target></target> +<target>ボリュームシャドウ・コピーサービスにアクセス出来ません!</target> <source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> <target>WOW64 では、ボリュームシャドウコピーに対応していません、FreeFileSync 64-bit 版をお試しください。</target> @@ -369,9 +369,6 @@ The command line is executed each time: <source>Batch execution</source> <target>一括処理を実行</target> -<source>Log-messages:</source> -<target>ログメッセージ:</target> - <source>Stop</source> <target>停止</target> @@ -498,6 +495,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>転送されたデータの総量</target> +<source>Operation:</source> +<target>操作:</target> + +<source>Items found:</source> +<target>見つかった要素:</target> + +<source>Items remaining:</source> +<target>残りの要素:</target> + +<source>Speed:</source> +<target>速度:</target> + +<source>Time remaining:</source> +<target>残り時間:</target> + +<source>Time elapsed:</source> +<target>経過時間:</target> + <source>Batch job</source> <target>一括処理</target> @@ -546,32 +561,14 @@ The command line is executed each time: <source>&Cancel</source> <target>キャンセル(&C)</target> -<source>Operation:</source> -<target>操作:</target> - -<source>Items found:</source> -<target>見つかった要素:</target> - -<source>Items remaining:</source> -<target>残りの要素:</target> - -<source>Speed:</source> -<target>速度:</target> - -<source>Time remaining:</source> -<target>残り時間:</target> - -<source>Time elapsed:</source> -<target>経過時間:</target> - <source>Select variant:</source> <target>変数を選択:</target> <source><Automatic></source> <target><自動></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>データベースを使用して、両側アイテムの変更を特定します。 削除、競合は自動的に検出することができます。</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>両側の識別、プロパティの変更特定にデータベースを使用します。削除、リネーム及び競合などは自動的に検出されます</target> <source>Mirror ->></source> <target>ミラー >></target> @@ -790,30 +787,22 @@ Exclude: \stuff\temp\* <target>列を下に移動</target> <source>Transactional file copy</source> -<target>Transactional ファイルコピー</target> +<target>トランザクション・コピーを使用</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> <target>最初に一時ファイル(*.ffs_tmp)に書き込み、それをリネームします。これにより、致命的なエラーが起こっても状態は保証されます</target> <source>Copy locked files</source> -<target>ロックされたファイルをコピー</target> +<target>ロックされたファイルをコピーする</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -ボリュームシャドーコピーを使用して共有/ロックされたファイルをコピー(管理者権限が必要) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>ボリュームシャドーコピーを使用して共有/ロックされたファイルをコピー(管理者権限が必要)</target> <source>Copy file access permissions</source> -<target>ファイルのアクセスパーミッションをコピー</target> +<target>ファイルのアクセスパーミッションをコピーする</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -ファイルとディレクトリのパーミッション転送(管理者権限が必要) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>ファイルとディレクトリのパーミッション転送(管理者権限が必要)</target> <source>Hidden dialogs:</source> <target>ダイアログを隠す</target> @@ -1123,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>フィルター:単一ペア</target> -<source>Ignore</source> -<target>無視</target> - <source>Direct</source> <target>方向</target> @@ -1274,12 +1260,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Error opening file:</source> <target>ファイルのオープンに失敗:</target> -<source>Endless loop when traversing directory:</source> -<target>ディレクトリ移動中に無限ループが発生:</target> - <source>Error traversing directory:</source> <target>ディレクトリの移動エラー:</target> +<source>Endless loop when traversing directory:</source> +<target>ディレクトリ移動中に無限ループが発生:</target> + <source>Error setting privilege:</source> <target>特権の設定エラー:</target> @@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>ディレクトリが依存関係にあります! 同期規則の設定時には注意してください:</target> -<source>Comparing content of files %x</source> -<target>ファイル %x の内容を比較中</target> - <source>Memory allocation failed!</source> <target>メモリ割り当てに失敗!</target> @@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>シンボリックリンク %x の日付は同一ですが、異なる対象があります!</target> +<source>Comparing content of files %x</source> +<target>ファイル %x の内容を比較中</target> + <source>Comparing files by content failed.</source> <target>ファイル内容の比較に失敗しました</target> <source>Generating file list...</source> <target>ファイル一覧を作成中...</target> -<source>Multiple...</source> -<target>複数処理...</target> - <source>Both sides are equal</source> <target>両側とも等しく</target> @@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>右側のファイル/フォルダを削除</target> +<source>Move file on left</source> +<target>ファイルを左に移動</target> + +<source>Move file on right</source> +<target>ファイルを右に移動</target> + <source>Overwrite left file/folder with right one</source> <target>右側のものを左側のファイル/フォルダに上書き</target> @@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>ファイル属性のみ右側にコピー</target> +<source>Multiple...</source> +<target>複数処理...</target> + <source>Deleting file %x</source> <target>ファイル %x を削除中</target> diff --git a/BUILD/Languages/korean.lng b/BUILD/Languages/korean.lng index 561c10cd..653fb7e9 100644 --- a/BUILD/Languages/korean.lng +++ b/BUILD/Languages/korean.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>실시간 동기화 - 자동 동기화</target> -<source>Browse</source> -<target>찾아보기</target> - -<source>Windows Error Code %x:</source> -<target>윈도우 에러 코드 %x:</target> - -<source>Linux Error Code %x:</source> -<target>리눅스 에러 코드 %x:</target> - -<source>Invalid command line: %x</source> -<target>잘못된 명령줄 : %x</target> - -<source>Error resolving symbolic link:</source> -<target>심볼릭 링크를 해결하던 중 발생한 오류 :</target> - -<source>Show pop-up</source> -<target>팝업 보이기</target> - -<source>Show pop-up on errors or warnings</source> -<target>오류 또는 경고에 대한 팝업 보이기</target> - -<source>Ignore errors</source> -<target>오류 무시</target> - -<source>Hide all error and warning messages</source> -<target>모든 오류/경고 메세지 숨기기</target> - -<source>Exit instantly</source> -<target>즉시 종료</target> - -<source>Abort synchronization immediately</source> -<target>동기화 작업 즉시 중단</target> - <source>Select alternate comparison settings</source> <target>대체 비교 설정 선택</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>시간간격(타임스팬) 선택</target> +<source>Show pop-up</source> +<target>팝업 보이기</target> + +<source>Show pop-up on errors or warnings</source> +<target>오류 또는 경고에 대한 팝업 보이기</target> + +<source>Ignore errors</source> +<target>오류 무시</target> + +<source>Hide all error and warning messages</source> +<target>모든 오류/경고 메세지 숨기기</target> + +<source>Exit instantly</source> +<target>즉시 종료</target> + +<source>Abort synchronization immediately</source> +<target>동기화 작업 즉시 중단</target> + +<source>Browse</source> +<target>찾아보기</target> + +<source>Error reading from synchronization database:</source> +<target>동기화 데이터베이스로부터 읽어 들이던 중 발생한 오류 :</target> + +<source>Error writing to synchronization database:</source> +<target>동기화 데이터베이스에 쓰던 중 발생한 오류 :</target> + +<source>Invalid command line: %x</source> +<target>잘못된 명령줄 : %x</target> + +<source>Windows Error Code %x:</source> +<target>윈도우 에러 코드 %x:</target> + +<source>Linux Error Code %x:</source> +<target>리눅스 에러 코드 %x:</target> + +<source>Error resolving symbolic link:</source> +<target>심볼릭 링크를 해결하던 중 발생한 오류 :</target> + <source>%x MB</source> <target>%x MB</target> @@ -162,17 +168,14 @@ <source>Comparison Result</source> <target>비교 결과</target> -<source>Incompatible synchronization database format:</source> -<target>호환되지 않는 동기화 데이터베이스 형식 :</target> - <source>Initial synchronization:</source> <target>초기 동기화 :</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>FreeFileSync 데이터베이스 파일 중 하나가 아직 존재하지 않습니다 :</target> -<source>Error reading from synchronization database:</source> -<target>동기화 데이터베이스로부터 읽어 들이던 중 발생한 오류 :</target> +<source>Incompatible synchronization database format:</source> +<target>호환되지 않는 동기화 데이터베이스 형식 :</target> <source>Database files do not share a common synchronization session:</source> <target>데이터베이스 파일이 공통 동기화 세션을 공유하지 않습니다 :</target> @@ -197,12 +200,18 @@ <pluralform>%x초</pluralform> </target> +<source>Drag && drop</source> +<target>드래그 && 드랍 (마우스로 파일 끌어다 놓기)</target> + <source>Info</source> <target>정보</target> <source>Fatal Error</source> <target>치명적 오류</target> +<source>Error reading file:</source> +<target>파일을 읽던 중 발생한 오류 :</target> + <source>Scanning:</source> <target>스캔 :</target> @@ -220,15 +229,36 @@ <source>Invalid FreeFileSync config file!</source> <target>잘못된 FreeFileSync 설정 파일!</target> -<source>File does not exist:</source> -<target>파일이 존재하지 않습니다 :</target> - <source>Error parsing configuration file:</source> <target>설정파일 분석 중 발생한 오류 :</target> +<source>Error moving to Recycle Bin:</source> +<target>휴지통으로 이동 중 발생한 오류 :</target> + +<source>Could not load a required DLL:</source> +<target>필요한 DLL을 로드할 수 없습니다 :</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>볼륨 섀도 복사본 서비스에 액세스하던 중 오류 발생!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>WOW64 에서의 Shadow Copy 는 지원하지 않습니다. FreeFileSync 64-bit 버전을 사용하세요.</target> + +<source>Could not determine volume name for file:</source> +<target>파일 볼륨 이름을 결정할 수 없습니다 :</target> + +<source>Volume name %x not part of filename %y!</source> +<target>볼륨 이름 %x 이(가) 파일 이름 %y 의 일부가 아닙니다!</target> + <source>/sec</source> <target>/초</target> +<source>File does not exist:</source> +<target>파일이 존재하지 않습니다 :</target> + +<source>Could not read values for the following XML nodes:</source> +<target>다음 XML 노드 값을 읽어 들일 수 없습니다 :</target> + <source>S&ave configuration...</source> <target>설정 저장</target> @@ -321,138 +351,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>디렉토리 입력 필드가 비어 있습니다.</target> -<source>Drag && drop</source> -<target>드래그 && 드랍</target> - -<source>Could not initialize directory monitoring:</source> -<target>디렉토리 모니터링을 초기화 할 수 없습니다 :</target> - -<source>Error when monitoring directories.</source> -<target>디렉토리 모니터링 중 발생한 오류 :</target> - -<source>Conversion error:</source> -<target>변환 오류 :</target> - -<source>Error deleting file:</source> -<target>파일 삭제 중 발생한 오류 :</target> - -<source>Error moving file:</source> -<target>파일 이동 중 발생한 오류 :</target> - -<source>Target file already existing!</source> -<target>대상 파일이 이미 존재합니다!</target> - -<source>Error moving directory:</source> -<target>디렉토리 이동 중 발생한 오류 :</target> - -<source>Target directory already existing!</source> -<target>대상 디렉토리가 이미 존재합니다!</target> - -<source>Error deleting directory:</source> -<target>디렉토리 삭제 중 발생한 오류 :</target> - -<source>Error changing modification time:</source> -<target>시간 수정 중 발생한 오류 :</target> - -<source>Error loading library function:</source> -<target>라이브러리 기능 로드 중 발생한 오류 :</target> - -<source>Error reading security context:</source> -<target>보안 컨텍스트를 읽던 중 발생한 오류 :</target> - -<source>Error writing security context:</source> -<target>보안 컨텍스트를 쓰던 중 발생한 오류 :</target> - -<source>Error copying file permissions:</source> -<target>파일 권한 복사 중 발생한 오류 :</target> - -<source>Error creating directory:</source> -<target>디렉토리 생성 중 발생한 오류 :</target> - -<source>Error copying symbolic link:</source> -<target>심볼릭 링크 복사 중 발생한 오류 :</target> - -<source>Error copying file:</source> -<target>파일 복사 중 발생한 오류 :</target> - -<source>Error opening file:</source> -<target>파일을 열던 중 발생한 오류 :</target> - -<source>Error writing file:</source> -<target>파일을 쓰던 중 발생한 오류 :</target> - -<source>Error reading file:</source> -<target>파일을 읽던 중 발생한 오류 :</target> - -<source>Operation aborted!</source> -<target>작업 중단!</target> - -<source>Endless loop when traversing directory:</source> -<target>디렉토리 이동 중 무한 루프 발생 :</target> - -<source>Error traversing directory:</source> -<target>디렉토리 이동 중 발생한 오류 :</target> - -<source>Error setting privilege:</source> -<target>권한 설정 중 발생한 오류 :</target> - -<source>Error moving to Recycle Bin:</source> -<target>휴지통으로 이동 중 발생한 오류 :</target> - -<source>Could not load a required DLL:</source> -<target>필요한 DLL을 로드할 수 없습니다 :</target> - -<source>Error writing to synchronization database:</source> -<target>동기화 데이터베이스에 쓰던 중 발생한 오류 :</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>볼륨 섀도 복사본 서비스에 액세스하던 중 오류 발생!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>WOW64 에서의 Shadow Copy 는 지원하지 않습니다. FreeFileSync 64-bit 버전을 사용하세요.</target> - -<source>Could not determine volume name for file:</source> -<target>파일 볼륨 이름을 결정할 수 없습니다 :</target> - -<source>Volume name %x not part of filename %y!</source> -<target>볼륨 이름 %x 이(가) 파일 이름 %y 의 일부가 아닙니다!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x분</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x시간</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x일</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>다음 XML 노드 값을 읽어 들일 수 없습니다 :</target> - <source>Logging</source> <target>로그 중</target> @@ -471,9 +369,6 @@ The command line is executed each time: <source>Batch execution</source> <target>일괄 실행</target> -<source>Log-messages:</source> -<target>로그 메세지 :</target> - <source>Stop</source> <target>정지</target> @@ -600,6 +495,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>전송하게 될 전체 데이터 용량</target> +<source>Operation:</source> +<target>작업 :</target> + +<source>Items found:</source> +<target>발견된 요소 :</target> + +<source>Items remaining:</source> +<target>남은 요소 :</target> + +<source>Speed:</source> +<target>속도 :</target> + +<source>Time remaining:</source> +<target>남은 시간 :</target> + +<source>Time elapsed:</source> +<target>경과 시간 :</target> + <source>Batch job</source> <target>일괄 작업</target> @@ -648,32 +561,14 @@ The command line is executed each time: <source>&Cancel</source> <target>취소(&C)</target> -<source>Operation:</source> -<target>작업 :</target> - -<source>Items found:</source> -<target>발견된 요소 :</target> - -<source>Items remaining:</source> -<target>남은 요소 :</target> - -<source>Speed:</source> -<target>속도 :</target> - -<source>Time remaining:</source> -<target>남은 시간 :</target> - -<source>Time elapsed:</source> -<target>경과 시간 :</target> - <source>Select variant:</source> <target>옵션 선택 :</target> <source><Automatic></source> <target><자동></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>데이터베이스를 사용하여, 양측 변경사항을 확인합니다. 삭제 및 충돌 내역은 자동 감지됩니다.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>데이터베이스를 활용하여 양측의 변경사항을 확인하고 반영합니다. 파일 삭제/명칭 변경/충돌은 자동으로 감지됩니다.</target> <source>Mirror ->></source> <target>미러 ->></target> @@ -895,27 +790,19 @@ Exclude: \stuff\temp\* <target>트랜잭션 파일 복사</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>임시 파일 (*.ffs_tmp)로 우선 작성 후, 파일명을 변경합니다. 이러면 치명적인 오류가 발생하더라도 일관된 상태를 보장할 수 있습니다.</target> <source>Copy locked files</source> <target>락 걸린 파일 복사</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Volume Shadow Copy를 사용하여 공유 또는 락 걸린 파일을 복사 (관리자 권한 필요) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Volume Shadow Copy를 사용하여 공유 또는 락 걸린 파일을 복사 (관리자 권한 필요)</target> <source>Copy file access permissions</source> <target>파일 접근 권한 복사</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -파일 및 디렉토리 권한 전송 (관리자 권한이 필요함) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>파일 및 디렉토리 권한 전송 (관리자 권한이 필요함)</target> <source>Hidden dialogs:</source> <target>다이얼로그 숨기기</target> @@ -947,6 +834,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>다음 검색(&F)</target> +<source>Operation aborted!</source> +<target>작업 중단!</target> + <source>Main bar</source> <target>메인 바</target> @@ -987,16 +877,16 @@ Transfer file and directory permissions (Requires Administrator rights) <target>열 자동정렬</target> <source>Icon size:</source> -<target></target> +<target>아이콘 크기</target> <source>Small</source> -<target></target> +<target>작게</target> <source>Medium</source> -<target></target> +<target>중간</target> <source>Large</source> -<target></target> +<target>크게</target> <source>Include all rows</source> <target>모든 행 포함</target> @@ -1124,6 +1014,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>파일 리스트 내보내기 완료!</target> +<source>Error writing file:</source> +<target>파일을 쓰던 중 발생한 오류 :</target> + <source>Batch file created successfully!</source> <target>일괄 파일이 성공적으로 생성 됐습니다!</target> @@ -1219,9 +1112,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>필터 : 단일 페어(짝)</target> -<source>Ignore</source> -<target>무시</target> - <source>Direct</source> <target>다이렉트</target> @@ -1283,6 +1173,102 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>파일을 타임스탬프 된 서브 폴더로 이동</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x분</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x시간</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x일</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>디렉토리 모니터링을 초기화 할 수 없습니다 :</target> + +<source>Error when monitoring directories.</source> +<target>디렉토리 모니터링 중 발생한 오류 :</target> + +<source>Conversion error:</source> +<target>변환 오류 :</target> + +<source>Error deleting file:</source> +<target>파일 삭제 중 발생한 오류 :</target> + +<source>Error moving file:</source> +<target>파일 이동 중 발생한 오류 :</target> + +<source>Target file already existing!</source> +<target>대상 파일이 이미 존재합니다!</target> + +<source>Error moving directory:</source> +<target>디렉토리 이동 중 발생한 오류 :</target> + +<source>Target directory already existing!</source> +<target>대상 디렉토리가 이미 존재합니다!</target> + +<source>Error deleting directory:</source> +<target>디렉토리 삭제 중 발생한 오류 :</target> + +<source>Error changing modification time:</source> +<target>시간 수정 중 발생한 오류 :</target> + +<source>Error loading library function:</source> +<target>라이브러리 기능 로드 중 발생한 오류 :</target> + +<source>Error reading security context:</source> +<target>보안 컨텍스트를 읽던 중 발생한 오류 :</target> + +<source>Error writing security context:</source> +<target>보안 컨텍스트를 쓰던 중 발생한 오류 :</target> + +<source>Error copying file permissions:</source> +<target>파일 권한 복사 중 발생한 오류 :</target> + +<source>Error creating directory:</source> +<target>디렉토리 생성 중 발생한 오류 :</target> + +<source>Error copying symbolic link:</source> +<target>심볼릭 링크 복사 중 발생한 오류 :</target> + +<source>Error copying file:</source> +<target>파일 복사 중 발생한 오류 :</target> + +<source>Error opening file:</source> +<target>파일을 열던 중 발생한 오류 :</target> + +<source>Error traversing directory:</source> +<target>디렉토리 이동 중 발생한 오류 :</target> + +<source>Endless loop when traversing directory:</source> +<target>디렉토리 이동 중 무한 루프 발생 :</target> + +<source>Error setting privilege:</source> +<target>권한 설정 중 발생한 오류 :</target> + <source>Both sides have changed since last synchronization!</source> <target>마지막 동기화 작업 이후, 양측 모두 변경 되었습니다!</target> @@ -1313,9 +1299,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>디렉토리가 의존 관계에 있습니다. 동기화 규칙 설정시 주의하십시오.</target> -<source>Comparing content of files %x</source> -<target>파일 %x 내용 별 비교 중</target> - <source>Memory allocation failed!</source> <target>메모리 할당 실패!</target> @@ -1331,15 +1314,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>심링크 %x 의 날짜는 같으나, 대상이 다릅니다!</target> +<source>Comparing content of files %x</source> +<target>파일 %x 내용 별 비교 중</target> + <source>Comparing files by content failed.</source> <target>내용 별 파일 비교 실패</target> <source>Generating file list...</source> <target>파일 리스트 생성 중...</target> -<source>Multiple...</source> -<target>다중처리 (멀티플) 작업...</target> - <source>Both sides are equal</source> <target>양측이 같음</target> @@ -1358,6 +1341,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>우측 파일/폴더 삭제</target> +<source>Move file on left</source> +<target>좌측 파일 이동</target> + +<source>Move file on right</source> +<target>우측 파일 이동</target> + <source>Overwrite left file/folder with right one</source> <target>우측 파일/폴더로 좌측 파일/폴더 덮어쓰기</target> @@ -1373,6 +1362,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>파일 속성만 우측으로 복사</target> +<source>Multiple...</source> +<target>다중처리 (멀티플) 작업...</target> + <source>Deleting file %x</source> <target>파일 %x 삭제 중</target> diff --git a/BUILD/Languages/polish.lng b/BUILD/Languages/polish.lng index 6ce2e79b..5c874c53 100644 --- a/BUILD/Languages/polish.lng +++ b/BUILD/Languages/polish.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Automatyczna Synchronizacja</target> -<source>Browse</source> -<target>Przeglądaj</target> - -<source>Windows Error Code %x:</source> -<target>Błąd systemu Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Błąd systemu linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Nieprawidłowa komenda: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Błąd odczytu dowiązania symbolicznego:</target> - -<source>Show pop-up</source> -<target>Pokazuj okna pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Pokazuj okna pop-up dla błędów i ostrzeżeń</target> - -<source>Ignore errors</source> -<target>Ignoruj błędy</target> - -<source>Hide all error and warning messages</source> -<target>Ukryj wszystkie informacje błędach i ostrzeżeniach</target> - -<source>Exit instantly</source> -<target>Wyjdź natychmiast</target> - -<source>Abort synchronization immediately</source> -<target>Natychmiast zakończ synchronizację</target> - <source>Select alternate comparison settings</source> <target>Określ alternatywne ustawienia porównywania</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Określ przedział czasowy</target> +<source>Show pop-up</source> +<target>Pokazuj okna pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Pokazuj okna pop-up dla błędów i ostrzeżeń</target> + +<source>Ignore errors</source> +<target>Ignoruj błędy</target> + +<source>Hide all error and warning messages</source> +<target>Ukryj wszystkie informacje błędach i ostrzeżeniach</target> + +<source>Exit instantly</source> +<target>Wyjdź natychmiast</target> + +<source>Abort synchronization immediately</source> +<target>Natychmiast zakończ synchronizację</target> + +<source>Browse</source> +<target>Przeglądaj</target> + +<source>Error reading from synchronization database:</source> +<target>Błąd odczytu z bazy danych synchronizacji:</target> + +<source>Error writing to synchronization database:</source> +<target>Błąd zapisu do bazy danych synchronizacji:</target> + +<source>Invalid command line: %x</source> +<target>Nieprawidłowa komenda: %x</target> + +<source>Windows Error Code %x:</source> +<target>Błąd systemu Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Błąd systemu linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Błąd odczytu dowiązania symbolicznego:</target> + <source>%x MB</source> <target>%x MB</target> @@ -164,17 +170,14 @@ <source>Comparison Result</source> <target>Rezultat porównywania</target> -<source>Incompatible synchronization database format:</source> -<target>Niepoprawny format bazy danych dla synchronizacji:</target> - <source>Initial synchronization:</source> <target>Wstępna synchronizacja:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Jeden z plików bazy danych FreeFileSync nie istnieje:</target> -<source>Error reading from synchronization database:</source> -<target>Błąd odczytu z bazy danych synchronizacji:</target> +<source>Incompatible synchronization database format:</source> +<target>Niepoprawny format bazy danych dla synchronizacji:</target> <source>Database files do not share a common synchronization session:</source> <target>Pliki danych nie współdzielą wspólnej sesji synchronizacji:</target> @@ -201,12 +204,18 @@ <pluralform>%x sekund</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && Drop</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Błąd krytyczny</target> +<source>Error reading file:</source> +<target>Błąd odczytu pliku:</target> + <source>Scanning:</source> <target>Skanowanie:</target> @@ -226,15 +235,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Nieprawidłowy plik konfiguracyjny!</target> -<source>File does not exist:</source> -<target>Plik nie istnieje:</target> - <source>Error parsing configuration file:</source> <target>Błąd parsowania pliku konfiguracyjnego:</target> +<source>Error moving to Recycle Bin:</source> +<target>Błąd podczas przenoszenia do kosza:</target> + +<source>Could not load a required DLL:</source> +<target>Nie można załadować wymaganej biblioteki DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Błąd podczas dostępdu do usługi Volume Shadow Copy!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Tworzenie Shadow Copies dla WOW64 nie jest obsługiwane. Zainstaluj 64 bitową wersję FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Nie można określić nazwy dysku dla pliku:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Dysk %x nie jest częścią pliku %y!</target> + <source>/sec</source> <target>/sekundę</target> +<source>File does not exist:</source> +<target>Plik nie istnieje:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Nie można odczytać wartości dla danych gałęzi XML:</target> + <source>S&ave configuration...</source> <target>Z&apisz konfigurację...</target> @@ -327,144 +357,6 @@ Komenda jest wykonwywana za każdym razem gdy: <source>A directory input field is empty.</source> <target>Pole ze ścieżką katalogu jest puste.</target> -<source>Drag && drop</source> -<target>Drag && Drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Nie można uruchomić monitora katalogów:</target> - -<source>Error when monitoring directories.</source> -<target>Błąd podczas monitorowania katalogów.</target> - -<source>Conversion error:</source> -<target>Błąd konwersji:</target> - -<source>Error deleting file:</source> -<target>Błąd podczas usuwania pliku:</target> - -<source>Error moving file:</source> -<target>Błąd podczas przenoszenia pliku:</target> - -<source>Target file already existing!</source> -<target>Plik docelowy już istnieje!</target> - -<source>Error moving directory:</source> -<target>Błąd podczas przenoszenia katalogu:</target> - -<source>Target directory already existing!</source> -<target>Katalog docelowy już istnieje!</target> - -<source>Error deleting directory:</source> -<target>Błąd podczas usuwania katalogu:</target> - -<source>Error changing modification time:</source> -<target>Błąd zmiany godziny modyfikacji:</target> - -<source>Error loading library function:</source> -<target>Błąd wczytywania funkcji:</target> - -<source>Error reading security context:</source> -<target>Błąd odczytu kontekstu bezpieczeństwa:</target> - -<source>Error writing security context:</source> -<target>Błąd zapisu kontekstu bezpieczeństwa:</target> - -<source>Error copying file permissions:</source> -<target>Błąd podczas kopiowania uprawnień pliku:</target> - -<source>Error creating directory:</source> -<target>Błąd podczas tworzenia katalogu:</target> - -<source>Error copying symbolic link:</source> -<target>Błąd podczas kopiowania dowiązania symbolicznego (symlink)</target> - -<source>Error copying file:</source> -<target>Błąd podczas kopiowania pliku:</target> - -<source>Error opening file:</source> -<target>Błąd odczytu pliku:</target> - -<source>Error writing file:</source> -<target>Błąd zapisu pliku:</target> - -<source>Error reading file:</source> -<target>Błąd odczytu pliku:</target> - -<source>Operation aborted!</source> -<target>Operacja przerwana!</target> - -<source>Endless loop when traversing directory:</source> -<target>Zapętlenie podczas przeglądania katalogu:</target> - -<source>Error traversing directory:</source> -<target>Błąd podczas odczytywania katalogu:</target> - -<source>Error setting privilege:</source> -<target>Błąd ustawiania uprawnień:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Błąd podczas przenoszenia do kosza:</target> - -<source>Could not load a required DLL:</source> -<target>Nie można załadować wymaganej biblioteki DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Błąd zapisu do bazy danych synchronizacji:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Błąd podczas dostępdu do usługi Volume Shadow Copy!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Tworzenie Shadow Copies dla WOW64 nie jest obsługiwane. Zainstaluj 64 bitową wersję FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Nie można określić nazwy dysku dla pliku:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Dysk %x nie jest częścią pliku %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 minuta</pluralform> -<pluralform>%x minuty</pluralform> -<pluralform>%x minut</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 godzina</pluralform> -<pluralform>%x godziny</pluralform> -<pluralform>%x godzin</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dzień</pluralform> -<pluralform>%x dni</pluralform> -<pluralform>%x dni</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Nie można odczytać wartości dla danych gałęzi XML:</target> - <source>Logging</source> <target>Tworzenie logów</target> @@ -483,9 +375,6 @@ Komenda jest wykonwywana za każdym razem gdy: <source>Batch execution</source> <target>Uruchomienie pliku wsadowego</target> -<source>Log-messages:</source> -<target>Logi:</target> - <source>Stop</source> <target>Zatrzymaj</target> @@ -612,6 +501,24 @@ Komenda jest wykonwywana za każdym razem gdy: <source>Total amount of data that will be transferred</source> <target>Liczba danych do przekopiowania</target> +<source>Operation:</source> +<target>Operacja:</target> + +<source>Items found:</source> +<target>Znalezione elementy:</target> + +<source>Items remaining:</source> +<target>Pozostałe elementy:</target> + +<source>Speed:</source> +<target>Prędkość:</target> + +<source>Time remaining:</source> +<target>Pozostały czas:</target> + +<source>Time elapsed:</source> +<target>Czas:</target> + <source>Batch job</source> <target>Plik wsadowy</target> @@ -660,32 +567,14 @@ Komenda jest wykonwywana za każdym razem gdy: <source>&Cancel</source> <target>&Anuluj</target> -<source>Operation:</source> -<target>Operacja:</target> - -<source>Items found:</source> -<target>Znalezione elementy:</target> - -<source>Items remaining:</source> -<target>Pozostałe elementy:</target> - -<source>Speed:</source> -<target>Prędkość:</target> - -<source>Time remaining:</source> -<target>Pozostały czas:</target> - -<source>Time elapsed:</source> -<target>Czas:</target> - <source>Select variant:</source> <target>Wybierz wariant:</target> <source><Automatic></source> <target><Automatycznie></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Wykryj i zastosuj zmiany po obu stronach używając bazy danych. Usunięcia i konflikty są wykrywane automatycznie.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Znajdź i zastosuj zmiany po obu stronach przy pomocy bazy danych. Usunięnia, zmiany nazwy plików oraz konflikty są usuwane automatycznie.</target> <source>Mirror ->></source> <target>Lustrzana ->></target> @@ -907,27 +796,19 @@ Wyklucz: \moje\temp\* <target>Transakcyjne kopiowanie pliku</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Stwórz tymczasowy plik (*.ffs_tmp) następnie zamień jego nazwę. Gwarantuje to spójność nawet po wystąpieniu błędu.</target> <source>Copy locked files</source> <target>Kopiuj zablokowane pliki</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopiuj pliki udostępnione i zablokowane używając usługi Volume Shadow Copy (Wymaga uprawnień administratora) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopiuj pliki udostępnione i zablokowane używając usługi Volume Shadow Copy (Wymaga uprawnień administratora)</target> <source>Copy file access permissions</source> <target>Kopiuj uprawnienia plików</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora)</target> <source>Hidden dialogs:</source> <target>Ukryte dialogi:</target> @@ -959,6 +840,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>&Find next</source> <target>&Znajdź następny</target> +<source>Operation aborted!</source> +<target>Operacja przerwana!</target> + <source>Main bar</source> <target>Główny pasek</target> @@ -999,16 +883,16 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <target>Autodopasowanie kolumn</target> <source>Icon size:</source> -<target></target> +<target>Rozmiar ikony:</target> <source>Small</source> -<target></target> +<target>Mały</target> <source>Medium</source> -<target></target> +<target>Średni</target> <source>Large</source> -<target></target> +<target>Duży</target> <source>Include all rows</source> <target>Dołącz wszystkie rzędy</target> @@ -1136,6 +1020,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>File list exported!</source> <target>Lista plików wyeksportowana!</target> +<source>Error writing file:</source> +<target>Błąd zapisu pliku:</target> + <source>Batch file created successfully!</source> <target>Plik wsadowy utworzony pomyślnie!</target> @@ -1239,9 +1126,6 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Filter: Single pair</source> <target>Filtr: Pojedyńcza para</target> -<source>Ignore</source> -<target>Ignoruj</target> - <source>Direct</source> <target>Bezpośrednio</target> @@ -1307,6 +1191,108 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Move files into a time-stamped subdirectory</source> <target>Przenieś pliki do oznaczonego podkatalogu</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 minuta</pluralform> +<pluralform>%x minuty</pluralform> +<pluralform>%x minut</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 godzina</pluralform> +<pluralform>%x godziny</pluralform> +<pluralform>%x godzin</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dzień</pluralform> +<pluralform>%x dni</pluralform> +<pluralform>%x dni</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Nie można uruchomić monitora katalogów:</target> + +<source>Error when monitoring directories.</source> +<target>Błąd podczas monitorowania katalogów.</target> + +<source>Conversion error:</source> +<target>Błąd konwersji:</target> + +<source>Error deleting file:</source> +<target>Błąd podczas usuwania pliku:</target> + +<source>Error moving file:</source> +<target>Błąd podczas przenoszenia pliku:</target> + +<source>Target file already existing!</source> +<target>Plik docelowy już istnieje!</target> + +<source>Error moving directory:</source> +<target>Błąd podczas przenoszenia katalogu:</target> + +<source>Target directory already existing!</source> +<target>Katalog docelowy już istnieje!</target> + +<source>Error deleting directory:</source> +<target>Błąd podczas usuwania katalogu:</target> + +<source>Error changing modification time:</source> +<target>Błąd zmiany godziny modyfikacji:</target> + +<source>Error loading library function:</source> +<target>Błąd wczytywania funkcji:</target> + +<source>Error reading security context:</source> +<target>Błąd odczytu kontekstu bezpieczeństwa:</target> + +<source>Error writing security context:</source> +<target>Błąd zapisu kontekstu bezpieczeństwa:</target> + +<source>Error copying file permissions:</source> +<target>Błąd podczas kopiowania uprawnień pliku:</target> + +<source>Error creating directory:</source> +<target>Błąd podczas tworzenia katalogu:</target> + +<source>Error copying symbolic link:</source> +<target>Błąd podczas kopiowania dowiązania symbolicznego (symlink)</target> + +<source>Error copying file:</source> +<target>Błąd podczas kopiowania pliku:</target> + +<source>Error opening file:</source> +<target>Błąd odczytu pliku:</target> + +<source>Error traversing directory:</source> +<target>Błąd podczas odczytywania katalogu:</target> + +<source>Endless loop when traversing directory:</source> +<target>Zapętlenie podczas przeglądania katalogu:</target> + +<source>Error setting privilege:</source> +<target>Błąd ustawiania uprawnień:</target> + <source>Both sides have changed since last synchronization!</source> <target>Obie strony uległy zmianie od ostatniej synchronizacji!</target> @@ -1337,9 +1323,6 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Katalogi są zależne! Pamiętaj o tym podczas ustawiania zasad synchronizacji:</target> -<source>Comparing content of files %x</source> -<target>Porównywanie zawartości plików %x</target> - <source>Memory allocation failed!</source> <target>Błąd alokacji zasobów!</target> @@ -1355,15 +1338,15 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Symlinks %x have the same date but a different target!</source> <target>Dowiązanie symboliczne %x ma te same dane, ale inny cel!</target> +<source>Comparing content of files %x</source> +<target>Porównywanie zawartości plików %x</target> + <source>Comparing files by content failed.</source> <target>Porównywanie przez zawartość zakończone niepowodzeniem.</target> <source>Generating file list...</source> <target>Generowanie listy plików...</target> -<source>Multiple...</source> -<target>Wiele...</target> - <source>Both sides are equal</source> <target>Obie strony są równe</target> @@ -1382,6 +1365,12 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Delete right file/folder</source> <target>Usuń plik/katalog po prawej stronie</target> +<source>Move file on left</source> +<target>Przenieś plik na lewą stronę</target> + +<source>Move file on right</source> +<target>Przenieś plik na prawą stronę</target> + <source>Overwrite left file/folder with right one</source> <target>Nadpisz plik/katalog po lewej stronie tym po prawej</target> @@ -1397,6 +1386,9 @@ Transfer uprawnień plików i katalogów (Wymaga uprawnień Administratora) <source>Copy file attributes only to right</source> <target>Kopiuj atrybuty plików tylko na prawą stronę</target> +<source>Multiple...</source> +<target>Wiele...</target> + <source>Deleting file %x</source> <target>Usuwanie pliku %x</target> diff --git a/BUILD/Languages/portuguese.lng b/BUILD/Languages/portuguese.lng index 97603be2..a108cdc3 100644 --- a/BUILD/Languages/portuguese.lng +++ b/BUILD/Languages/portuguese.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Sincronização Automática</target> -<source>Browse</source> -<target>Procurar</target> - -<source>Windows Error Code %x:</source> -<target>Código de erro do Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Código de erro do Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Linha de comando inválida: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Erro na resolução do link simbólico:</target> - -<source>Show pop-up</source> -<target>Mostrar popup</target> - -<source>Show pop-up on errors or warnings</source> -<target>Mostrar popup em caso de erros ou avisos</target> - -<source>Ignore errors</source> -<target>Ignorar erros</target> - -<source>Hide all error and warning messages</source> -<target>Ocultar todas as mensagens de erro/aviso</target> - -<source>Exit instantly</source> -<target>Sair imediatamente</target> - -<source>Abort synchronization immediately</source> -<target>Abortar sincronização imediatamente</target> - <source>Select alternate comparison settings</source> <target>Selecionar opções alternativas de comparação</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Selecionar intervalo de tempo</target> +<source>Show pop-up</source> +<target>Mostrar popup</target> + +<source>Show pop-up on errors or warnings</source> +<target>Mostrar popup em caso de erros ou avisos</target> + +<source>Ignore errors</source> +<target>Ignorar erros</target> + +<source>Hide all error and warning messages</source> +<target>Ocultar todas as mensagens de erro/aviso</target> + +<source>Exit instantly</source> +<target>Sair imediatamente</target> + +<source>Abort synchronization immediately</source> +<target>Abortar sincronização imediatamente</target> + +<source>Browse</source> +<target>Procurar</target> + +<source>Error reading from synchronization database:</source> +<target>Erro ao ler a base de dados de sincronização:</target> + +<source>Error writing to synchronization database:</source> +<target>Erro na escrita da base de dados de sincronização:</target> + +<source>Invalid command line: %x</source> +<target>Linha de comando inválida: %x</target> + +<source>Windows Error Code %x:</source> +<target>Código de erro do Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Código de erro do Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Erro na resolução do link simbólico:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Resultados da comparação</target> -<source>Incompatible synchronization database format:</source> -<target>Formato de base de dados de sincronização incompatível:</target> - <source>Initial synchronization:</source> <target>Sincronização inicial:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Um dos ficheiros da base de dados não existe:</target> -<source>Error reading from synchronization database:</source> -<target>Erro ao ler a base de dados de sincronização:</target> +<source>Incompatible synchronization database format:</source> +<target>Formato de base de dados de sincronização incompatível:</target> <source>Database files do not share a common synchronization session:</source> <target>Bases de dados não partilham a mesma sessão de sincronização:</target> @@ -199,12 +202,18 @@ <pluralform>%x segs</pluralform> </target> +<source>Drag && drop</source> +<target>Arrastar && Largar</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Erro crítico</target> +<source>Error reading file:</source> +<target>Erro de leitura de ficheiro:</target> + <source>Scanning:</source> <target>A pesquisar:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Ficheiro de configuração inválido!</target> -<source>File does not exist:</source> -<target>O ficheiro não existe:</target> - <source>Error parsing configuration file:</source> <target>Erro de leitura do ficheiro de configuração:</target> +<source>Error moving to Recycle Bin:</source> +<target>Erro ao mover para a Reciclagem:</target> + +<source>Could not load a required DLL:</source> +<target>Não foi possível carregar a DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Erro no acesso ao serviço Volume Shadow Copy!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Fazer cópias fantasma em WOW64 não é suportado. Por favor usar a versão 64-bit.</target> + +<source>Could not determine volume name for file:</source> +<target>Não é possível determinar o nome do volume para o ficheiro:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Nome do volume %x não faz parte do ficheiro %y!</target> + <source>/sec</source> <target>/seg</target> +<source>File does not exist:</source> +<target>O ficheiro não existe:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Não foi possível ler os valores dos seguintes nós XML:</target> + <source>S&ave configuration...</source> <target>G&uardar a configuração...</target> @@ -324,141 +354,6 @@ A linha de comandos é executada cada vez que: <source>A directory input field is empty.</source> <target>Um campo de directório está vazio.</target> -<source>Drag && drop</source> -<target>Arrastar && Largar</target> - -<source>Could not initialize directory monitoring:</source> -<target>Não é possível iniciar monitorização do directório:</target> - -<source>Error when monitoring directories.</source> -<target>Erro ao monitorizar os directórios.</target> - -<source>Conversion error:</source> -<target>Erro de conversão:</target> - -<source>Error deleting file:</source> -<target>Erro ao eliminar o ficheiro:</target> - -<source>Error moving file:</source> -<target>Erro ao mover o ficheiro:</target> - -<source>Target file already existing!</source> -<target>Ficheiro de destino já existe!</target> - -<source>Error moving directory:</source> -<target>Erro ao mover o directório:</target> - -<source>Target directory already existing!</source> -<target>Directório de destino já existe!</target> - -<source>Error deleting directory:</source> -<target>Erro ao eliminar a pasta:</target> - -<source>Error changing modification time:</source> -<target>Erro ao mudar a hora de modificação:</target> - -<source>Error loading library function:</source> -<target>Erro ao carregar a livraria:</target> - -<source>Error reading security context:</source> -<target>Erro ao ler contexto de segurança:</target> - -<source>Error writing security context:</source> -<target>Erro de escrita no contexto de segurança:</target> - -<source>Error copying file permissions:</source> -<target>Erro ao copiar permissões dos ficheiros:</target> - -<source>Error creating directory:</source> -<target>Erro ao criar a pasta:</target> - -<source>Error copying symbolic link:</source> -<target>Erro ao copiar o link:</target> - -<source>Error copying file:</source> -<target>Erro ao copiar ficheiro:</target> - -<source>Error opening file:</source> -<target>Erro ao abrir ficheiro:</target> - -<source>Error writing file:</source> -<target>Erro de escrita no ficheiro:</target> - -<source>Error reading file:</source> -<target>Erro de leitura de ficheiro:</target> - -<source>Operation aborted!</source> -<target>Operação abortada!</target> - -<source>Endless loop when traversing directory:</source> -<target>Loop infinito ao percorrer directório:</target> - -<source>Error traversing directory:</source> -<target>Erro ao percorrer a pasta:</target> - -<source>Error setting privilege:</source> -<target>Erro ao estabelecer privilégios:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Erro ao mover para a Reciclagem:</target> - -<source>Could not load a required DLL:</source> -<target>Não foi possível carregar a DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Erro na escrita da base de dados de sincronização:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Erro no acesso ao serviço Volume Shadow Copy!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Fazer cópias fantasma em WOW64 não é suportado. Por favor usar a versão 64-bit.</target> - -<source>Could not determine volume name for file:</source> -<target>Não é possível determinar o nome do volume para o ficheiro:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Nome do volume %x não faz parte do ficheiro %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x mins</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 hora</pluralform> -<pluralform>%x horas</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dia</pluralform> -<pluralform>%x dias</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Não foi possível ler os valores dos seguintes nós XML:</target> - <source>Logging</source> <target>A escrever em log</target> @@ -477,9 +372,6 @@ A linha de comandos é executada cada vez que: <source>Batch execution</source> <target>Execução do batch</target> -<source>Log-messages:</source> -<target>Log de mensagens:</target> - <source>Stop</source> <target>Parar</target> @@ -606,6 +498,24 @@ A linha de comandos é executada cada vez que: <source>Total amount of data that will be transferred</source> <target>Volume de dados a ser transferido</target> +<source>Operation:</source> +<target>Operação:</target> + +<source>Items found:</source> +<target>Elementos encontrados:</target> + +<source>Items remaining:</source> +<target>Elementos restantes:</target> + +<source>Speed:</source> +<target>Velocidade:</target> + +<source>Time remaining:</source> +<target>Tempo restante:</target> + +<source>Time elapsed:</source> +<target>Tempo passado:</target> + <source>Batch job</source> <target>Ficheiro Batch</target> @@ -654,32 +564,14 @@ A linha de comandos é executada cada vez que: <source>&Cancel</source> <target>&Cancelar</target> -<source>Operation:</source> -<target>Operação:</target> - -<source>Items found:</source> -<target>Elementos encontrados:</target> - -<source>Items remaining:</source> -<target>Elementos restantes:</target> - -<source>Speed:</source> -<target>Velocidade:</target> - -<source>Time remaining:</source> -<target>Tempo restante:</target> - -<source>Time elapsed:</source> -<target>Tempo passado:</target> - <source>Select variant:</source> <target>Selecione uma variante:</target> <source><Automatic></source> <target><Automático></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identificar e propagar as mudanças usando base de dados. Eliminações e conflitos serão detectados automaticamente.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target></target> <source>Mirror ->></source> <target>Espelhar ->></target> @@ -905,22 +797,14 @@ Excluir: \stuff\temp\* <source>Copy locked files</source> <target>Copiar ficheiros bloqueados</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy (Requer direitos de administrador) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy (Requer direitos de administrador)</target> <source>Copy file access permissions</source> <target>Copiar permissões de acesso do ficheiro</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transferir ficheiro e permissões (Requer direitos de administrador) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transferir ficheiro e permissões (Requer direitos de administrador)</target> <source>Hidden dialogs:</source> <target>Diálogos ocultos:</target> @@ -952,6 +836,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>&Find next</source> <target>&Procurar seguinte</target> +<source>Operation aborted!</source> +<target>Operação abortada!</target> + <source>Main bar</source> <target>Barra principal</target> @@ -1129,6 +1016,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>File list exported!</source> <target>Lista dos ficheiros exportada!</target> +<source>Error writing file:</source> +<target>Erro de escrita no ficheiro:</target> + <source>Batch file created successfully!</source> <target>Ficheiro batch criado com sucesso!</target> @@ -1228,9 +1118,6 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Filter: Single pair</source> <target>Filtro: Par simples</target> -<source>Ignore</source> -<target>Ignorar</target> - <source>Direct</source> <target>Direto</target> @@ -1294,6 +1181,105 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Move files into a time-stamped subdirectory</source> <target>Mover ficheiros para uma subpasta datada</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x mins</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 hora</pluralform> +<pluralform>%x horas</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dia</pluralform> +<pluralform>%x dias</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Não é possível iniciar monitorização do directório:</target> + +<source>Error when monitoring directories.</source> +<target>Erro ao monitorizar os directórios.</target> + +<source>Conversion error:</source> +<target>Erro de conversão:</target> + +<source>Error deleting file:</source> +<target>Erro ao eliminar o ficheiro:</target> + +<source>Error moving file:</source> +<target>Erro ao mover o ficheiro:</target> + +<source>Target file already existing!</source> +<target>Ficheiro de destino já existe!</target> + +<source>Error moving directory:</source> +<target>Erro ao mover o directório:</target> + +<source>Target directory already existing!</source> +<target>Directório de destino já existe!</target> + +<source>Error deleting directory:</source> +<target>Erro ao eliminar a pasta:</target> + +<source>Error changing modification time:</source> +<target>Erro ao mudar a hora de modificação:</target> + +<source>Error loading library function:</source> +<target>Erro ao carregar a livraria:</target> + +<source>Error reading security context:</source> +<target>Erro ao ler contexto de segurança:</target> + +<source>Error writing security context:</source> +<target>Erro de escrita no contexto de segurança:</target> + +<source>Error copying file permissions:</source> +<target>Erro ao copiar permissões dos ficheiros:</target> + +<source>Error creating directory:</source> +<target>Erro ao criar a pasta:</target> + +<source>Error copying symbolic link:</source> +<target>Erro ao copiar o link:</target> + +<source>Error copying file:</source> +<target>Erro ao copiar ficheiro:</target> + +<source>Error opening file:</source> +<target>Erro ao abrir ficheiro:</target> + +<source>Error traversing directory:</source> +<target>Erro ao percorrer a pasta:</target> + +<source>Endless loop when traversing directory:</source> +<target>Loop infinito ao percorrer directório:</target> + +<source>Error setting privilege:</source> +<target>Erro ao estabelecer privilégios:</target> + <source>Both sides have changed since last synchronization!</source> <target>Ambos os lados tiveram alterações desde a última sincronização!</target> @@ -1324,9 +1310,6 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Directórios são dependentes! Cuidado ao definir as regras de sincronização:</target> -<source>Comparing content of files %x</source> -<target>A comparar o conteúdo do ficheiro %x</target> - <source>Memory allocation failed!</source> <target>Alocação de memória falhou!</target> @@ -1342,15 +1325,15 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Symlinks %x have the same date but a different target!</source> <target>Links simbólicos %x tem a mesma data mas diferente destino!</target> +<source>Comparing content of files %x</source> +<target>A comparar o conteúdo do ficheiro %x</target> + <source>Comparing files by content failed.</source> <target>A comparação de ficheiros por conteúdo falhou.</target> <source>Generating file list...</source> <target>A gerar lista ficheiros...</target> -<source>Multiple...</source> -<target>Multiplo...</target> - <source>Both sides are equal</source> <target>Ambos os lados iguais</target> @@ -1369,6 +1352,12 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Delete right file/folder</source> <target>Eliminar ficheiro/pasta à direita</target> +<source>Move file on left</source> +<target></target> + +<source>Move file on right</source> +<target></target> + <source>Overwrite left file/folder with right one</source> <target>Substituir ficheiro/pasta da esquerda (pelo da direita)</target> @@ -1384,6 +1373,9 @@ Transferir ficheiro e permissões (Requer direitos de administrador) <source>Copy file attributes only to right</source> <target>Copiar apenas atributos de ficheiro para a direita</target> +<source>Multiple...</source> +<target>Multiplo...</target> + <source>Deleting file %x</source> <target>Apagar ficheiro %x</target> diff --git a/BUILD/Languages/portuguese_br.lng b/BUILD/Languages/portuguese_br.lng index 5489adeb..b6ec4d95 100644 --- a/BUILD/Languages/portuguese_br.lng +++ b/BUILD/Languages/portuguese_br.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Sincronização Automatizada</target> -<source>Browse</source> -<target>Procurar</target> - -<source>Windows Error Code %x:</source> -<target>Código de Erro do Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Código de Erro do Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Linha de comando inválida: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Erro na resolução de link simbólico:</target> - -<source>Show pop-up</source> -<target>Mostrar pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Mostrar pop-up em erros e avisos</target> - -<source>Ignore errors</source> -<target>Ignorar erros</target> - -<source>Hide all error and warning messages</source> -<target>Ocultar todas as mensagens de erro ou aviso</target> - -<source>Exit instantly</source> -<target>Sair instantaneamente</target> - -<source>Abort synchronization immediately</source> -<target>Cancelar a sincronização imediatamente</target> - <source>Select alternate comparison settings</source> <target>Selecionar configuração de comparação alternativa</target> @@ -89,7 +56,7 @@ <target>Erro</target> <source>Warning</source> -<target>Atenção</target> +<target>Avisos</target> <source>Question</source> <target>Questão</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Selecionar período de tempo</target> +<source>Show pop-up</source> +<target>Mostrar pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Mostrar pop-up em erros e avisos</target> + +<source>Ignore errors</source> +<target>Ignorar erros</target> + +<source>Hide all error and warning messages</source> +<target>Ocultar todas as mensagens de erro ou aviso</target> + +<source>Exit instantly</source> +<target>Sair instantaneamente</target> + +<source>Abort synchronization immediately</source> +<target>Cancelar a sincronização imediatamente</target> + +<source>Browse</source> +<target>Procurar</target> + +<source>Error reading from synchronization database:</source> +<target>Erro ao ler do banco de dados de sincronização:</target> + +<source>Error writing to synchronization database:</source> +<target>Erro ao escrever no banco de dados de sincronização:</target> + +<source>Invalid command line: %x</source> +<target>Linha de comando inválida: %x</target> + +<source>Windows Error Code %x:</source> +<target>Código de Erro do Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Código de Erro do Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Erro na resolução de link simbólico:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Resultado da Comparação</target> -<source>Incompatible synchronization database format:</source> -<target>Formato de banco de dados de sincronização incompatível:</target> - <source>Initial synchronization:</source> <target>Sincronização inicial:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Um dos arquivos de banco de dados do FreeFileSync ainda não existe:</target> -<source>Error reading from synchronization database:</source> -<target>Erro ao ler do banco de dados de sincronização:</target> +<source>Incompatible synchronization database format:</source> +<target>Formato de banco de dados de sincronização incompatível:</target> <source>Database files do not share a common synchronization session:</source> <target>Arquivos de banco de dados não compartilham uma sessão de sincronização comum:</target> @@ -199,12 +202,18 @@ <pluralform>%x seg</pluralform> </target> +<source>Drag && drop</source> +<target>Arrastar && Soltar</target> + <source>Info</source> -<target>Info</target> +<target>Informações</target> <source>Fatal Error</source> <target>Erro fatal</target> +<source>Error reading file:</source> +<target>Erro ao ler arquivo:</target> + <source>Scanning:</source> <target>Pesquisando:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Arquivo de configuração do FreeFileSync inválido!</target> -<source>File does not exist:</source> -<target>O arquivo não existe:</target> - <source>Error parsing configuration file:</source> <target>Erro de leitura do arquivo de configuração:</target> +<source>Error moving to Recycle Bin:</source> +<target>Erro ao mover para a Lixeira:</target> + +<source>Could not load a required DLL:</source> +<target>Não foi possível carregar uma DLL requerida:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Erro ao acessar o Serviço de Cópia de Sombra de Volume!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Cópias de sombra no WOW64 não são suportadas. Por favor use a versão 64-bits do FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Não foi possível determinar o nome do volume para o arquivo:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Nome do volume %x não é parte do arquivo %y!</target> + <source>/sec</source> <target>/seg</target> +<source>File does not exist:</source> +<target>O arquivo não existe:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Não foi possível ler os valores para os seguintes nós XML:</target> + <source>S&ave configuration...</source> <target>S&alvar configuração...</target> @@ -324,143 +354,8 @@ A linha de comando é executada cada vez que: <source>A directory input field is empty.</source> <target>Um campo de entrada de diretório está vazio.</target> -<source>Drag && drop</source> -<target>Arrastar && Soltar</target> - -<source>Could not initialize directory monitoring:</source> -<target>Não foi possível inicializar o monitoramento de diretórios:</target> - -<source>Error when monitoring directories.</source> -<target>Erro ao monitorar os diretórios.</target> - -<source>Conversion error:</source> -<target>Erro de conversão:</target> - -<source>Error deleting file:</source> -<target>Erro ao apagar arquivo:</target> - -<source>Error moving file:</source> -<target>Erro ao mover arquivo:</target> - -<source>Target file already existing!</source> -<target>Arquivo de destino já existe!</target> - -<source>Error moving directory:</source> -<target>Erro ao mover diretório:</target> - -<source>Target directory already existing!</source> -<target>Diretório de destino já existe!</target> - -<source>Error deleting directory:</source> -<target>Erro ao apagar diretório:</target> - -<source>Error changing modification time:</source> -<target>Erro ao mudar a hora de modificação:</target> - -<source>Error loading library function:</source> -<target>Erro ao carregar a biblioteca de funções:</target> - -<source>Error reading security context:</source> -<target>Erro ao ler contexto de segurança:</target> - -<source>Error writing security context:</source> -<target>Erro ao escrever contexto de segurança:</target> - -<source>Error copying file permissions:</source> -<target>Erro ao copiar permissões do arquivo:</target> - -<source>Error creating directory:</source> -<target>Erro ao criar diretório:</target> - -<source>Error copying symbolic link:</source> -<target>Erro ao copiar links simbólicos:</target> - -<source>Error copying file:</source> -<target>Erro ao copiar arquivo:</target> - -<source>Error opening file:</source> -<target>Erro ao abrir arquivo:</target> - -<source>Error writing file:</source> -<target>Erro ao escrever arquivo:</target> - -<source>Error reading file:</source> -<target>Erro ao ler arquivo:</target> - -<source>Operation aborted!</source> -<target>Operação cancelada!</target> - -<source>Endless loop when traversing directory:</source> -<target>Loop infinito quando percorrendo diretório:</target> - -<source>Error traversing directory:</source> -<target>Erro ao percorrer diretório:</target> - -<source>Error setting privilege:</source> -<target>Erro ao definir privilégio:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Erro ao mover para a Lixeira:</target> - -<source>Could not load a required DLL:</source> -<target>Não foi possível carregar uma DLL requerida:</target> - -<source>Error writing to synchronization database:</source> -<target>Erro ao escrever no banco de dados de sincronização:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Erro ao acessar o Serviço de Cópia de Sombra de Volume!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Cópias de sombra no WOW64 não são suportadas. Por favor use a versão 64-bits do FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Não foi possível determinar o nome do volume para o arquivo:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Nome do volume %x não é parte do arquivo %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 hora</pluralform> -<pluralform>%x horas</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dia</pluralform> -<pluralform>%x dias</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Não foi possível ler os valores para os seguintes nós XML:</target> - <source>Logging</source> -<target>Gravando log</target> +<target>Log</target> <source>FreeFileSync batch file</source> <target>FreeFileSync arquivo batch</target> @@ -477,9 +372,6 @@ A linha de comando é executada cada vez que: <source>Batch execution</source> <target>Execução do batch</target> -<source>Log-messages:</source> -<target>Log de mensagens:</target> - <source>Stop</source> <target>Parar</target> @@ -606,6 +498,24 @@ A linha de comando é executada cada vez que: <source>Total amount of data that will be transferred</source> <target>Volume total de dados que será transferido</target> +<source>Operation:</source> +<target>Operação:</target> + +<source>Items found:</source> +<target>Elementos encontrados:</target> + +<source>Items remaining:</source> +<target>Elementos faltantes:</target> + +<source>Speed:</source> +<target>Velocidade:</target> + +<source>Time remaining:</source> +<target>Tempo restante:</target> + +<source>Time elapsed:</source> +<target>Tempo decorrido:</target> + <source>Batch job</source> <target>Arquivo Batch</target> @@ -654,32 +564,14 @@ A linha de comando é executada cada vez que: <source>&Cancel</source> <target>&Cancelar</target> -<source>Operation:</source> -<target>Operação:</target> - -<source>Items found:</source> -<target>Elementos encontrados:</target> - -<source>Items remaining:</source> -<target>Elementos faltantes:</target> - -<source>Speed:</source> -<target>Velocidade:</target> - -<source>Time remaining:</source> -<target>Tempo restante:</target> - -<source>Time elapsed:</source> -<target>Tempo passado:</target> - <source>Select variant:</source> <target>Selecione um modo:</target> <source><Automatic></source> <target><Automático></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identifica e propaga mudanças em ambos os lados utilizando um banco de dados. Exclusões e conflitos serão detectados automaticamente.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identifica e propaga as mudanças em ambos os lados usando um banco de dados. Arquivos apagados, renomeados e conflitantes são detectados automaticamente.</target> <source>Mirror ->></source> <target>Espelhar ->></target> @@ -901,27 +793,19 @@ Excluir: \stuff\temp\* <target>Cópia de arquivo transacional</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Escreve para um arquivo temporário primeiro (*.ffs_tmp) e depois o renomeia. Isto garante um estado consistente mesmo em caso de erro fatal.</target> <source>Copy locked files</source> <target>Copiar arquivos bloqueados (em uso)</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copia os arquivos compartilhados ou bloqueados (em uso) usando o Serviço de Cópia de Sombra de Volume (Requer direitos de Administrador) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Copia os arquivos compartilhados ou bloqueados (em uso) usando o Serviço de Cópia de Sombra de Volume (Requer direitos de Administrador)</target> <source>Copy file access permissions</source> <target>Copiar permissões de acesso aos arquivos</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transfere as permissões de arquivos e diretórios (Requer direitos de Administrador) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transfere as permissões de arquivos e diretórios (Requer direitos de Administrador)</target> <source>Hidden dialogs:</source> <target>Diálogos ocultados:</target> @@ -953,6 +837,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>&Find next</source> <target>&Localizar próxima</target> +<source>Operation aborted!</source> +<target>Operação cancelada!</target> + <source>Main bar</source> <target>Barra principal</target> @@ -993,16 +880,16 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <target>Autoajustar colunas</target> <source>Icon size:</source> -<target></target> +<target>Tamanho do ícone:</target> <source>Small</source> -<target></target> +<target>Pequeno</target> <source>Medium</source> -<target></target> +<target>Médio</target> <source>Large</source> -<target></target> +<target>Grande</target> <source>Include all rows</source> <target>Incluir todas as linhas</target> @@ -1130,6 +1017,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>File list exported!</source> <target>Lista de arquivos exportada!</target> +<source>Error writing file:</source> +<target>Erro ao escrever arquivo:</target> + <source>Batch file created successfully!</source> <target>Arquivo batch criado com sucesso!</target> @@ -1229,9 +1119,6 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Filter: Single pair</source> <target>Filtro: Apenas um par</target> -<source>Ignore</source> -<target>Ignorar</target> - <source>Direct</source> <target>Direcionar</target> @@ -1295,6 +1182,105 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Move files into a time-stamped subdirectory</source> <target>Mover arquivos para um subdiretório com carimbo de tempo</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 hora</pluralform> +<pluralform>%x horas</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dia</pluralform> +<pluralform>%x dias</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Não foi possível inicializar o monitoramento de diretórios:</target> + +<source>Error when monitoring directories.</source> +<target>Erro ao monitorar os diretórios.</target> + +<source>Conversion error:</source> +<target>Erro de conversão:</target> + +<source>Error deleting file:</source> +<target>Erro ao apagar arquivo:</target> + +<source>Error moving file:</source> +<target>Erro ao mover arquivo:</target> + +<source>Target file already existing!</source> +<target>Arquivo de destino já existe!</target> + +<source>Error moving directory:</source> +<target>Erro ao mover diretório:</target> + +<source>Target directory already existing!</source> +<target>Diretório de destino já existe!</target> + +<source>Error deleting directory:</source> +<target>Erro ao apagar diretório:</target> + +<source>Error changing modification time:</source> +<target>Erro ao mudar a hora de modificação:</target> + +<source>Error loading library function:</source> +<target>Erro ao carregar a biblioteca de funções:</target> + +<source>Error reading security context:</source> +<target>Erro ao ler contexto de segurança:</target> + +<source>Error writing security context:</source> +<target>Erro ao escrever contexto de segurança:</target> + +<source>Error copying file permissions:</source> +<target>Erro ao copiar permissões do arquivo:</target> + +<source>Error creating directory:</source> +<target>Erro ao criar diretório:</target> + +<source>Error copying symbolic link:</source> +<target>Erro ao copiar links simbólicos:</target> + +<source>Error copying file:</source> +<target>Erro ao copiar arquivo:</target> + +<source>Error opening file:</source> +<target>Erro ao abrir arquivo:</target> + +<source>Error traversing directory:</source> +<target>Erro ao percorrer diretório:</target> + +<source>Endless loop when traversing directory:</source> +<target>Loop infinito quando percorrendo diretório:</target> + +<source>Error setting privilege:</source> +<target>Erro ao definir privilégio:</target> + <source>Both sides have changed since last synchronization!</source> <target>Ambos os lados foram alterados desde a última sincronização!</target> @@ -1325,9 +1311,6 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Diretórios são dependentes! Cuidado ao definir as regras de sincronização:</target> -<source>Comparing content of files %x</source> -<target>Comparando conteúdo do arquivo %x</target> - <source>Memory allocation failed!</source> <target>Alocação de memória falhou!</target> @@ -1343,15 +1326,15 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Symlinks %x have the same date but a different target!</source> <target>Links Simbólicos %x têm a mesma data mas um destino diferente!</target> +<source>Comparing content of files %x</source> +<target>Comparando conteúdo do arquivo %x</target> + <source>Comparing files by content failed.</source> <target>Comparação de arquivos pelo conteúdo falhou.</target> <source>Generating file list...</source> <target>Gerando lista de arquivos...</target> -<source>Multiple...</source> -<target>Múltiplos...</target> - <source>Both sides are equal</source> <target>Ambos os lados são iguais</target> @@ -1370,6 +1353,12 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Delete right file/folder</source> <target>Apagar arquivos/pastas da direita</target> +<source>Move file on left</source> +<target>Mover arquivo da esquerda</target> + +<source>Move file on right</source> +<target>Mover arquivo da direita</target> + <source>Overwrite left file/folder with right one</source> <target>Substituir arquivos/pastas da esquerda pelos da direita</target> @@ -1385,6 +1374,9 @@ Transfere as permissões de arquivos e diretórios (Requer direitos de Administr <source>Copy file attributes only to right</source> <target>Copiar apenas os atributos do arquivo para a direita</target> +<source>Multiple...</source> +<target>Múltiplos...</target> + <source>Deleting file %x</source> <target>Apagando arquivo %x</target> diff --git a/BUILD/Languages/romanian.lng b/BUILD/Languages/romanian.lng index f9e85c0e..c7b8958c 100644 --- a/BUILD/Languages/romanian.lng +++ b/BUILD/Languages/romanian.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Sincronizare Inteligentă</target> -<source>Browse</source> -<target>Explorează</target> - -<source>Windows Error Code %x:</source> -<target>Codul Erorii Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Codul Erorii Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Linie de comandă nevalidă: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Eroare la rezolvarea legăturii simbolice:</target> - -<source>Show pop-up</source> -<target>Este arătat un popîc</target> - -<source>Show pop-up on errors or warnings</source> -<target>Se afișează o fereastră popîc [popup] la erori sau avertizări</target> - -<source>Ignore errors</source> -<target>Erorile sînt ignorate</target> - -<source>Hide all error and warning messages</source> -<target>Sînt ascunse toate mesajele de eroare și de avertizare</target> - -<source>Exit instantly</source> -<target>Ieși imediat</target> - -<source>Abort synchronization immediately</source> -<target>Abandonează imediat sincronizarea</target> - <source>Select alternate comparison settings</source> <target>Selectează setările alternative de comparare</target> @@ -101,7 +68,7 @@ <target>Configurează Filtrul</target> <source>Customize columns</source> -<target>Personalizează coloanele</target> +<target>Bifează coloanele de afișat</target> <source>Global settings</source> <target>Setări Globale</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Selectează intervalul de timp</target> +<source>Show pop-up</source> +<target>Este arătat un popîc</target> + +<source>Show pop-up on errors or warnings</source> +<target>Se afișează o fereastră popîc [popup] la erori sau avertizări</target> + +<source>Ignore errors</source> +<target>Erorile sînt ignorate</target> + +<source>Hide all error and warning messages</source> +<target>Sînt ascunse toate mesajele de eroare și de avertizare</target> + +<source>Exit instantly</source> +<target>Ieși imediat</target> + +<source>Abort synchronization immediately</source> +<target>Abandonează imediat sincronizarea</target> + +<source>Browse</source> +<target>Explorează</target> + +<source>Error reading from synchronization database:</source> +<target>Eroare la citirea din baza de date a sincronizării:</target> + +<source>Error writing to synchronization database:</source> +<target>Eroare la scrierea în baza de date a sincronizării:</target> + +<source>Invalid command line: %x</source> +<target>Linie de comandă nevalidă: %x</target> + +<source>Windows Error Code %x:</source> +<target>Codul Erorii Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Codul Erorii Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Eroare la rezolvarea legăturii simbolice:</target> + <source>%x MB</source> <target>%x MB</target> @@ -147,7 +153,7 @@ <target>Dată</target> <source>Full path</source> -<target>Cale completă</target> +<target>Calea Completă</target> <source>Filename</source> <target>Numele Elementului</target> @@ -164,17 +170,14 @@ <source>Comparison Result</source> <target>Rezultatul Comparării</target> -<source>Incompatible synchronization database format:</source> -<target>Format al bazei de date necompatibil cu versiunea softului:</target> - <source>Initial synchronization:</source> <target>Sincronizare inițială:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Una dintre părți nu are o filă de tip bază de date FreeFileSync:</target> -<source>Error reading from synchronization database:</source> -<target>Eroare la citirea din baza de date a sincronizării:</target> +<source>Incompatible synchronization database format:</source> +<target>Format al bazei de date necompatibil cu versiunea softului:</target> <source>Database files do not share a common synchronization session:</source> <target>Filele bază de date nu partajează o sesiune comună de sincronizare</target> @@ -201,17 +204,23 @@ <pluralform>%x de sec</pluralform> </target> +<source>Drag && drop</source> +<target>Trage și pune un dosar peste compartimentul de mai jos sau selectează-l cu butonul de explorare</target> + <source>Info</source> <target>Informații</target> <source>Fatal Error</source> <target>Eroare Fatală</target> +<source>Error reading file:</source> +<target>Eroare la citirea filei:</target> + <source>Scanning:</source> <target>Scanez:</target> <source>Encoding extended time information: %x</source> -<target>Codarea informațiilor timpului extins: %x</target> +<target>Codez informațiile extinse despre timp: %x</target> <source> <pluralform>[1 Thread]</pluralform> @@ -226,15 +235,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Filă de configurare FreeFileSync nevalidă!</target> -<source>File does not exist:</source> -<target>Fila nu există:</target> - <source>Error parsing configuration file:</source> <target>Eroare la parsarea filei de configurare:</target> +<source>Error moving to Recycle Bin:</source> +<target>Eroare la mutarea în Reciclator:</target> + +<source>Could not load a required DLL:</source> +<target>Nu pot încărca o filă DLL necesară:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Eroare la accesarea Serviciului de Conservare a Volumelor [Volume Shadow Copy]!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Realizarea de conservări (copii de rezervă) prin sistemul WOW64 nu este suportată. Folosește versiunea pe 64-biți a FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>Nu pot determina numele volumului pentru fila:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Numele volumului %x nu face parte din numele filei %y !</target> + <source>/sec</source> <target>/sec</target> +<source>File does not exist:</source> +<target>Fila nu există:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Nu pot citi valorile pentru următoarele noduri XML:</target> + <source>S&ave configuration...</source> <target>S&alvează Configurația...</target> @@ -327,146 +357,8 @@ Linia de comandă este executată de fiecare dată cînd: <source>A directory input field is empty.</source> <target>Cel puțin unul din dosarele de comparat este nespecificat.</target> -<source>Drag && drop</source> -<target>Trage și lasă un dosar peste compartimentul de mai jos sau selectează-l cu butonul de explorare</target> - -<source>Could not initialize directory monitoring:</source> -<target>Nu pot inițializa monitorizarea dosarelor:</target> - -<source>Error when monitoring directories.</source> -<target>Eroare la monitorizarea dosarelor.</target> - -<source>Conversion error:</source> -<target>Eroare de convertire:</target> - -<source>Error deleting file:</source> -<target>Eroare la ștergerea filei:</target> - -<source>Error moving file:</source> -<target>Eroare la mutarea filei:</target> - -<source>Target file already existing!</source> -<target>Fila țintă există deja!</target> - -<source>Error moving directory:</source> -<target>Eroare la mutarea dosarului:</target> - -<source>Target directory already existing!</source> -<target>Dosarul țintă există deja!</target> - -<source>Error deleting directory:</source> -<target>Eroare la ștergerea dosarului:</target> - -<source>Error changing modification time:</source> -<target>Eroare la schimbarea datei de modificare:</target> - -<source>Error loading library function:</source> -<target>Eroare la încărcarea bibliotecii de funcții:</target> - -<source>Error reading security context:</source> -<target>Eroare la citirea contextului de securitate:</target> - -<source>Error writing security context:</source> -<target>Eroare la scrierea contextului de securitate:</target> - -<source>Error copying file permissions:</source> -<target>Eroare la copierea permisiunilor filei:</target> - -<source>Error creating directory:</source> -<target>Eroare la crearea dosarului:</target> - -<source>Error copying symbolic link:</source> -<target>Eroare la copierea legăturii simbolice:</target> - -<source>Error copying file:</source> -<target>Eroare la copierea filei:</target> - -<source>Error opening file:</source> -<target>Eroare la deschiderea filei:</target> - -<source>Error writing file:</source> -<target>Eroare la scrierea filei:</target> - -<source>Error reading file:</source> -<target>Eroare la citirea filei:</target> - -<source>Operation aborted!</source> -<target>Operație abandonată!</target> - -<source>Endless loop when traversing directory:</source> -<target>Buclă infinită la parcurgerea dosarului:</target> - -<source>Error traversing directory:</source> -<target>Eroare la parcurgerea dosarului:</target> - -<source>Error setting privilege:</source> -<target>Eroare la setarea privilegiului:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Eroare la mutarea în Reciclator:</target> - -<source>Could not load a required DLL:</source> -<target>Nu pot încărca o filă DLL necesară:</target> - -<source>Error writing to synchronization database:</source> -<target>Eroare la scrierea în baza de date a sincronizării:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Eroare la accesarea Serviciului de Conservare a Volumelor [Volume Shadow Copy]!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Realizarea de conservări (copii de rezervă) prin sistemul WOW64 nu este suportată. Folosește versiunea pe 64-biți a FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>Nu pot determina numele volumului pentru fila:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Numele volumului %x nu face parte din numele filei %y !</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -<pluralform>%x de min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 oră</pluralform> -<pluralform>%x ore</pluralform> -<pluralform>%x de ore</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 zi</pluralform> -<pluralform>%x zile</pluralform> -<pluralform>%x de zile</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Nu pot citi valorile pentru următoarele noduri XML:</target> - <source>Logging</source> -<target>Jurnalizez</target> +<target>Jurnal</target> <source>FreeFileSync batch file</source> <target>Filă cu set de comenzi FreeFileSync</target> @@ -483,9 +375,6 @@ Linia de comandă este executată de fiecare dată cînd: <source>Batch execution</source> <target>Execută Fila Set</target> -<source>Log-messages:</source> -<target>Mesaje de jurnalizare:</target> - <source>Stop</source> <target>Oprește</target> @@ -612,6 +501,24 @@ Linia de comandă este executată de fiecare dată cînd: <source>Total amount of data that will be transferred</source> <target>Volumul total de date care va fi transferat</target> +<source>Operation:</source> +<target>Operație:</target> + +<source>Items found:</source> +<target>Elemente Găsite:</target> + +<source>Items remaining:</source> +<target>Elemente Rămase:</target> + +<source>Speed:</source> +<target>Viteză:</target> + +<source>Time remaining:</source> +<target>Timp Rămas:</target> + +<source>Time elapsed:</source> +<target>Timp Scurs:</target> + <source>Batch job</source> <target>Sarcină Set</target> @@ -660,32 +567,14 @@ Linia de comandă este executată de fiecare dată cînd: <source>&Cancel</source> <target>&Anulează</target> -<source>Operation:</source> -<target>Operație:</target> - -<source>Items found:</source> -<target>Elemente Găsite:</target> - -<source>Items remaining:</source> -<target>Elemente Rămase:</target> - -<source>Speed:</source> -<target>Viteză:</target> - -<source>Time remaining:</source> -<target>Timp Rămas:</target> - -<source>Time elapsed:</source> -<target>Timp Scurs:</target> - <source>Select variant:</source> <target>Selectează Varianta de Sincronizare:</target> <source><Automatic></source> <target><Sincronizare Inteligentă></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Modificările din ambele părți sînt identificate și propagate folosind o bază de date. Ștergerile și conflictele sînt detectate automat.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identificare și propagare a modificărilor din ambele părți folosind o bază de date. Ștergerile, renumirile și conflictele sînt detectate automat</target> <source>Mirror ->></source> <target>Clonare =>></target> @@ -697,7 +586,7 @@ Linia de comandă este executată de fiecare dată cînd: <target>Actualizare =></target> <source>Copy new or updated files to right folder.</source> -<target>Copiază în dosarul din dreapta filele actualizate sau noi.</target> +<target>Copiere în dosarul din dreapta a filelor actualizate sau noi.</target> <source>Custom</source> <target>Sincronizare Personalizată</target> @@ -907,27 +796,19 @@ Excluse: \stuff\temp\* <target>Copiere tranzacțională a filelor</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Scrierea se face mai întîi într-o filă temporară (*.ffs_tmp), care e apoi renumită. Se garantează astfel consecvența stării filelor chiar și în cazul apariției de erori fatale.</target> <source>Copy locked files</source> -<target>Copiere și a filelor zăvorîte [locked]</target> +<target>Copiere a filelor partajate [shared] sau zăvorîte [locked]</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copiază filele partajate sau zăvorîte folosind Serviciul de Conservare a Volumelor [Volume Shadow Copy] (Necesită drepturi de Administrator) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Filele partajate sau zăvorîte sînt copiate folosind Serviciul de Conservare a Volumelor din Windows [Volume Shadow Copy] (necesită drepturi de Administrator)</target> <source>Copy file access permissions</source> <target>Copiază permisiunile de acces ale filelor</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrator) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transferă permisiunile filelor și dosarelor (necesită drepturi de Administrator)</target> <source>Hidden dialogs:</source> <target>Casete de dialog ascunse:</target> @@ -948,7 +829,7 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <target>Varianta Sincronizării</target> <source>Statistics</source> -<target>Statistici</target> +<target>Statis.</target> <source>Find what:</source> <target>Găsește Asta:</target> @@ -959,6 +840,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>&Find next</source> <target>&Găsește Următorul</target> +<source>Operation aborted!</source> +<target>Operație abandonată!</target> + <source>Main bar</source> <target>Bara Principală</target> @@ -996,19 +880,19 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <target>Selectează intervalul de timp...</target> <source>Auto-adjust columns</source> -<target>Autoajustează Coloanele</target> +<target>Ajustează Automat Coloanele</target> <source>Icon size:</source> -<target></target> +<target>Mărimea Icoanelor Elementelor:</target> <source>Small</source> -<target></target> +<target>Mică</target> <source>Medium</source> -<target></target> +<target>Medie</target> <source>Large</source> -<target></target> +<target>Mare</target> <source>Include all rows</source> <target>Include Toate Rîndurile</target> @@ -1136,6 +1020,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>File list exported!</source> <target>Lista de file a fost exportată!</target> +<source>Error writing file:</source> +<target>Eroare la scrierea filei:</target> + <source>Batch file created successfully!</source> <target>Fila cu setul de comenzi a fost creată cu succces !</target> @@ -1239,9 +1126,6 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Filter: Single pair</source> <target>Filtru: O singură pereche</target> -<source>Ignore</source> -<target>Ignoră</target> - <source>Direct</source> <target>Direcționează</target> @@ -1307,6 +1191,108 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Move files into a time-stamped subdirectory</source> <target>Filele sînt mutate într-un subdosar cu marcaj de timp</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +<pluralform>%x de min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 oră</pluralform> +<pluralform>%x ore</pluralform> +<pluralform>%x de ore</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 zi</pluralform> +<pluralform>%x zile</pluralform> +<pluralform>%x de zile</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Nu pot inițializa monitorizarea dosarelor:</target> + +<source>Error when monitoring directories.</source> +<target>Eroare la monitorizarea dosarelor.</target> + +<source>Conversion error:</source> +<target>Eroare de convertire:</target> + +<source>Error deleting file:</source> +<target>Eroare la ștergerea filei:</target> + +<source>Error moving file:</source> +<target>Eroare la mutarea filei:</target> + +<source>Target file already existing!</source> +<target>Fila țintă există deja!</target> + +<source>Error moving directory:</source> +<target>Eroare la mutarea dosarului:</target> + +<source>Target directory already existing!</source> +<target>Dosarul țintă există deja!</target> + +<source>Error deleting directory:</source> +<target>Eroare la ștergerea dosarului:</target> + +<source>Error changing modification time:</source> +<target>Eroare la schimbarea datei de modificare:</target> + +<source>Error loading library function:</source> +<target>Eroare la încărcarea bibliotecii de funcții:</target> + +<source>Error reading security context:</source> +<target>Eroare la citirea contextului de securitate:</target> + +<source>Error writing security context:</source> +<target>Eroare la scrierea contextului de securitate:</target> + +<source>Error copying file permissions:</source> +<target>Eroare la copierea permisiunilor filei:</target> + +<source>Error creating directory:</source> +<target>Eroare la crearea dosarului:</target> + +<source>Error copying symbolic link:</source> +<target>Eroare la copierea legăturii simbolice:</target> + +<source>Error copying file:</source> +<target>Eroare la copierea filei:</target> + +<source>Error opening file:</source> +<target>Eroare la deschiderea filei:</target> + +<source>Error traversing directory:</source> +<target>Eroare la parcurgerea dosarului:</target> + +<source>Endless loop when traversing directory:</source> +<target>Buclă infinită la parcurgerea dosarului:</target> + +<source>Error setting privilege:</source> +<target>Eroare la setarea privilegiului:</target> + <source>Both sides have changed since last synchronization!</source> <target>Ambele părți s-au modificat de la ultima sincronizare!</target> @@ -1337,9 +1323,6 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Dosarele sînt interdependente! Atenție la setarea regulilor de sincronizare:</target> -<source>Comparing content of files %x</source> -<target>Compar conținutul filelor %x</target> - <source>Memory allocation failed!</source> <target>Alocarea memoriei a eșuat!</target> @@ -1355,15 +1338,15 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Symlinks %x have the same date but a different target!</source> <target>Simlegăturile %x au dată identică, dar ținte diferite!</target> +<source>Comparing content of files %x</source> +<target>Compar conținutul filelor %x</target> + <source>Comparing files by content failed.</source> <target>Compararea filelor după conținut a eșuat.</target> <source>Generating file list...</source> <target>Generez lista de file...</target> -<source>Multiple...</source> -<target>Multiplu...</target> - <source>Both sides are equal</source> <target>Ambele părți sînt identice</target> @@ -1382,6 +1365,12 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Delete right file/folder</source> <target>Șterge elementul drept</target> +<source>Move file on left</source> +<target>Mută fila în stînga</target> + +<source>Move file on right</source> +<target>Mută fila în dreapta</target> + <source>Overwrite left file/folder with right one</source> <target>Suprascrie elementul stîng (fila/dosarul) cu cel drept</target> @@ -1397,6 +1386,9 @@ Transferă permisiunile filelor și dosarelor (Necesită drepturi de Administrat <source>Copy file attributes only to right</source> <target>Copiază atributele filelor doar înspre dreapta</target> +<source>Multiple...</source> +<target>Multiplu...</target> + <source>Deleting file %x</source> <target>Șterg fila %x</target> diff --git a/BUILD/Languages/russian.lng b/BUILD/Languages/russian.lng index 1a4965e8..75da2588 100644 --- a/BUILD/Languages/russian.lng +++ b/BUILD/Languages/russian.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Автоматическая синхронизация</target> -<source>Browse</source> -<target>Обзор</target> - -<source>Windows Error Code %x:</source> -<target>Код ошибки Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Код ошибки Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Неверная командная строка: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Ошибка при решении символической ссылки:</target> - -<source>Show pop-up</source> -<target>Показывать всплывающие окна</target> - -<source>Show pop-up on errors or warnings</source> -<target>Показывать всплывающие окна при ошибках и замечаниях</target> - -<source>Ignore errors</source> -<target>Игнорировать ошибки</target> - -<source>Hide all error and warning messages</source> -<target>Скрывать все ошибки и сообщения с предупреждениями</target> - -<source>Exit instantly</source> -<target>Выйти немедленно</target> - -<source>Abort synchronization immediately</source> -<target>Отменить синхронизацию немедленно</target> - <source>Select alternate comparison settings</source> <target>Выбрать альтернативные настройки сравнения</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Выберите промежуток времени</target> +<source>Show pop-up</source> +<target>Показывать всплывающие окна</target> + +<source>Show pop-up on errors or warnings</source> +<target>Показывать всплывающие окна при ошибках и замечаниях</target> + +<source>Ignore errors</source> +<target>Игнорировать ошибки</target> + +<source>Hide all error and warning messages</source> +<target>Скрывать все ошибки и сообщения с предупреждениями</target> + +<source>Exit instantly</source> +<target>Выйти немедленно</target> + +<source>Abort synchronization immediately</source> +<target>Отменить синхронизацию немедленно</target> + +<source>Browse</source> +<target>Обзор</target> + +<source>Error reading from synchronization database:</source> +<target>Ошибка при чтении из базы данных синхронизации:</target> + +<source>Error writing to synchronization database:</source> +<target>Ошибка при записи в базу данных синхронизации:</target> + +<source>Invalid command line: %x</source> +<target>Неверная командная строка: %x</target> + +<source>Windows Error Code %x:</source> +<target>Код ошибки Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Код ошибки Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Ошибка при решении символической ссылки:</target> + <source>%x MB</source> <target>%x МБ</target> @@ -164,17 +170,14 @@ <source>Comparison Result</source> <target>Результаты сравнения</target> -<source>Incompatible synchronization database format:</source> -<target>Несовместимый формат базы данных синхронизации:</target> - <source>Initial synchronization:</source> <target>Первоначальная синхронизация:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Одного из файлов баз данных FreeFileSync еще не существует:</target> -<source>Error reading from synchronization database:</source> -<target>Ошибка при чтении из базы данных синхронизации:</target> +<source>Incompatible synchronization database format:</source> +<target>Несовместимый формат базы данных синхронизации:</target> <source>Database files do not share a common synchronization session:</source> <target>Файлы баз данных не имеют общей сессии синхронизации:</target> @@ -201,12 +204,18 @@ <pluralform>%x секунд</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && drop</target> + <source>Info</source> <target>Информация</target> <source>Fatal Error</source> <target>Критическая ошибка</target> +<source>Error reading file:</source> +<target>Ошибка при чтении файла:</target> + <source>Scanning:</source> <target>Сканирую:</target> @@ -226,15 +235,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Неверный файл конфигурации FreeFileSync!</target> -<source>File does not exist:</source> -<target>Файл не существует:</target> - <source>Error parsing configuration file:</source> <target>Ошибка при анализе файла настроек синхронизации:</target> +<source>Error moving to Recycle Bin:</source> +<target>Ошибка при перемещении в "Корзину":</target> + +<source>Could not load a required DLL:</source> +<target>Не удалось загрузить необходимые DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Ошибка доступа к службе Теневого Копирования Тома!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Создание теневых копий на WOW64 не поддерживается. Пожалуйста, используйте FreeFileSync 64-разрядной версии.</target> + +<source>Could not determine volume name for file:</source> +<target>Не удалось определить название тома для файла:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Имя тома %x не является частью имени файла %y!</target> + <source>/sec</source> <target>/с</target> +<source>File does not exist:</source> +<target>Файл не существует:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Не удалось прочитать значения для следующих XML записей:</target> + <source>S&ave configuration...</source> <target>Сохранить настройки синхронизации...</target> @@ -327,144 +357,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>Поле ввода пути папки пустое.</target> -<source>Drag && drop</source> -<target>Drag && drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Не удалось инициализировать папку для мониторинга:</target> - -<source>Error when monitoring directories.</source> -<target>Ошибка при мониторинге папок.</target> - -<source>Conversion error:</source> -<target>Ошибка преобразования:</target> - -<source>Error deleting file:</source> -<target>Ошибка при удалении файла:</target> - -<source>Error moving file:</source> -<target>Ошибка перемещения файла:</target> - -<source>Target file already existing!</source> -<target>Конечный файл уже существует!</target> - -<source>Error moving directory:</source> -<target>Ошибка перемещения папки:</target> - -<source>Target directory already existing!</source> -<target>Конечная папка уже существует!</target> - -<source>Error deleting directory:</source> -<target>Ошибка при удалении папки:</target> - -<source>Error changing modification time:</source> -<target>Ошибка при изменении времени модификации файла:</target> - -<source>Error loading library function:</source> -<target>Ошибка при загрузке функции библиотеки:</target> - -<source>Error reading security context:</source> -<target>Ошибка при чтении контекста безобасности:</target> - -<source>Error writing security context:</source> -<target>Ошибка при записи контекста безобасности:</target> - -<source>Error copying file permissions:</source> -<target>Ошибка при копировании прав доступа:</target> - -<source>Error creating directory:</source> -<target>Ошибка при создании папки:</target> - -<source>Error copying symbolic link:</source> -<target>Ошибка при копировании символьной ссылки:</target> - -<source>Error copying file:</source> -<target>Ошибка при копировании файла:</target> - -<source>Error opening file:</source> -<target>Ошибка при открытии файла:</target> - -<source>Error writing file:</source> -<target>Ошибка при записи файла:</target> - -<source>Error reading file:</source> -<target>Ошибка при чтении файла:</target> - -<source>Operation aborted!</source> -<target>Операция отменена!</target> - -<source>Endless loop when traversing directory:</source> -<target>Зацикливание при встрече пересекающихся путей:</target> - -<source>Error traversing directory:</source> -<target>Ошибка при пересечении папок:</target> - -<source>Error setting privilege:</source> -<target>Ошибка установки привилегий:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Ошибка при перемещении в "Корзину":</target> - -<source>Could not load a required DLL:</source> -<target>Не удалось загрузить необходимые DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Ошибка при записи в базу данных синхронизации:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Ошибка доступа к службе Теневого Копирования Тома!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Создание теневых копий на WOW64 не поддерживается. Пожалуйста, используйте FreeFileSync 64-разрядной версии.</target> - -<source>Could not determine volume name for file:</source> -<target>Не удалось определить название тома для файла:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Имя тома %x не является частью имени файла %y!</target> - -<source>%x TB</source> -<target>%x ТБ</target> - -<source>%x PB</source> -<target>%x ПБ</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x минута</pluralform> -<pluralform>%x минуты</pluralform> -<pluralform>%x минут</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x час</pluralform> -<pluralform>%x часа</pluralform> -<pluralform>%x часов</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x день</pluralform> -<pluralform>%x дня</pluralform> -<pluralform>%x дней</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Не удалось прочитать значения для следующих XML записей:</target> - <source>Logging</source> <target>Лог-файлы</target> @@ -483,9 +375,6 @@ The command line is executed each time: <source>Batch execution</source> <target>Выполнение пакетного задания</target> -<source>Log-messages:</source> -<target>Лог-сообщения:</target> - <source>Stop</source> <target>Стоп</target> @@ -615,6 +504,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>Общий объем данных, который будет передаваться</target> +<source>Operation:</source> +<target>Операция:</target> + +<source>Items found:</source> +<target>Элементов найдено:</target> + +<source>Items remaining:</source> +<target>Элементов осталось:</target> + +<source>Speed:</source> +<target>Скорость:</target> + +<source>Time remaining:</source> +<target>Времени осталось:</target> + +<source>Time elapsed:</source> +<target>Времени прошло:</target> + <source>Batch job</source> <target>Пакетное задание</target> @@ -663,32 +570,14 @@ The command line is executed each time: <source>&Cancel</source> <target>&Отмена</target> -<source>Operation:</source> -<target>Операция:</target> - -<source>Items found:</source> -<target>Элементов найдено:</target> - -<source>Items remaining:</source> -<target>Элементов осталось:</target> - -<source>Speed:</source> -<target>Скорость:</target> - -<source>Time remaining:</source> -<target>Времени осталось:</target> - -<source>Time elapsed:</source> -<target>Времени прошло:</target> - <source>Select variant:</source> <target>Выберите вариант:</target> <source><Automatic></source> <target><Автоматический></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Выявление и распространение изменений на обеих сторонах с использованием базы данных. Удаленные файлы и конфликты определяются автоматически.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Выявление и распространение изменений на обе стороны, используя базу данных. Удаленные, переименованные и конфликтные файлы определяются автоматически.</target> <source>Mirror ->></source> <target>Зеркало ->></target> @@ -910,22 +799,14 @@ Exclude: \stuff\temp\* <source>Copy locked files</source> <target>Копирование заблокированных файлов</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Копирование общих или заблокированных файлов с использованием службы Теневого Копирования Тома (требуются права Администратора) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Копирование общих или заблокированных файлов с использованием службы Теневого Копирования Тома (требуются права Администратора)</target> <source>Copy file access permissions</source> <target>Копирование прав доступа к файлам</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Передача прав доступа к файлам/папкам (требуются права Администратора) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Передача прав доступа к файлам/папкам (требуются права Администратора)</target> <source>Hidden dialogs:</source> <target>Скрытые диалоги</target> @@ -957,6 +838,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>&Найти далее</target> +<source>Operation aborted!</source> +<target>Операция отменена!</target> + <source>Main bar</source> <target>Главная панель</target> @@ -1134,6 +1018,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>Список файлов экспортирован!</target> +<source>Error writing file:</source> +<target>Ошибка при записи файла:</target> + <source>Batch file created successfully!</source> <target>Файл пакетного задания создан успешно!</target> @@ -1237,9 +1124,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>Фильтр: Одна пара</target> -<source>Ignore</source> -<target>Игнорировать</target> - <source>Direct</source> <target>Прямое</target> @@ -1308,6 +1192,108 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>Перемещать файлы в заданную папку (можно создавать архивные версии удаленных файлов)</target> +<source>%x TB</source> +<target>%x ТБ</target> + +<source>%x PB</source> +<target>%x ПБ</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x минута</pluralform> +<pluralform>%x минуты</pluralform> +<pluralform>%x минут</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x час</pluralform> +<pluralform>%x часа</pluralform> +<pluralform>%x часов</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x день</pluralform> +<pluralform>%x дня</pluralform> +<pluralform>%x дней</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Не удалось инициализировать папку для мониторинга:</target> + +<source>Error when monitoring directories.</source> +<target>Ошибка при мониторинге папок.</target> + +<source>Conversion error:</source> +<target>Ошибка преобразования:</target> + +<source>Error deleting file:</source> +<target>Ошибка при удалении файла:</target> + +<source>Error moving file:</source> +<target>Ошибка перемещения файла:</target> + +<source>Target file already existing!</source> +<target>Конечный файл уже существует!</target> + +<source>Error moving directory:</source> +<target>Ошибка перемещения папки:</target> + +<source>Target directory already existing!</source> +<target>Конечная папка уже существует!</target> + +<source>Error deleting directory:</source> +<target>Ошибка при удалении папки:</target> + +<source>Error changing modification time:</source> +<target>Ошибка при изменении времени модификации файла:</target> + +<source>Error loading library function:</source> +<target>Ошибка при загрузке функции библиотеки:</target> + +<source>Error reading security context:</source> +<target>Ошибка при чтении контекста безобасности:</target> + +<source>Error writing security context:</source> +<target>Ошибка при записи контекста безобасности:</target> + +<source>Error copying file permissions:</source> +<target>Ошибка при копировании прав доступа:</target> + +<source>Error creating directory:</source> +<target>Ошибка при создании папки:</target> + +<source>Error copying symbolic link:</source> +<target>Ошибка при копировании символьной ссылки:</target> + +<source>Error copying file:</source> +<target>Ошибка при копировании файла:</target> + +<source>Error opening file:</source> +<target>Ошибка при открытии файла:</target> + +<source>Error traversing directory:</source> +<target>Ошибка при пересечении папок:</target> + +<source>Endless loop when traversing directory:</source> +<target>Зацикливание при встрече пересекающихся путей:</target> + +<source>Error setting privilege:</source> +<target>Ошибка установки привилегий:</target> + <source>Both sides have changed since last synchronization!</source> <target>Со времени последней синхронизации с обеих сторон произошли изменения!</target> @@ -1341,9 +1327,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Зависимые папки! Будьте внимательны при настройке правил синхронизации:</target> -<source>Comparing content of files %x</source> -<target>Сравнение содержания файлов %x</target> - <source>Memory allocation failed!</source> <target>Ошибка выделения памяти! (Не хватает памяти)</target> @@ -1359,15 +1342,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>Символьная ссылка %x имеет ту же дату, но различное содержание!</target> +<source>Comparing content of files %x</source> +<target>Сравнение содержания файлов %x</target> + <source>Comparing files by content failed.</source> <target>Сравнение файлов по содержимому провалено.</target> <source>Generating file list...</source> <target>Создание списка файлов...</target> -<source>Multiple...</source> -<target>Различные варианты синхронизации</target> - <source>Both sides are equal</source> <target>Обе стороны равны</target> @@ -1386,6 +1369,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>Удалить файл/папку справа</target> +<source>Move file on left</source> +<target>Переместить файл налево</target> + +<source>Move file on right</source> +<target>Переместить файл направо</target> + <source>Overwrite left file/folder with right one</source> <target>Перезаписать файл/папку слева на аналогичную из правой части</target> @@ -1401,6 +1390,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>Скопировать только атрибуты файла направо</target> +<source>Multiple...</source> +<target>Различные варианты синхронизации</target> + <source>Deleting file %x</source> <target>Удаление файла %x</target> diff --git a/BUILD/Languages/slovenian.lng b/BUILD/Languages/slovenian.lng index bf917426..4e6683db 100644 --- a/BUILD/Languages/slovenian.lng +++ b/BUILD/Languages/slovenian.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Avtomatizirana sinhronizacija</target> -<source>Browse</source> -<target>Brskaj</target> - -<source>Windows Error Code %x:</source> -<target>Windows koda napake %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux koda napake %x:</target> - -<source>Invalid command line: %x</source> -<target>Napačna ukazna vrstica: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Napaka pri razreševanju simbolične povezave:</target> - -<source>Show pop-up</source> -<target>Prikaži pojavno okno</target> - -<source>Show pop-up on errors or warnings</source> -<target>Prikaži pojavne napaka ali opozorila</target> - -<source>Ignore errors</source> -<target>Ignoriraj napake</target> - -<source>Hide all error and warning messages</source> -<target>Skrij vsa obvestila o napakah in opozorilih</target> - -<source>Exit instantly</source> -<target>Zapusti v trenutku</target> - -<source>Abort synchronization immediately</source> -<target>Takoj prekini sinhronizacijo</target> - <source>Select alternate comparison settings</source> <target>Izberite alternativne nastavitve primerjanja</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Izberite časovni okvir</target> +<source>Show pop-up</source> +<target>Prikaži pojavno okno</target> + +<source>Show pop-up on errors or warnings</source> +<target>Prikaži pojavne napaka ali opozorila</target> + +<source>Ignore errors</source> +<target>Ignoriraj napake</target> + +<source>Hide all error and warning messages</source> +<target>Skrij vsa obvestila o napakah in opozorilih</target> + +<source>Exit instantly</source> +<target>Zapusti v trenutku</target> + +<source>Abort synchronization immediately</source> +<target>Takoj prekini sinhronizacijo</target> + +<source>Browse</source> +<target>Brskaj</target> + +<source>Error reading from synchronization database:</source> +<target>Napaka pri branju iz sinhronizacijske podatkovne baze:</target> + +<source>Error writing to synchronization database:</source> +<target>Napaka pri pisanju v sinhronizacijsko podatkovno bazo:</target> + +<source>Invalid command line: %x</source> +<target>Napačna ukazna vrstica: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows koda napake %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux koda napake %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Napaka pri razreševanju simbolične povezave:</target> + <source>%x MB</source> <target>%x MB</target> @@ -165,17 +171,14 @@ <source>Comparison Result</source> <target>Rezultati primerjave</target> -<source>Incompatible synchronization database format:</source> -<target>Nekompatibilen format sinhronizacijske podatkovne baze:</target> - <source>Initial synchronization:</source> <target>Začetna sinhronizacija:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Ena od FreeFileSync datotek podatkovne baze še en obstaja:</target> -<source>Error reading from synchronization database:</source> -<target>Napaka pri branju iz sinhronizacijske podatkovne baze:</target> +<source>Incompatible synchronization database format:</source> +<target>Nekompatibilen format sinhronizacijske podatkovne baze:</target> <source>Database files do not share a common synchronization session:</source> <target>Datoteke podatkovne baze si ne delijo skupne sinhronizacijske seje:</target> @@ -203,12 +206,18 @@ <pluralform>%x sek</pluralform> </target> +<source>Drag && drop</source> +<target>Povleci && spusti</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Usodna napaka</target> +<source>Error reading file:</source> +<target>Napaka pri branju datoteke:</target> + <source>Scanning:</source> <target>Pregledujem:</target> @@ -229,15 +238,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Neveljavna FreeFileSync nastavitvena datoteka!</target> -<source>File does not exist:</source> -<target>Datoteka ne obstaja:</target> - <source>Error parsing configuration file:</source> <target>Napaka pri preverjanju konfiguracijske datoteke:</target> +<source>Error moving to Recycle Bin:</source> +<target>Napaka pri premikanju v Koš:</target> + +<source>Could not load a required DLL:</source> +<target>Ne morem naložiti zahtevano DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Napaka pri dostopu do servisa senčnih kopij!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Ustvarjanje senčnih kopij na WOW63 ni podprto. Prosimo uporabite 64-bitno FreeFileSync različico.</target> + +<source>Could not determine volume name for file:</source> +<target>Ne morem določiti imena volumna za datoteko:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Ime volumna %x ni del imena datoteke %y!</target> + <source>/sec</source> <target>/sek</target> +<source>File does not exist:</source> +<target>Datoteka ne obstaja:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Ne morem brati vrednosti za naslednja XML vozlišča:</target> + <source>S&ave configuration...</source> <target>Shr&ani konfiguracijo...</target> @@ -330,147 +360,6 @@ Ukazna vrstica se izvrši vsakič ko: <source>A directory input field is empty.</source> <target>Vpisno polje za imenik je prazno.</target> -<source>Drag && drop</source> -<target>Povleci && spusti</target> - -<source>Could not initialize directory monitoring:</source> -<target>Ne morem začeti nadzorovanja imenikov:</target> - -<source>Error when monitoring directories.</source> -<target>Napaka pri nadzorovanju imenikov.</target> - -<source>Conversion error:</source> -<target>Napaka pri pretvorbi:</target> - -<source>Error deleting file:</source> -<target>Napaka pri brisanju datoteke:</target> - -<source>Error moving file:</source> -<target>Napaka pri premikanju datoteke:</target> - -<source>Target file already existing!</source> -<target>Ciljna datoteka že obstaja!</target> - -<source>Error moving directory:</source> -<target>Napaka pri premikanju imenika:</target> - -<source>Target directory already existing!</source> -<target>Ciljni imenik že obstaja!</target> - -<source>Error deleting directory:</source> -<target>Napaka pri brisanju imenika:</target> - -<source>Error changing modification time:</source> -<target>Napaka pri spreminjanju časa modifikacije:</target> - -<source>Error loading library function:</source> -<target>Napaka pri nalaganju funkcije iz knjižnice:</target> - -<source>Error reading security context:</source> -<target>Napaka pri branju varnostne skladnosti:</target> - -<source>Error writing security context:</source> -<target>Napaka pri pisanju varnostne skladnosti:</target> - -<source>Error copying file permissions:</source> -<target>Napaka pri kopiranju datotečnih dovoljenj:</target> - -<source>Error creating directory:</source> -<target>Napaka pri ustvarjanju imenika:</target> - -<source>Error copying symbolic link:</source> -<target>Napaka pri kopiranju simboličnih povezav:</target> - -<source>Error copying file:</source> -<target>Napaka pri kopiranju datoteke:</target> - -<source>Error opening file:</source> -<target>Napaka pri odpiranju datoteke:</target> - -<source>Error writing file:</source> -<target>Napaka pri pisanju datoteke:</target> - -<source>Error reading file:</source> -<target>Napaka pri branju datoteke:</target> - -<source>Operation aborted!</source> -<target>Operacija prekinjena!</target> - -<source>Endless loop when traversing directory:</source> -<target>Neskončna zanka pri prehodu imenika:</target> - -<source>Error traversing directory:</source> -<target>Napaka pri prehajanju imenika:</target> - -<source>Error setting privilege:</source> -<target>Napaka pri nastavljanju privilegija:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Napaka pri premikanju v Koš:</target> - -<source>Could not load a required DLL:</source> -<target>Ne morem naložiti zahtevano DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Napaka pri pisanju v sinhronizacijsko podatkovno bazo:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Napaka pri dostopu do servisa senčnih kopij!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Ustvarjanje senčnih kopij na WOW63 ni podprto. Prosimo uporabite 64-bitno FreeFileSync različico.</target> - -<source>Could not determine volume name for file:</source> -<target>Ne morem določiti imena volumna za datoteko:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Ime volumna %x ni del imena datoteke %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -<pluralform>%x min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 ura</pluralform> -<pluralform>%x uri</pluralform> -<pluralform>%x ure</pluralform> -<pluralform>%x ur</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dan</pluralform> -<pluralform>%x dni</pluralform> -<pluralform>%x dni</pluralform> -<pluralform>%x dni</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Ne morem brati vrednosti za naslednja XML vozlišča:</target> - <source>Logging</source> <target>Beleženje</target> @@ -489,9 +378,6 @@ Ukazna vrstica se izvrši vsakič ko: <source>Batch execution</source> <target>Paketno izvajanje</target> -<source>Log-messages:</source> -<target>Sporočila beleženja:</target> - <source>Stop</source> <target>Ustavi</target> @@ -618,6 +504,24 @@ Ukazna vrstica se izvrši vsakič ko: <source>Total amount of data that will be transferred</source> <target>Količina podatkov, ki bo prenešena</target> +<source>Operation:</source> +<target>Operacija:</target> + +<source>Items found:</source> +<target>Najdenih elementov:</target> + +<source>Items remaining:</source> +<target>Preostalih elementov:</target> + +<source>Speed:</source> +<target>Hitrost:</target> + +<source>Time remaining:</source> +<target>Preostali čas:</target> + +<source>Time elapsed:</source> +<target>Pretečen čas:</target> + <source>Batch job</source> <target>Paketno opravilo</target> @@ -666,32 +570,14 @@ Ukazna vrstica se izvrši vsakič ko: <source>&Cancel</source> <target>&Prekliči</target> -<source>Operation:</source> -<target>Operacija:</target> - -<source>Items found:</source> -<target>Najdenih elementov:</target> - -<source>Items remaining:</source> -<target>Preostalih elementov:</target> - -<source>Speed:</source> -<target>Hitrost:</target> - -<source>Time remaining:</source> -<target>Preostali čas:</target> - -<source>Time elapsed:</source> -<target>Pretečen čas:</target> - <source>Select variant:</source> <target>Izberite varianto:</target> <source><Automatic></source> <target><Samodejno></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Prepoznaj in širi spremembe na obeh straneh z uporabo podatkovne baze. Izbrisi in spori so zaznani samodejno.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identificiraj in promoviraj spremembe na obeh straneh z uporabo podatkovne baze. Izbrisi, preimenovanja in spori so samodejno zaznani.</target> <source>Mirror ->></source> <target>Zrcalno ->></target> @@ -913,27 +799,19 @@ Izključi: \stuff\temp\* <target>Transakcijsko kopiranje datotek</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Najprej zapisuj v začasno datoteko (*.ffs_tmp) in nato preimenuj. To zagotavlja dosledno stanje celo v primeru usodne napake.</target> <source>Copy locked files</source> <target>Kopiraj zaklenjene datoteke</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopiraj deljene ali zaklenjene datoteke z uporabo servisa Shadow Copy (Zahteva pravice skrbnika) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopiraj deljene ali zaklenjene datoteke z uporabo servisa Shadow Copy (Zahteva pravice skrbnika)</target> <source>Copy file access permissions</source> <target>Kopiraj dovoljenja dostopov datoteke</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika)</target> <source>Hidden dialogs:</source> <target>Skriti pogovori:</target> @@ -965,6 +843,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>&Find next</source> <target>&Najdi naslednje</target> +<source>Operation aborted!</source> +<target>Operacija prekinjena!</target> + <source>Main bar</source> <target>Glavna vrstica</target> @@ -1005,16 +886,16 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <target>Samo-prilagodi stolpce</target> <source>Icon size:</source> -<target></target> +<target>Velikost ikone:</target> <source>Small</source> -<target></target> +<target>Majhna</target> <source>Medium</source> -<target></target> +<target>Srednja</target> <source>Large</source> -<target></target> +<target>Velika</target> <source>Include all rows</source> <target>Vključi se vrstice</target> @@ -1142,6 +1023,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>File list exported!</source> <target>Seznam datotek je bil izvožen!</target> +<source>Error writing file:</source> +<target>Napaka pri pisanju datoteke:</target> + <source>Batch file created successfully!</source> <target>Paketna datoteka je bila uspešno ustvarjena!</target> @@ -1249,9 +1133,6 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Filter: Single pair</source> <target>Filtriraj: En sam par</target> -<source>Ignore</source> -<target>Ignoriraj</target> - <source>Direct</source> <target>Neposredno</target> @@ -1319,6 +1200,111 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Move files into a time-stamped subdirectory</source> <target>Premakni datoteke v časovno-označen podimenik</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +<pluralform>%x min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 ura</pluralform> +<pluralform>%x uri</pluralform> +<pluralform>%x ure</pluralform> +<pluralform>%x ur</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dan</pluralform> +<pluralform>%x dni</pluralform> +<pluralform>%x dni</pluralform> +<pluralform>%x dni</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Ne morem začeti nadzorovanja imenikov:</target> + +<source>Error when monitoring directories.</source> +<target>Napaka pri nadzorovanju imenikov.</target> + +<source>Conversion error:</source> +<target>Napaka pri pretvorbi:</target> + +<source>Error deleting file:</source> +<target>Napaka pri brisanju datoteke:</target> + +<source>Error moving file:</source> +<target>Napaka pri premikanju datoteke:</target> + +<source>Target file already existing!</source> +<target>Ciljna datoteka že obstaja!</target> + +<source>Error moving directory:</source> +<target>Napaka pri premikanju imenika:</target> + +<source>Target directory already existing!</source> +<target>Ciljni imenik že obstaja!</target> + +<source>Error deleting directory:</source> +<target>Napaka pri brisanju imenika:</target> + +<source>Error changing modification time:</source> +<target>Napaka pri spreminjanju časa modifikacije:</target> + +<source>Error loading library function:</source> +<target>Napaka pri nalaganju funkcije iz knjižnice:</target> + +<source>Error reading security context:</source> +<target>Napaka pri branju varnostne skladnosti:</target> + +<source>Error writing security context:</source> +<target>Napaka pri pisanju varnostne skladnosti:</target> + +<source>Error copying file permissions:</source> +<target>Napaka pri kopiranju datotečnih dovoljenj:</target> + +<source>Error creating directory:</source> +<target>Napaka pri ustvarjanju imenika:</target> + +<source>Error copying symbolic link:</source> +<target>Napaka pri kopiranju simboličnih povezav:</target> + +<source>Error copying file:</source> +<target>Napaka pri kopiranju datoteke:</target> + +<source>Error opening file:</source> +<target>Napaka pri odpiranju datoteke:</target> + +<source>Error traversing directory:</source> +<target>Napaka pri prehajanju imenika:</target> + +<source>Endless loop when traversing directory:</source> +<target>Neskončna zanka pri prehodu imenika:</target> + +<source>Error setting privilege:</source> +<target>Napaka pri nastavljanju privilegija:</target> + <source>Both sides have changed since last synchronization!</source> <target>Obe strani sta se spremenili od zadnje sinhronizacije!</target> @@ -1349,9 +1335,6 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Imeniki so v odvisnosti! Bodite pozorni, ko nastavljate sinhronizacijska pravila:</target> -<source>Comparing content of files %x</source> -<target>Primerjam vsebino datotek %x</target> - <source>Memory allocation failed!</source> <target>Neuspešno dodeljevanje pomnilnika!</target> @@ -1367,15 +1350,15 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Symlinks %x have the same date but a different target!</source> <target>Simbolične povezave %x imajo isti datum, vendar različni cilj!</target> +<source>Comparing content of files %x</source> +<target>Primerjam vsebino datotek %x</target> + <source>Comparing files by content failed.</source> <target>Primerjava datotek po vsebini ni uspela.</target> <source>Generating file list...</source> <target>Ustvarjam seznam datotek...</target> -<source>Multiple...</source> -<target>Večkratno...</target> - <source>Both sides are equal</source> <target>Obe strani sta enaki</target> @@ -1394,6 +1377,12 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Delete right file/folder</source> <target>Izbriši desno datoteko/mapo</target> +<source>Move file on left</source> +<target>Premakni datoteko na levo</target> + +<source>Move file on right</source> +<target>Premakni datoteko na desno</target> + <source>Overwrite left file/folder with right one</source> <target>Prepiši levo datoteko/mapo s tisto na desni</target> @@ -1409,6 +1398,9 @@ Prenesi dovoljenja datotek in imenikov (Zahteva pravice skrbnika) <source>Copy file attributes only to right</source> <target>Kopiraj atribute datoteke samo na desno</target> +<source>Multiple...</source> +<target>Večkratno...</target> + <source>Deleting file %x</source> <target>Brisanje datoteke %x</target> diff --git a/BUILD/Languages/spanish.lng b/BUILD/Languages/spanish.lng index f1072972..574aeca1 100644 --- a/BUILD/Languages/spanish.lng +++ b/BUILD/Languages/spanish.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Sincronización Automática</target> -<source>Browse</source> -<target>Examinar</target> - -<source>Windows Error Code %x:</source> -<target>Código de error de Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Código de error de Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Línea de comandos errónea: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Error al resolver enlace simbólico:</target> - -<source>Show pop-up</source> -<target>Mostrar ventana emergente</target> - -<source>Show pop-up on errors or warnings</source> -<target>Mostrar ventana emergente de errores o avisos</target> - -<source>Ignore errors</source> -<target>Ignorar errores</target> - -<source>Hide all error and warning messages</source> -<target>Ocultar todos los mensajes de error y aviso</target> - -<source>Exit instantly</source> -<target>Salir inmediatamente</target> - -<source>Abort synchronization immediately</source> -<target>Abortar sincronización inmediatamente</target> - <source>Select alternate comparison settings</source> <target>Seleccionar opciones alternativas de comparación</target> @@ -113,7 +80,46 @@ <target>Buscar</target> <source>Select time span</source> -<target></target> +<target>Seleccionar duración</target> + +<source>Show pop-up</source> +<target>Mostrar ventana emergente</target> + +<source>Show pop-up on errors or warnings</source> +<target>Mostrar ventana emergente de errores o avisos</target> + +<source>Ignore errors</source> +<target>Ignorar errores</target> + +<source>Hide all error and warning messages</source> +<target>Ocultar todos los mensajes de error y aviso</target> + +<source>Exit instantly</source> +<target>Salir inmediatamente</target> + +<source>Abort synchronization immediately</source> +<target>Abortar sincronización inmediatamente</target> + +<source>Browse</source> +<target>Examinar</target> + +<source>Error reading from synchronization database:</source> +<target>Error al leer de la base de datos de sincronización:</target> + +<source>Error writing to synchronization database:</source> +<target>Error al escribir en la base de datos de sincronización:</target> + +<source>Invalid command line: %x</source> +<target>Línea de comandos errónea: %x</target> + +<source>Windows Error Code %x:</source> +<target>Código de error de Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Código de error de Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Error al resolver enlace simbólico:</target> <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Resultado de la comparación</target> -<source>Incompatible synchronization database format:</source> -<target>Formato de base de datos de sincronización incompatible:</target> - <source>Initial synchronization:</source> <target>Sincronización inicial:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Uno de los archivos de la base de datos de FreeFileSync aún no existe:</target> -<source>Error reading from synchronization database:</source> -<target>Error al leer de la base de datos de sincronización:</target> +<source>Incompatible synchronization database format:</source> +<target>Formato de base de datos de sincronización incompatible:</target> <source>Database files do not share a common synchronization session:</source> <target>Archivos de base de datos no comparten la misma sesión de sincronización:</target> @@ -199,12 +202,18 @@ <pluralform>%x segundos</pluralform> </target> +<source>Drag && drop</source> +<target>Arrastrar y soltar</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Error fatal</target> +<source>Error reading file:</source> +<target>Error al leer archivo:</target> + <source>Scanning:</source> <target>Escanear:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>¡Archivo de configuración de FreeFileSync inválido!</target> -<source>File does not exist:</source> -<target>El archivo no existe:</target> - <source>Error parsing configuration file:</source> <target>Error al analizar el archivo de configuración:</target> +<source>Error moving to Recycle Bin:</source> +<target>Error al mover a la Papelera de Reciclaje:</target> + +<source>Could not load a required DLL:</source> +<target>No se ha podido cargar el DLL solicitado:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>¡Error al acceder al servicio Volume Shadow Copy!</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>La realización de copias shadow en WOW64 no está soportado. Por favor, use la versión 64-bit de FreeFileSync.</target> + +<source>Could not determine volume name for file:</source> +<target>No se ha podido determinar el nombre del volumen para el archivo:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>El nombre del volumen %x no es una parte del nombre de archivo %y</target> + <source>/sec</source> <target>/seg</target> +<source>File does not exist:</source> +<target>El archivo no existe:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>No se ha podido leer los valores para los siguientes nodos XML:</target> + <source>S&ave configuration...</source> <target>G&uardar configuración...</target> @@ -324,141 +354,6 @@ La línea de comandos se ejecuta cada vez: <source>A directory input field is empty.</source> <target>Un campo de directorio está vacío.</target> -<source>Drag && drop</source> -<target>Arrastrar y soltar</target> - -<source>Could not initialize directory monitoring:</source> -<target>No se ha podido inicializar la visualización de directorios:</target> - -<source>Error when monitoring directories.</source> -<target>Error al visualizar los directorios.</target> - -<source>Conversion error:</source> -<target>Error de conversión:</target> - -<source>Error deleting file:</source> -<target>Error al borrar archivo:</target> - -<source>Error moving file:</source> -<target>Error al mover archivo:</target> - -<source>Target file already existing!</source> -<target>¡El archivo de destino ya existe!</target> - -<source>Error moving directory:</source> -<target>Error al mover directorio:</target> - -<source>Target directory already existing!</source> -<target>¡El directorio de destino ya existe!</target> - -<source>Error deleting directory:</source> -<target>Error al borrar directorio:</target> - -<source>Error changing modification time:</source> -<target>Error al cambiar hora de modificación:</target> - -<source>Error loading library function:</source> -<target>Error al cargar la función de biblioteca:</target> - -<source>Error reading security context:</source> -<target>Error al leer en contexto de seguridad:</target> - -<source>Error writing security context:</source> -<target>Error al escribir en contexto de seguridad:</target> - -<source>Error copying file permissions:</source> -<target>Error al copiar permisos del fichero:</target> - -<source>Error creating directory:</source> -<target>Error al crear directorio:</target> - -<source>Error copying symbolic link:</source> -<target>Error al copiar enlace simbólico:</target> - -<source>Error copying file:</source> -<target>Error al copiar archivo:</target> - -<source>Error opening file:</source> -<target>Error al abrir archivo:</target> - -<source>Error writing file:</source> -<target>Error al escribir archivo:</target> - -<source>Error reading file:</source> -<target>Error al leer archivo:</target> - -<source>Operation aborted!</source> -<target>¡Operación abortada!</target> - -<source>Endless loop when traversing directory:</source> -<target>Bucle infinito al buscar en el directorio:</target> - -<source>Error traversing directory:</source> -<target>Error al buscar en el directorio:</target> - -<source>Error setting privilege:</source> -<target>Error al establecer privilegios:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Error al mover a la Papelera de Reciclaje:</target> - -<source>Could not load a required DLL:</source> -<target>No se ha podido cargar el DLL solicitado:</target> - -<source>Error writing to synchronization database:</source> -<target>Error al escribir en la base de datos de sincronización:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>¡Error al acceder al servicio Volume Shadow Copy!</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>La realización de copias shadow en WOW64 no está soportado. Por favor, use la versión 64-bit de FreeFileSync.</target> - -<source>Could not determine volume name for file:</source> -<target>No se ha podido determinar el nombre del volumen para el archivo:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>El nombre del volumen %x no es una parte del nombre de archivo %y</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 minuto</pluralform> -<pluralform>%x minutos</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 hora</pluralform> -<pluralform>%x horas</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 día</pluralform> -<pluralform>%x días</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>No se ha podido leer los valores para los siguientes nodos XML:</target> - <source>Logging</source> <target>Iniciando sesión</target> @@ -477,9 +372,6 @@ La línea de comandos se ejecuta cada vez: <source>Batch execution</source> <target>Ejecución batch</target> -<source>Log-messages:</source> -<target>Registro de mensajes:</target> - <source>Stop</source> <target>Detener</target> @@ -606,6 +498,24 @@ La línea de comandos se ejecuta cada vez: <source>Total amount of data that will be transferred</source> <target>Cantidad total de datos que serán transferidos</target> +<source>Operation:</source> +<target>Operación:</target> + +<source>Items found:</source> +<target>Elementos encontrados:</target> + +<source>Items remaining:</source> +<target>Elementos restantes:</target> + +<source>Speed:</source> +<target>Velocidad:</target> + +<source>Time remaining:</source> +<target>Tiempo restante:</target> + +<source>Time elapsed:</source> +<target>Tiempo transcurrido:</target> + <source>Batch job</source> <target>Tarea batch</target> @@ -654,32 +564,14 @@ La línea de comandos se ejecuta cada vez: <source>&Cancel</source> <target>&Cancelar</target> -<source>Operation:</source> -<target>Operación:</target> - -<source>Items found:</source> -<target>Elementos encontrados:</target> - -<source>Items remaining:</source> -<target>Elementos restantes:</target> - -<source>Speed:</source> -<target>Velocidad:</target> - -<source>Time remaining:</source> -<target>Tiempo restante:</target> - -<source>Time elapsed:</source> -<target>Tiempo transcurrido:</target> - <source>Select variant:</source> <target>Seleccione un tipo:</target> <source><Automatic></source> <target><Automático></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identificar y aplicar cambios en ambos lados usando una base de datos. Las eliminaciones y los conflictos se detectan automáticamente.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Identificar y propagar cambios en ambos lados usando una base de datos. Borrados, renombraciones y conflictos son detectados automáticamente.</target> <source>Mirror ->></source> <target>Espejo ->></target> @@ -901,27 +793,19 @@ Excluir: \stuff\temp\* <target>Copia de archivos transaccionales</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Escribir en archivo temporal (*.ffs_tmp) primero y después renombrarlo. Esto garantiza un estado consistente incluso en caso de error fatal.</target> <source>Copy locked files</source> <target>Copiar archivos bloqueados</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Copiar archivos compartidos o bloqueados usando el servicio "Volume Shadow Copy" (Requiere derechos de administrador) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Copiar archivos compartidos o bloqueados usando el servicio "Volume Shadow Copy" (Requiere derechos de administrador)</target> <source>Copy file access permissions</source> <target>Copiar permisos de acceso al archivo</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Transferir permisos de archivo y directorio (Requiere derechos de administrador) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Transferir permisos de archivo y directorio (Requiere derechos de administrador)</target> <source>Hidden dialogs:</source> <target>Diálogos ocultos:</target> @@ -953,6 +837,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>&Find next</source> <target>&Buscar siguiente</target> +<source>Operation aborted!</source> +<target>¡Operación abortada!</target> + <source>Main bar</source> <target>Barra principal</target> @@ -993,16 +880,16 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <target>Ajustar automáticamente las columnas</target> <source>Icon size:</source> -<target></target> +<target>Tamaño del icono:</target> <source>Small</source> -<target></target> +<target>Pequeño</target> <source>Medium</source> -<target></target> +<target>Medio</target> <source>Large</source> -<target></target> +<target>Grande</target> <source>Include all rows</source> <target>Incluir todas las filas</target> @@ -1130,6 +1017,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>File list exported!</source> <target>¡Lista de archivos exportada!</target> +<source>Error writing file:</source> +<target>Error al escribir archivo:</target> + <source>Batch file created successfully!</source> <target>¡El archivo batch ha sido creado correctamente!</target> @@ -1229,9 +1119,6 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Filter: Single pair</source> <target>Filtro: Sólo un par</target> -<source>Ignore</source> -<target>Ignorar</target> - <source>Direct</source> <target>Enviar</target> @@ -1295,6 +1182,105 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Move files into a time-stamped subdirectory</source> <target>Mover archivos a un subdirectorio con marca de tiempo</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 minuto</pluralform> +<pluralform>%x minutos</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 hora</pluralform> +<pluralform>%x horas</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 día</pluralform> +<pluralform>%x días</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>No se ha podido inicializar la visualización de directorios:</target> + +<source>Error when monitoring directories.</source> +<target>Error al visualizar los directorios.</target> + +<source>Conversion error:</source> +<target>Error de conversión:</target> + +<source>Error deleting file:</source> +<target>Error al borrar archivo:</target> + +<source>Error moving file:</source> +<target>Error al mover archivo:</target> + +<source>Target file already existing!</source> +<target>¡El archivo de destino ya existe!</target> + +<source>Error moving directory:</source> +<target>Error al mover directorio:</target> + +<source>Target directory already existing!</source> +<target>¡El directorio de destino ya existe!</target> + +<source>Error deleting directory:</source> +<target>Error al borrar directorio:</target> + +<source>Error changing modification time:</source> +<target>Error al cambiar hora de modificación:</target> + +<source>Error loading library function:</source> +<target>Error al cargar la función de biblioteca:</target> + +<source>Error reading security context:</source> +<target>Error al leer en contexto de seguridad:</target> + +<source>Error writing security context:</source> +<target>Error al escribir en contexto de seguridad:</target> + +<source>Error copying file permissions:</source> +<target>Error al copiar permisos del fichero:</target> + +<source>Error creating directory:</source> +<target>Error al crear directorio:</target> + +<source>Error copying symbolic link:</source> +<target>Error al copiar enlace simbólico:</target> + +<source>Error copying file:</source> +<target>Error al copiar archivo:</target> + +<source>Error opening file:</source> +<target>Error al abrir archivo:</target> + +<source>Error traversing directory:</source> +<target>Error al buscar en el directorio:</target> + +<source>Endless loop when traversing directory:</source> +<target>Bucle infinito al buscar en el directorio:</target> + +<source>Error setting privilege:</source> +<target>Error al establecer privilegios:</target> + <source>Both sides have changed since last synchronization!</source> <target>¡Ambos lados han cambiado desde la última sincronizacion!</target> @@ -1325,9 +1311,6 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>¡Los directorios son dependientes! Tenga cuidado al establecer las reglas de sincronización:</target> -<source>Comparing content of files %x</source> -<target>Comparación del contenido de los archivos %x</target> - <source>Memory allocation failed!</source> <target>¡La asignación de memoria ha fallado!</target> @@ -1343,15 +1326,15 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Symlinks %x have the same date but a different target!</source> <target>¡Los enlaces simbólicos %x tienen la misma fecha pero un destino diferente!</target> +<source>Comparing content of files %x</source> +<target>Comparación del contenido de los archivos %x</target> + <source>Comparing files by content failed.</source> <target>La comparación de archivos por el contenido ha fallado.</target> <source>Generating file list...</source> <target>Generando lista de archivos...</target> -<source>Multiple...</source> -<target>Múltiple...</target> - <source>Both sides are equal</source> <target>Ambos lados son iguales</target> @@ -1370,6 +1353,12 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Delete right file/folder</source> <target>Eliminar archivo/carpeta de la derecha</target> +<source>Move file on left</source> +<target>Mover archivo a la izquierda</target> + +<source>Move file on right</source> +<target>Mover archivo a la derecha</target> + <source>Overwrite left file/folder with right one</source> <target>Sobreescribir archivo/carpeta de la izquierda por el de la derecha</target> @@ -1385,6 +1374,9 @@ Transferir permisos de archivo y directorio (Requiere derechos de administrador) <source>Copy file attributes only to right</source> <target>Copiar sólo atributos del archivo a la derecha</target> +<source>Multiple...</source> +<target>Múltiple...</target> + <source>Deleting file %x</source> <target>Borrar archivo %x</target> diff --git a/BUILD/Languages/swedish.lng b/BUILD/Languages/swedish.lng index acd17992..07d20948 100644 --- a/BUILD/Languages/swedish.lng +++ b/BUILD/Languages/swedish.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Automatiserad synkronisering</target> -<source>Browse</source> -<target>Bläddra</target> - -<source>Windows Error Code %x:</source> -<target>Windows Felkod %x:</target> - -<source>Linux Error Code %x:</source> -<target>Linux Felkod %x:</target> - -<source>Invalid command line: %x</source> -<target>Ogiltig kommandorad: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Kan inte tyda symbolisk länk:</target> - -<source>Show pop-up</source> -<target>Visa pop-up</target> - -<source>Show pop-up on errors or warnings</source> -<target>Visa pop-up vid fel och varningar</target> - -<source>Ignore errors</source> -<target>Ignorera fel</target> - -<source>Hide all error and warning messages</source> -<target>Visa inte fel- och varningsmeddelanden</target> - -<source>Exit instantly</source> -<target>Avsluta omedelbart</target> - -<source>Abort synchronization immediately</source> -<target>Avbryt synkronisering omedelbart</target> - <source>Select alternate comparison settings</source> <target>Välj alternativa jämförelseinställningar</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Välj tidsintervall</target> +<source>Show pop-up</source> +<target>Visa pop-up</target> + +<source>Show pop-up on errors or warnings</source> +<target>Visa pop-up vid fel och varningar</target> + +<source>Ignore errors</source> +<target>Ignorera fel</target> + +<source>Hide all error and warning messages</source> +<target>Visa inte fel- och varningsmeddelanden</target> + +<source>Exit instantly</source> +<target>Avsluta omedelbart</target> + +<source>Abort synchronization immediately</source> +<target>Avbryt synkronisering omedelbart</target> + +<source>Browse</source> +<target>Bläddra</target> + +<source>Error reading from synchronization database:</source> +<target>Kan inte läsa från databasen:</target> + +<source>Error writing to synchronization database:</source> +<target>Kan inte skriva till databas:</target> + +<source>Invalid command line: %x</source> +<target>Ogiltig kommandorad: %x</target> + +<source>Windows Error Code %x:</source> +<target>Windows Felkod %x:</target> + +<source>Linux Error Code %x:</source> +<target>Linux Felkod %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Kan inte tyda symbolisk länk:</target> + <source>%x MB</source> <target>%x MB</target> @@ -163,17 +169,14 @@ <source>Comparison Result</source> <target>Jämförelseresultat</target> -<source>Incompatible synchronization database format:</source> -<target>Inkompatibelt databasformat:</target> - <source>Initial synchronization:</source> <target>Initial synkronisering:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>En av FreeFileSyncs databasfiler saknas:</target> -<source>Error reading from synchronization database:</source> -<target>Kan inte läsa från databasen:</target> +<source>Incompatible synchronization database format:</source> +<target>Inkompatibelt databasformat:</target> <source>Database files do not share a common synchronization session:</source> <target>Databasfiler delar inte en gemensam synkroniseringssession:</target> @@ -199,12 +202,18 @@ <pluralform>%x sek</pluralform> </target> +<source>Drag && drop</source> +<target>Dra && släpp</target> + <source>Info</source> <target>Info</target> <source>Fatal Error</source> <target>Allvarligt fel</target> +<source>Error reading file:</source> +<target>Kan inte läsa fil:</target> + <source>Scanning:</source> <target>Skannar:</target> @@ -223,15 +232,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Felaktig FreeFileSync konfigurationsfil!</target> -<source>File does not exist:</source> -<target>Filen finns inte:</target> - <source>Error parsing configuration file:</source> <target>Kan inte läsa in konfigurationsfil:</target> +<source>Error moving to Recycle Bin:</source> +<target>Kan inte flytta till papperskorgen:</target> + +<source>Could not load a required DLL:</source> +<target>Kan inte läsa in nödvändig DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Kunde inte starta tjänsten Volume Shadow Copy (VSS)</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Skuggkopior av wow64 stöds ej. Använd FreeFileSync x64 istället!</target> + +<source>Could not determine volume name for file:</source> +<target>Kan inte bestämma volym för fil:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Volymnamn %x saknas i filnamn %y!</target> + <source>/sec</source> <target>/s</target> +<source>File does not exist:</source> +<target>Filen finns inte:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Kan inte läsa värden för följande XML-noder:</target> + <source>S&ave configuration...</source> <target>S¶ inställningar...</target> @@ -324,141 +354,6 @@ Kommandot verkställes när: <source>A directory input field is empty.</source> <target>Ett katalogfält är tomt</target> -<source>Drag && drop</source> -<target>Dra && släpp</target> - -<source>Could not initialize directory monitoring:</source> -<target>Kan inte initiera katalogskanner:</target> - -<source>Error when monitoring directories.</source> -<target>Fel vid övervakning av kataloger.</target> - -<source>Conversion error:</source> -<target>Konversionsfel:</target> - -<source>Error deleting file:</source> -<target>Kan inte ta bort fil:</target> - -<source>Error moving file:</source> -<target>Kan inte flytta fil:</target> - -<source>Target file already existing!</source> -<target>Filen finns redan!</target> - -<source>Error moving directory:</source> -<target>Kan inte flytta katalog:</target> - -<source>Target directory already existing!</source> -<target>Målkatalogen finns redan!</target> - -<source>Error deleting directory:</source> -<target>Kan inte ta bort katalog:</target> - -<source>Error changing modification time:</source> -<target>Kan inte modifiera tidsstämpel:</target> - -<source>Error loading library function:</source> -<target>Kan inte starta biblioteksfunktion:</target> - -<source>Error reading security context:</source> -<target>Kan inte läsa säkerhetskontext:</target> - -<source>Error writing security context:</source> -<target>Kan inte skriva säkerhetskontext:</target> - -<source>Error copying file permissions:</source> -<target>Kan inte kopiera filsystembehörighet:</target> - -<source>Error creating directory:</source> -<target>Kan inte skapa katalog:</target> - -<source>Error copying symbolic link:</source> -<target>Kan inte kopiera symbolisk länk:</target> - -<source>Error copying file:</source> -<target>Kan inte kopiera fil:</target> - -<source>Error opening file:</source> -<target>Kan inte öppna fil:</target> - -<source>Error writing file:</source> -<target>Kan inte skriva fil:</target> - -<source>Error reading file:</source> -<target>Kan inte läsa fil:</target> - -<source>Operation aborted!</source> -<target>Processen avbruten!</target> - -<source>Endless loop when traversing directory:</source> -<target>Oändlig loop vid accessförsök på katalog:</target> - -<source>Error traversing directory:</source> -<target>Accessfel på katalog:</target> - -<source>Error setting privilege:</source> -<target>Kan inte ange privilegie:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Kan inte flytta till papperskorgen:</target> - -<source>Could not load a required DLL:</source> -<target>Kan inte läsa in nödvändig DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Kan inte skriva till databas:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Kunde inte starta tjänsten Volume Shadow Copy (VSS)</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Skuggkopior av wow64 stöds ej. Använd FreeFileSync x64 istället!</target> - -<source>Could not determine volume name for file:</source> -<target>Kan inte bestämma volym för fil:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Volymnamn %x saknas i filnamn %y!</target> - -<source>%x TB</source> -<target>%x TB</target> - -<source>%x PB</source> -<target>%x PB</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>1 timma</pluralform> -<pluralform>%x timmar</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>1 dag</pluralform> -<pluralform>%x dagar</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Kan inte läsa värden för följande XML-noder:</target> - <source>Logging</source> <target>Loggar</target> @@ -477,9 +372,6 @@ Kommandot verkställes när: <source>Batch execution</source> <target>Batch-körning</target> -<source>Log-messages:</source> -<target>Logg-meddelanden:</target> - <source>Stop</source> <target>Stopp</target> @@ -606,6 +498,24 @@ Kommandot verkställes när: <source>Total amount of data that will be transferred</source> <target>Total mängd data som kommer att överföras</target> +<source>Operation:</source> +<target>Arbetsuppgift:</target> + +<source>Items found:</source> +<target>Funna poster:</target> + +<source>Items remaining:</source> +<target>Återstående poster:</target> + +<source>Speed:</source> +<target>Hastighet:</target> + +<source>Time remaining:</source> +<target>Kvarvarande tid:</target> + +<source>Time elapsed:</source> +<target>Förfluten tid:</target> + <source>Batch job</source> <target>Batch-jobb</target> @@ -654,32 +564,14 @@ Kommandot verkställes när: <source>&Cancel</source> <target>&Avbryt</target> -<source>Operation:</source> -<target>Arbetsuppgift:</target> - -<source>Items found:</source> -<target>Funna poster:</target> - -<source>Items remaining:</source> -<target>Återstående poster:</target> - -<source>Speed:</source> -<target>Hastighet:</target> - -<source>Time remaining:</source> -<target>Kvarvarande tid:</target> - -<source>Time elapsed:</source> -<target>Förfluten tid:</target> - <source>Select variant:</source> <target>Välj variant:</target> <source><Automatic></source> <target><Automatisk></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Identifiera och visa förändringar på båda sidor via databas. Borttagningar och konflikter upptäcks automatiskt.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Använd en databas för att identifiera och sprida ändringar på båda sidor. Borttagning, namnbyte och konflikter upptäcks automatiskt</target> <source>Mirror ->></source> <target>Spegla ->></target> @@ -901,27 +793,19 @@ Undanta: \stuff\temp\* <target>Transaktionell filkopiering</target> <source>Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error.</source> -<target></target> +<target>Skriv först till en temporär fil (*.ffs_tmp) och byt sedan namn på den. Detta garanterar en konsistent status även vid allvarliga fel</target> <source>Copy locked files</source> <target>Kopiera låsta filer</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Kopiera delade eller låsta filer med hjälp av Volume Shadow Copy Service (Kräver administratörsrättighet) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Kopiera delade eller låsta filer med hjälp av Volume Shadow Copy Service (Kräver administratörsrättighet)</target> <source>Copy file access permissions</source> <target>Kopiera filåtkomstbehörigheter</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Överför fil- och katalogrättigheter (Kräver administratörsrättigheter) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Överför fil- och katalogrättigheter (Kräver administratörsrättigheter)</target> <source>Hidden dialogs:</source> <target>Dolda meddelanden:</target> @@ -953,6 +837,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>&Sök nästa</target> +<source>Operation aborted!</source> +<target>Processen avbruten!</target> + <source>Main bar</source> <target>Huvudfält</target> @@ -993,16 +880,16 @@ Transfer file and directory permissions (Requires Administrator rights) <target>Autojustera kollumner</target> <source>Icon size:</source> -<target></target> +<target>Ikonstorlek:</target> <source>Small</source> -<target></target> +<target>Liten</target> <source>Medium</source> -<target></target> +<target>Normal</target> <source>Large</source> -<target></target> +<target>Stor</target> <source>Include all rows</source> <target>Inkludera alla rader</target> @@ -1130,6 +1017,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>Fillista exporterad!</target> +<source>Error writing file:</source> +<target>Kan inte skriva fil:</target> + <source>Batch file created successfully!</source> <target>Batch-filen skapades korrekt!</target> @@ -1229,9 +1119,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>Filter: Enstaka undantag</target> -<source>Ignore</source> -<target>Ignorera</target> - <source>Direct</source> <target>Direkt</target> @@ -1295,6 +1182,105 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>Flytta filer till en tidsstämplad underkatalog</target> +<source>%x TB</source> +<target>%x TB</target> + +<source>%x PB</source> +<target>%x PB</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>1 timma</pluralform> +<pluralform>%x timmar</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>1 dag</pluralform> +<pluralform>%x dagar</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Kan inte initiera katalogskanner:</target> + +<source>Error when monitoring directories.</source> +<target>Fel vid övervakning av kataloger.</target> + +<source>Conversion error:</source> +<target>Konversionsfel:</target> + +<source>Error deleting file:</source> +<target>Kan inte ta bort fil:</target> + +<source>Error moving file:</source> +<target>Kan inte flytta fil:</target> + +<source>Target file already existing!</source> +<target>Filen finns redan!</target> + +<source>Error moving directory:</source> +<target>Kan inte flytta katalog:</target> + +<source>Target directory already existing!</source> +<target>Målkatalogen finns redan!</target> + +<source>Error deleting directory:</source> +<target>Kan inte ta bort katalog:</target> + +<source>Error changing modification time:</source> +<target>Kan inte modifiera tidsstämpel:</target> + +<source>Error loading library function:</source> +<target>Kan inte starta biblioteksfunktion:</target> + +<source>Error reading security context:</source> +<target>Kan inte läsa säkerhetskontext:</target> + +<source>Error writing security context:</source> +<target>Kan inte skriva säkerhetskontext:</target> + +<source>Error copying file permissions:</source> +<target>Kan inte kopiera filsystembehörighet:</target> + +<source>Error creating directory:</source> +<target>Kan inte skapa katalog:</target> + +<source>Error copying symbolic link:</source> +<target>Kan inte kopiera symbolisk länk:</target> + +<source>Error copying file:</source> +<target>Kan inte kopiera fil:</target> + +<source>Error opening file:</source> +<target>Kan inte öppna fil:</target> + +<source>Error traversing directory:</source> +<target>Accessfel på katalog:</target> + +<source>Endless loop when traversing directory:</source> +<target>Oändlig loop vid accessförsök på katalog:</target> + +<source>Error setting privilege:</source> +<target>Kan inte ange privilegie:</target> + <source>Both sides have changed since last synchronization!</source> <target>Båda sidor har ändrats sedan senaste synkroniseringen!</target> @@ -1325,9 +1311,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Kataloger är beroende! Var försiktig när du sätter upp synkroniseringsregler:</target> -<source>Comparing content of files %x</source> -<target>Jämför filinnehåll för %x</target> - <source>Memory allocation failed!</source> <target>Minnesallokering misslyckades!</target> @@ -1343,15 +1326,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>Symbolisk länk %x har samma datum, men annat mål!</target> +<source>Comparing content of files %x</source> +<target>Jämför filinnehåll för %x</target> + <source>Comparing files by content failed.</source> <target>Kunde inte jämföra filinnehåll.</target> <source>Generating file list...</source> <target>Skapar fillista...</target> -<source>Multiple...</source> -<target>Multipla...</target> - <source>Both sides are equal</source> <target>Bägge sidor är lika</target> @@ -1370,6 +1353,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>Ta bort höger fil/katalog</target> +<source>Move file on left</source> +<target>Flytta fil på vänster sida</target> + +<source>Move file on right</source> +<target>Flytta fil på höger sida</target> + <source>Overwrite left file/folder with right one</source> <target>Skriv över vänster fil/katalog med den högra</target> @@ -1385,6 +1374,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>Kopiera endast filattribut åt höger</target> +<source>Multiple...</source> +<target>Multipla...</target> + <source>Deleting file %x</source> <target>Tar bort filen %x</target> diff --git a/BUILD/Languages/turkish.lng b/BUILD/Languages/turkish.lng index a360bcd1..2e0622d4 100644 --- a/BUILD/Languages/turkish.lng +++ b/BUILD/Languages/turkish.lng @@ -169,15 +169,15 @@ <source>Comparison Result</source> <target>Karşılaştırma sonucu</target> -<source>Incompatible synchronization database format:</source> -<target>Uyumsuz eşleştirme veritabanı biçimi:</target> - <source>Initial synchronization:</source> <target>Başlangıç eşleştirmesi:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>FreeFileSync veritabanı dosyalarından biri henüz yok:</target> +<source>Incompatible synchronization database format:</source> +<target>Uyumsuz eşleştirme veritabanı biçimi:</target> + <source>Database files do not share a common synchronization session:</source> <target>Veritabanıdosyaları ortak bir eşleştirmeoturumunu paylaşmıyor:</target> @@ -232,9 +232,6 @@ <source>Invalid FreeFileSync config file!</source> <target>Geçersiz FreeFileSync yapılandırma dosyası!</target> -<source>File does not exist:</source> -<target>Dosya bulunamadı:</target> - <source>Error parsing configuration file:</source> <target>Yapılandırma dosyası çözümlenirken hata:</target> @@ -259,6 +256,9 @@ <source>/sec</source> <target>/san</target> +<source>File does not exist:</source> +<target>Dosya bulunamadı:</target> + <source>Could not read values for the following XML nodes:</source> <target>Şu XML düğümlerindeki değerler okunamadı:</target> @@ -372,9 +372,6 @@ Her seferinde çalıştırılacak komut satırı: <source>Batch execution</source> <target>Toplu komut yürütme</target> -<source>Log-messages:</source> -<target>Günlük iletileri:</target> - <source>Stop</source> <target>Durdur</target> @@ -501,6 +498,24 @@ Her seferinde çalıştırılacak komut satırı: <source>Total amount of data that will be transferred</source> <target>Aktarılacak toplam veri miktarı</target> +<source>Operation:</source> +<target>İşlem:</target> + +<source>Items found:</source> +<target>Bulunan bileşenler:</target> + +<source>Items remaining:</source> +<target>Kalan bileşenler:</target> + +<source>Speed:</source> +<target>Hız:</target> + +<source>Time remaining:</source> +<target>Kalan zaman:</target> + +<source>Time elapsed:</source> +<target>Geçen zaman:</target> + <source>Batch job</source> <target>Toplu iş</target> @@ -549,32 +564,14 @@ Her seferinde çalıştırılacak komut satırı: <source>&Cancel</source> <target>İ&ptal</target> -<source>Operation:</source> -<target>İşlem:</target> - -<source>Items found:</source> -<target>Bulunan bileşenler:</target> - -<source>Items remaining:</source> -<target>Kalan bileşenler:</target> - -<source>Speed:</source> -<target>Hız:</target> - -<source>Time remaining:</source> -<target>Kalan zaman:</target> - -<source>Time elapsed:</source> -<target>Geçen zaman:</target> - <source>Select variant:</source> <target>Davranışı seçin:</target> <source><Automatic></source> <target><Kendiliğinden></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Bir veritabanı kullanarak iki yandaki değişiklikleri belirler ve günceller. Silinme ve tutarsızlıklar kendiliğinden algılanır.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>İki yandaki değişiklikleri bir veritabanı kullanarak belirle ve sakla. Silme, yeniden adlandırma ve çakışma işlemleri kendiliğinden algılanır.</target> <source>Mirror ->></source> <target>Yansı ->></target> @@ -801,22 +798,14 @@ Katma: \stuff\temp\* <source>Copy locked files</source> <target>Kilitli dosyaları da kopyala</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Paylaşılan ya da kilitli dosyaları Gölge Kopya Hizmetini kullanarak kopyalar (Yönetici izinlerine gerek duyar) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Paylaşılan ya da kilitli dosyaları Gölge Kopya Hizmetini kullanarak kopyalar (Yönetici izinlerine gerek duyar)</target> <source>Copy file access permissions</source> <target>Dosya erişim izinlerini kopyala</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar)</target> <source>Hidden dialogs:</source> <target>Gizlenmiş iletiler:</target> @@ -1130,9 +1119,6 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Filter: Single pair</source> <target>Süzgeç: Tek çift</target> -<source>Ignore</source> -<target>Yoksay</target> - <source>Direct</source> <target>Doğrudan</target> @@ -1286,12 +1272,12 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Error opening file:</source> <target>Dosya açılırken hata:</target> -<source>Endless loop when traversing directory:</source> -<target>Klasörlerde dolaşırken sonsuz döngü:</target> - <source>Error traversing directory:</source> <target>Klasörde dolaşırken hata:</target> +<source>Endless loop when traversing directory:</source> +<target>Klasörlerde dolaşırken sonsuz döngü:</target> + <source>Error setting privilege:</source> <target>İzinler ayarlanırken hata:</target> @@ -1325,9 +1311,6 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Klasörler bağımlı! Eşleştirme kurallarını koyarken dikkatli olun:</target> -<source>Comparing content of files %x</source> -<target>%x dosyalarının içeriği karşılaştırılıyor</target> - <source>Memory allocation failed!</source> <target>Bellek ayrılamadı!</target> @@ -1343,15 +1326,15 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Symlinks %x have the same date but a different target!</source> <target>Sembolik bağlantılar %x aynı tarihli fakat hedefleri farklı!</target> +<source>Comparing content of files %x</source> +<target>%x dosyalarının içeriği karşılaştırılıyor</target> + <source>Comparing files by content failed.</source> <target>Dosyaların içerikleri karşılaştırılamadı.</target> <source>Generating file list...</source> <target>Dosya listesi oluşturuluyor...</target> -<source>Multiple...</source> -<target>Çoklu...</target> - <source>Both sides are equal</source> <target>İki tarafta aynı</target> @@ -1370,6 +1353,12 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Delete right file/folder</source> <target>Sağdaki dosya/klasörleri sil</target> +<source>Move file on left</source> +<target>Soldaki dosyayı taşı</target> + +<source>Move file on right</source> +<target>Sağdaki dosyayı taşı</target> + <source>Overwrite left file/folder with right one</source> <target>Soldaki dosya/klasörlerin üzerine sağdakileri yaz</target> @@ -1385,6 +1374,9 @@ Dosya ve klasör izinlerini de aktarır (Yönetici izinlerine gerek duyar) <source>Copy file attributes only to right</source> <target>Dosya özniteliklerini yalnız sağa kopyalaya</target> +<source>Multiple...</source> +<target>Çoklu...</target> + <source>Deleting file %x</source> <target>%x dosyası siliniyor</target> diff --git a/BUILD/Languages/ukrainian.lng b/BUILD/Languages/ukrainian.lng index 4973cf06..cfe7e92d 100644 --- a/BUILD/Languages/ukrainian.lng +++ b/BUILD/Languages/ukrainian.lng @@ -22,39 +22,6 @@ <source>RealtimeSync - Automated Synchronization</source> <target>RealtimeSync - Автоматична синхронізація</target> -<source>Browse</source> -<target>Переглянути</target> - -<source>Windows Error Code %x:</source> -<target>Код помилки Windows %x:</target> - -<source>Linux Error Code %x:</source> -<target>Код помилки Linux %x:</target> - -<source>Invalid command line: %x</source> -<target>Неправильний командний рядок: %x</target> - -<source>Error resolving symbolic link:</source> -<target>Помилка при вирішені символічного посилання:</target> - -<source>Show pop-up</source> -<target>Показувати виринаючі вікна</target> - -<source>Show pop-up on errors or warnings</source> -<target>Показувати виринаючі вікна при помилках та попередженнях</target> - -<source>Ignore errors</source> -<target>Ігнорувати помилки</target> - -<source>Hide all error and warning messages</source> -<target>Приховати всі помилки і повідомлення з попередженнями</target> - -<source>Exit instantly</source> -<target>Вийти негайно</target> - -<source>Abort synchronization immediately</source> -<target>Перервати синхронізацію негайно</target> - <source>Select alternate comparison settings</source> <target>Вибрати альтернативні налаштування порівняння</target> @@ -115,6 +82,45 @@ <source>Select time span</source> <target>Виберіть часовий інтервал</target> +<source>Show pop-up</source> +<target>Показувати виринаючі вікна</target> + +<source>Show pop-up on errors or warnings</source> +<target>Показувати виринаючі вікна при помилках та попередженнях</target> + +<source>Ignore errors</source> +<target>Ігнорувати помилки</target> + +<source>Hide all error and warning messages</source> +<target>Приховати всі помилки і повідомлення з попередженнями</target> + +<source>Exit instantly</source> +<target>Вийти негайно</target> + +<source>Abort synchronization immediately</source> +<target>Перервати синхронізацію негайно</target> + +<source>Browse</source> +<target>Переглянути</target> + +<source>Error reading from synchronization database:</source> +<target>Помилка при читанні з бази даних синхронізації:</target> + +<source>Error writing to synchronization database:</source> +<target>Помилка при записі у базу данних синхронізації:</target> + +<source>Invalid command line: %x</source> +<target>Неправильний командний рядок: %x</target> + +<source>Windows Error Code %x:</source> +<target>Код помилки Windows %x:</target> + +<source>Linux Error Code %x:</source> +<target>Код помилки Linux %x:</target> + +<source>Error resolving symbolic link:</source> +<target>Помилка при вирішені символічного посилання:</target> + <source>%x MB</source> <target>%x МБ</target> @@ -164,17 +170,14 @@ <source>Comparison Result</source> <target>Результати порівнювання</target> -<source>Incompatible synchronization database format:</source> -<target>Несумісний формат бази даних синхронізації:</target> - <source>Initial synchronization:</source> <target>Вступна синхронізація:</target> <source>One of the FreeFileSync database files is not yet existing:</source> <target>Файлу бази даних FreeFileSync ще не існує:</target> -<source>Error reading from synchronization database:</source> -<target>Помилка при читанні з бази даних синхронізації:</target> +<source>Incompatible synchronization database format:</source> +<target>Несумісний формат бази даних синхронізації:</target> <source>Database files do not share a common synchronization session:</source> <target>Файли бази даних не мають спільної сесії синхронізації</target> @@ -201,12 +204,18 @@ <pluralform>%x сек</pluralform> </target> +<source>Drag && drop</source> +<target>Drag && drop</target> + <source>Info</source> <target>Інформація</target> <source>Fatal Error</source> <target>Критична помилка</target> +<source>Error reading file:</source> +<target>Помилка при читанні файлу:</target> + <source>Scanning:</source> <target>Сканую:</target> @@ -226,15 +235,36 @@ <source>Invalid FreeFileSync config file!</source> <target>Неправильний файл конфігурації FreeFileSync!</target> -<source>File does not exist:</source> -<target>Файл не існує:</target> - <source>Error parsing configuration file:</source> <target>Помилка при анализі файлу налаштувань синхронізації:</target> +<source>Error moving to Recycle Bin:</source> +<target>Помилка переміщення в "Корзину":</target> + +<source>Could not load a required DLL:</source> +<target>Не вдалося завантажити необхідні DLL:</target> + +<source>Error accessing Volume Shadow Copy Service!</source> +<target>Помилка доступу до послуги Тіньового Копіювання Тому</target> + +<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> +<target>Створення тіньових копій на WOW64 не підтримується. Будь ласка, використайте FreeFileSync 64-розрядної версії.</target> + +<source>Could not determine volume name for file:</source> +<target>Не вдалося визначити назву тому для файлу:</target> + +<source>Volume name %x not part of filename %y!</source> +<target>Ім’я тому %x не є частиною імені файлу %y!</target> + <source>/sec</source> <target>/сек</target> +<source>File does not exist:</source> +<target>Файл не існує:</target> + +<source>Could not read values for the following XML nodes:</source> +<target>Не вдалося прочитати значення таких XML записів:</target> + <source>S&ave configuration...</source> <target>Зберегти налаштування...</target> @@ -327,144 +357,6 @@ The command line is executed each time: <source>A directory input field is empty.</source> <target>Поле введення шляху каталога порожнє.</target> -<source>Drag && drop</source> -<target>Drag && drop</target> - -<source>Could not initialize directory monitoring:</source> -<target>Не вдалося ініціювати каталог для моніторингу:</target> - -<source>Error when monitoring directories.</source> -<target>Помилка моніторингу каталогу.</target> - -<source>Conversion error:</source> -<target>Помилка перетворення:</target> - -<source>Error deleting file:</source> -<target>Помилка при вилученні файлу:</target> - -<source>Error moving file:</source> -<target>Помилка переміщення файлу:</target> - -<source>Target file already existing!</source> -<target>Кінцевий файл уже існує!</target> - -<source>Error moving directory:</source> -<target>Помилка переміщення каталогу:</target> - -<source>Target directory already existing!</source> -<target>Кінцевий каталог вже існує!</target> - -<source>Error deleting directory:</source> -<target>Помилка при вилученні каталогу:</target> - -<source>Error changing modification time:</source> -<target>Помилка при зміні часу модификації файлу:</target> - -<source>Error loading library function:</source> -<target>Помилка при завантаженні функції бібліотеки:</target> - -<source>Error reading security context:</source> -<target>Помилка при читанні контексту безпеки:</target> - -<source>Error writing security context:</source> -<target>Помилка при записі контексту безпеки:</target> - -<source>Error copying file permissions:</source> -<target>Помилка при копіюванні прав доступу:</target> - -<source>Error creating directory:</source> -<target>Помилка при створенні каталогу:</target> - -<source>Error copying symbolic link:</source> -<target>Помилка при копіюванні символьного посилання:</target> - -<source>Error copying file:</source> -<target>Помилка при копіюванні файлу:</target> - -<source>Error opening file:</source> -<target>Помилка при відкриванні файлу:</target> - -<source>Error writing file:</source> -<target>Помилка при записі файлу:</target> - -<source>Error reading file:</source> -<target>Помилка при читанні файлу:</target> - -<source>Operation aborted!</source> -<target>Операція відмінена!</target> - -<source>Endless loop when traversing directory:</source> -<target>Зациклюванння при обході каталогу:</target> - -<source>Error traversing directory:</source> -<target>Помилка обходу каталогу:</target> - -<source>Error setting privilege:</source> -<target>Помилка встановлення привилеїв:</target> - -<source>Error moving to Recycle Bin:</source> -<target>Помилка переміщення в "Корзину":</target> - -<source>Could not load a required DLL:</source> -<target>Не вдалося завантажити необхідні DLL:</target> - -<source>Error writing to synchronization database:</source> -<target>Помилка при записі у базу данних синхронізації:</target> - -<source>Error accessing Volume Shadow Copy Service!</source> -<target>Помилка доступу до послуги Тіньового Копіювання Тому</target> - -<source>Making shadow copies on WOW64 is not supported. Please use FreeFileSync 64-bit version.</source> -<target>Створення тіньових копій на WOW64 не підтримується. Будь ласка, використайте FreeFileSync 64-розрядної версії.</target> - -<source>Could not determine volume name for file:</source> -<target>Не вдалося визначити назву тому для файлу:</target> - -<source>Volume name %x not part of filename %y!</source> -<target>Ім’я тому %x не є частиною імені файлу %y!</target> - -<source>%x TB</source> -<target>%x ТБ</target> - -<source>%x PB</source> -<target>%x ПБ</target> - -<source>%x%</source> -<target>%x%</target> - -<source> -<pluralform>1 min</pluralform> -<pluralform>%x min</pluralform> -</source> -<target> -<pluralform>%x хв</pluralform> -<pluralform>%x хв</pluralform> -<pluralform>%x хв</pluralform> -</target> - -<source> -<pluralform>1 hour</pluralform> -<pluralform>%x hours</pluralform> -</source> -<target> -<pluralform>%x година</pluralform> -<pluralform>%x години</pluralform> -<pluralform>%x годин</pluralform> -</target> - -<source> -<pluralform>1 day</pluralform> -<pluralform>%x days</pluralform> -</source> -<target> -<pluralform>%x день</pluralform> -<pluralform>%x дні</pluralform> -<pluralform>%x днів</pluralform> -</target> - -<source>Could not read values for the following XML nodes:</source> -<target>Не вдалося прочитати значення таких XML записів:</target> - <source>Logging</source> <target>Лог-файли</target> @@ -483,9 +375,6 @@ The command line is executed each time: <source>Batch execution</source> <target>Виконання пакетного завдання</target> -<source>Log-messages:</source> -<target>Лог-повідомлення:</target> - <source>Stop</source> <target>Стоп</target> @@ -615,6 +504,24 @@ The command line is executed each time: <source>Total amount of data that will be transferred</source> <target>Загальний об’єм даних, які будуть передаватися</target> +<source>Operation:</source> +<target>Операція:</target> + +<source>Items found:</source> +<target>Елементів знайдено:</target> + +<source>Items remaining:</source> +<target>Елементів залишилось:</target> + +<source>Speed:</source> +<target>Швидкість:</target> + +<source>Time remaining:</source> +<target>Залишилось часу:</target> + +<source>Time elapsed:</source> +<target>Пройшло часу:</target> + <source>Batch job</source> <target>Пакетне завдання</target> @@ -663,32 +570,14 @@ The command line is executed each time: <source>&Cancel</source> <target>&Відмінити</target> -<source>Operation:</source> -<target>Операція:</target> - -<source>Items found:</source> -<target>Елементів знайдено:</target> - -<source>Items remaining:</source> -<target>Елементів залишилось:</target> - -<source>Speed:</source> -<target>Швидкість:</target> - -<source>Time remaining:</source> -<target>Залишилось часу:</target> - -<source>Time elapsed:</source> -<target>Пройшло часу:</target> - <source>Select variant:</source> <target>Виберіть варіант:</target> <source><Automatic></source> <target><Автоматичний></target> -<source>Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically.</source> -<target>Виявлення і поширення змін на обох сторінах з використанням бази даних. Вилучені файли і конфлікти визначаються автоматично.</target> +<source>Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically.</source> +<target>Виявити та поширити зміни на обидві сторони використовуючи базу даних. Видалення, перейменування та конфлікти визначаються автоматично.</target> <source>Mirror ->></source> <target>Дзеркало ->></target> @@ -911,22 +800,14 @@ Exclude: \stuff\temp\* <source>Copy locked files</source> <target>Копіювати заблоковані файли</target> -<source> -Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights) -</source> -<target> -Копіювати спільних чи заблокованих файлів з використанням послуги Тіньового Копіювання Тому (потрібні права Адміністратора) -</target> +<source>Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)</source> +<target>Копіювати спільних чи заблокованих файлів з використанням послуги Тіньового Копіювання Тому (потрібні права Адміністратора)</target> <source>Copy file access permissions</source> <target>Копіювати права доступу до файлу</target> -<source> -Transfer file and directory permissions (Requires Administrator rights) -</source> -<target> -Передача прав доступу файлу/каталогу (потрібні права Адміністратора) -</target> +<source>Transfer file and directory permissions (Requires Administrator rights)</source> +<target>Передача прав доступу файлу/каталогу (потрібні права Адміністратора)</target> <source>Hidden dialogs:</source> <target>Приховані діалоги</target> @@ -958,6 +839,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>&Find next</source> <target>&Знайти наступний</target> +<source>Operation aborted!</source> +<target>Операція відмінена!</target> + <source>Main bar</source> <target>Головна панель</target> @@ -1135,6 +1019,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>File list exported!</source> <target>Список файлів експортовано!</target> +<source>Error writing file:</source> +<target>Помилка при записі файлу:</target> + <source>Batch file created successfully!</source> <target>Файл завдання успішно створений!</target> @@ -1238,9 +1125,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Filter: Single pair</source> <target>Фільтр: Одна пара</target> -<source>Ignore</source> -<target>Ігнорувати</target> - <source>Direct</source> <target>Прямо</target> @@ -1306,6 +1190,108 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Move files into a time-stamped subdirectory</source> <target>Переміщати файли в підкатлог з часовою міткою</target> +<source>%x TB</source> +<target>%x ТБ</target> + +<source>%x PB</source> +<target>%x ПБ</target> + +<source>%x%</source> +<target>%x%</target> + +<source> +<pluralform>1 min</pluralform> +<pluralform>%x min</pluralform> +</source> +<target> +<pluralform>%x хв</pluralform> +<pluralform>%x хв</pluralform> +<pluralform>%x хв</pluralform> +</target> + +<source> +<pluralform>1 hour</pluralform> +<pluralform>%x hours</pluralform> +</source> +<target> +<pluralform>%x година</pluralform> +<pluralform>%x години</pluralform> +<pluralform>%x годин</pluralform> +</target> + +<source> +<pluralform>1 day</pluralform> +<pluralform>%x days</pluralform> +</source> +<target> +<pluralform>%x день</pluralform> +<pluralform>%x дні</pluralform> +<pluralform>%x днів</pluralform> +</target> + +<source>Could not initialize directory monitoring:</source> +<target>Не вдалося ініціювати каталог для моніторингу:</target> + +<source>Error when monitoring directories.</source> +<target>Помилка моніторингу каталогу.</target> + +<source>Conversion error:</source> +<target>Помилка перетворення:</target> + +<source>Error deleting file:</source> +<target>Помилка при вилученні файлу:</target> + +<source>Error moving file:</source> +<target>Помилка переміщення файлу:</target> + +<source>Target file already existing!</source> +<target>Кінцевий файл уже існує!</target> + +<source>Error moving directory:</source> +<target>Помилка переміщення каталогу:</target> + +<source>Target directory already existing!</source> +<target>Кінцевий каталог вже існує!</target> + +<source>Error deleting directory:</source> +<target>Помилка при вилученні каталогу:</target> + +<source>Error changing modification time:</source> +<target>Помилка при зміні часу модификації файлу:</target> + +<source>Error loading library function:</source> +<target>Помилка при завантаженні функції бібліотеки:</target> + +<source>Error reading security context:</source> +<target>Помилка при читанні контексту безпеки:</target> + +<source>Error writing security context:</source> +<target>Помилка при записі контексту безпеки:</target> + +<source>Error copying file permissions:</source> +<target>Помилка при копіюванні прав доступу:</target> + +<source>Error creating directory:</source> +<target>Помилка при створенні каталогу:</target> + +<source>Error copying symbolic link:</source> +<target>Помилка при копіюванні символьного посилання:</target> + +<source>Error copying file:</source> +<target>Помилка при копіюванні файлу:</target> + +<source>Error opening file:</source> +<target>Помилка при відкриванні файлу:</target> + +<source>Error traversing directory:</source> +<target>Помилка обходу каталогу:</target> + +<source>Endless loop when traversing directory:</source> +<target>Зациклюванння при обході каталогу:</target> + +<source>Error setting privilege:</source> +<target>Помилка встановлення привилеїв:</target> + <source>Both sides have changed since last synchronization!</source> <target>З моменту останньої синхронізації з обох сторін відбулися зміни!</target> @@ -1339,9 +1325,6 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Directories are dependent! Be careful when setting up synchronization rules:</source> <target>Залежні каталоги! Будьте уважні при налаштуванні правил синхронізації:</target> -<source>Comparing content of files %x</source> -<target>Порівнювання вмісту файлів %x</target> - <source>Memory allocation failed!</source> <target>Помилка виділення пам’яті! (Не хватает памяти)</target> @@ -1357,15 +1340,15 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Symlinks %x have the same date but a different target!</source> <target>Символьне посиланння %x має таку ж дату, але різний вміст!</target> +<source>Comparing content of files %x</source> +<target>Порівнювання вмісту файлів %x</target> + <source>Comparing files by content failed.</source> <target>Порівнювання файлів за вмістом не вдалося.</target> <source>Generating file list...</source> <target>Створення списку файлів...</target> -<source>Multiple...</source> -<target>Різні варіанти...</target> - <source>Both sides are equal</source> <target>Сторони ідентичні</target> @@ -1384,6 +1367,12 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Delete right file/folder</source> <target>Вилучити файл/папку праворуч</target> +<source>Move file on left</source> +<target>Перемістити файли ліворуч</target> + +<source>Move file on right</source> +<target>Перемістити файли праворуч</target> + <source>Overwrite left file/folder with right one</source> <target>Перезаписати файл/папку ліворуч відповідником зправа</target> @@ -1399,6 +1388,9 @@ Transfer file and directory permissions (Requires Administrator rights) <source>Copy file attributes only to right</source> <target>Зкопіювати праворуч лише атрибути файлу</target> +<source>Multiple...</source> +<target>Різні варіанти...</target> + <source>Deleting file %x</source> <target>Вилучення файлу %x</target> diff --git a/BUILD/Resources.zip b/BUILD/Resources.zip Binary files differindex d1f7ca37..9ad96f71 100644 --- a/BUILD/Resources.zip +++ b/BUILD/Resources.zip diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp index 14c02576..a81cea63 100644 --- a/FreeFileSync.cbp +++ b/FreeFileSync.cbp @@ -23,7 +23,7 @@ <Linker> <Add option="-s" /> <Add option="-static" /> - <Add library="libboost_thread-mgw46-mt-s-1_47.a" /> + <Add library="libboost_thread-mgw46-mt-s-1_48.a" /> <Add library="libwxmsw28u_aui.a" /> <Add library="libwxmsw28u_adv.a" /> <Add library="libwxmsw28u_core.a" /> @@ -50,7 +50,7 @@ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_dll\mswud" /> </Compiler> <Linker> - <Add library="libboost_thread-mgw46-mt-sd-1_47.a" /> + <Add library="libboost_thread-mgw46-mt-sd-1_48.a" /> <Add library="libwxmsw28ud_aui.a" /> <Add library="libwxmsw28ud_adv.a" /> <Add library="libwxmsw28ud_core.a" /> @@ -77,7 +77,7 @@ <Add directory="lib\gtest\include" /> </Compiler> <Linker> - <Add library="libboost_thread-mgw46-mt-sd-1_47.a" /> + <Add library="libboost_thread-mgw46-mt-sd-1_48.a" /> <Add library="libwxmsw28ud_adv.a" /> <Add library="libwxmsw28ud_core.a" /> <Add library="libwxbase28ud.a" /> diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp index c842e6bb..1f6c8049 100644 --- a/RealtimeSync/RealtimeSync.cbp +++ b/RealtimeSync/RealtimeSync.cbp @@ -27,7 +27,7 @@ <Add library="libwxbase28u.a" /> <Add library="libwxpng.a" /> <Add library="libwxzlib.a" /> - <Add library="libboost_thread-mgw46-mt-s-1_47.a" /> + <Add library="libboost_thread-mgw46-mt-s-1_48.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" /> </Linker> </Target> @@ -51,7 +51,7 @@ <Add library="libwxbase28ud.a" /> <Add library="libwxpngd.a" /> <Add library="libwxzlibd.a" /> - <Add library="libboost_thread-mgw46-mt-sd-1_47.a" /> + <Add library="libboost_thread-mgw46-mt-sd-1_48.a" /> <Add directory="C:\Program Files\C++\wxWidgets\lib\gcc_dll" /> </Linker> </Target> diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp index 97ad480a..52dead7a 100644 --- a/RealtimeSync/watcher.cpp +++ b/RealtimeSync/watcher.cpp @@ -8,6 +8,7 @@ #include <zen/file_handling.h> #include <zen/stl_tools.h> #include <set> +#include <ctime> #include <wx/timer.h> #include "../lib/resolve_path.h" #include <zen/dir_watcher.h> @@ -22,12 +23,14 @@ using namespace zen; bool rts::updateUiIsAllowed() { - static wxLongLong lastExec; - const wxLongLong newExec = wxGetLocalTimeMillis(); + const std::clock_t CLOCK_UPDATE_INTERVAL = UI_UPDATE_INTERVAL * CLOCKS_PER_SEC / 1000; - if (newExec - lastExec >= rts::UI_UPDATE_INTERVAL) //perform ui updates not more often than necessary + static std::clock_t lastExec = 0; + const std::clock_t now = std::clock(); //this is quite fast: 2 * 10^-5 + + if (now - lastExec >= CLOCK_UPDATE_INTERVAL) //perform ui updates not more often than necessary { - lastExec = newExec; + lastExec = now; return true; } return false; @@ -105,7 +108,7 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt, try { - std::vector<Zstring> changedFiles = watcher.getChanges(); //throw FileError, ErrorNotExisting + std::vector<Zstring> changedFiles = watcher.getChanges([&] { statusHandler->requestUiRefresh(); }); //throw FileError, ErrorNotExisting //remove to be ignored changes vector_remove_if(changedFiles, [](const Zstring& name) diff --git a/algorithm.cpp b/algorithm.cpp index 7c6dc5d9..9a3b46f0 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -7,6 +7,7 @@ #include "algorithm.h" #include <iterator> #include <stdexcept> +#include <tuple> #include "lib/resources.h" #include <zen/file_handling.h> #include "lib/recycler.h" @@ -34,9 +35,15 @@ void zen::swapGrids(const MainConfiguration& config, FolderComparison& folderCmp class Redetermine { public: + static void execute(const DirectionSet& dirCfgIn, HierarchyObject& hierObj) + { + Redetermine(dirCfgIn).recurse(hierObj); + } + +private: Redetermine(const DirectionSet& dirCfgIn) : dirCfg(dirCfgIn) {} - void execute(HierarchyObject& hierObj) const + void recurse(HierarchyObject& hierObj) const { std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](FileMapping& fileMap) { (*this)(fileMap); }); std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), [&](SymLinkMapping& linkMap) { (*this)(linkMap); }); @@ -136,11 +143,9 @@ public: break; } - //recursion - execute(dirObj); + recurse(dirObj); } -private: const DirectionSet dirCfg; }; @@ -242,6 +247,8 @@ private: Zstring shortName; //empty if object not existing zen::Int64 lastWriteTime; zen::UInt64 fileSize; + + //note: we do *not* consider FileId here, but are only interested in *visual* changes. Consider user moving data to some other medium, this is not a change! }; @@ -392,6 +399,12 @@ std::pair<DataSetDir, const DirContainer*> retrieveDataSetDir(const Zstring& obj class RedetermineAuto { public: + static void execute(BaseDirMapping& baseDirectory, DeterminationProblem* handler) + { + RedetermineAuto(baseDirectory, handler); + } + +private: RedetermineAuto(BaseDirMapping& baseDirectory, DeterminationProblem* handler) : txtBothSidesChanged(_("Both sides have changed since last synchronization!")), @@ -411,7 +424,7 @@ public: //set conservative "two-way" directions DirectionSet twoWayCfg = getTwoWaySet(); - Redetermine(twoWayCfg).execute(baseDirectory); + Redetermine::execute(twoWayCfg, baseDirectory); return; } @@ -428,13 +441,20 @@ public: if (respectFiltering(baseDirectory, dirInfoRight)) dbFilterRight = dirInfoRight.filter.get(); */ - execute(baseDirectory, + recurse(baseDirectory, &dirInfoLeft.baseDirContainer, &dirInfoRight.baseDirContainer); - } + //----------- detect renamed files ----------------- + if (!exLeftOnly.empty() && !exRightOnly.empty()) + { + findEqualDbEntries(dirInfoLeft.baseDirContainer, //fill map "onceEqual" + dirInfoRight.baseDirContainer); + + detectRenamedFiles(); + } + } -private: /* static bool respectFiltering(const BaseDirMapping& baseDirectory, const DirInformation& dirInfo) { @@ -454,7 +474,7 @@ private: catch (FileErrorDatabaseNotExisting&) {} //let's ignore these errors for now... catch (FileError& error) //e.g. incompatible database version { - if (handler_) handler_->reportWarning(error.toString() + wxT(" \n\n") + + if (handler_) handler_->reportWarning(error.toString() + L" \n\n" + _("Setting default synchronization directions: Old files will be overwritten with newer files.")); } return std::pair<DirInfoPtr, DirInfoPtr>(); //NULL @@ -477,7 +497,7 @@ private: } */ - void execute(HierarchyObject& hierObj, + void recurse(HierarchyObject& hierObj, const DirContainer* dbDirectoryLeft, const DirContainer* dbDirectoryRight) { @@ -499,6 +519,18 @@ private: if (cat == FILE_EQUAL) return; + //----------------- prepare detection of renamed files ----------------- + if (cat == FILE_LEFT_SIDE_ONLY) + { + if (fileObj.getFileId<LEFT_SIDE>() != FileId()) + exLeftOnly.push_back(&fileObj); + } + else if (cat == FILE_RIGHT_SIDE_ONLY) + { + if (fileObj.getFileId<RIGHT_SIDE>() != FileId()) + exRightOnly.insert(std::make_pair(getAssocKey<RIGHT_SIDE>(fileObj), &fileObj)); + } + //---------------------------------------------------------------------- //##################### schedule potentially existing temporary files for deletion #################### if (cat == FILE_LEFT_SIDE_ONLY && endsWith(fileObj.getFullName<LEFT_SIDE>(), zen::TEMP_FILE_ENDING)) @@ -530,14 +562,14 @@ private: const DataSetFile dataDbLeft = retrieveDataSetFile(fileObj.getObjShortName(), dbDirectoryLeft); const DataSetFile dataDbRight = retrieveDataSetFile(fileObj.getObjShortName(), dbDirectoryRight); - const DataSetFile dataCurrentLeft( fileObj, Int2Type<LEFT_SIDE>()); + const DataSetFile dataCurrentLeft (fileObj, Int2Type<LEFT_SIDE >()); const DataSetFile dataCurrentRight(fileObj, Int2Type<RIGHT_SIDE>()); //evaluation const bool changeOnLeft = dataDbLeft != dataCurrentLeft; const bool changeOnRight = dataDbRight != dataCurrentRight; - if (dataDbLeft == dataDbRight) //last sync seems to have been successful + if (dataDbLeft == dataDbRight) //we have a "last synchronous state" => last sync seems to have been successful { if (changeOnLeft) { @@ -651,7 +683,7 @@ private: ; } - SetDirChangedFilter().execute(dirObj); //filter issue for this directory => treat subfiles/-dirs the same + SetDirChangedFilter().recurse(dirObj); //filter issue for this directory => treat subfiles/-dirs the same return; } */ @@ -711,18 +743,133 @@ private: } } - execute(dirObj, dataDbLeftStuff.second, dataDbRightStuff.second); //recursion + recurse(dirObj, dataDbLeftStuff.second, dataDbRightStuff.second); //recursion } + + void findEqualDbEntries(const DirContainer& dbDirectoryLeft, + const DirContainer& dbDirectoryRight) + { + //note: we cannot integrate this traversal into "recurse()" since it may take a *slightly* different path: e.g. file renamed on both sides + + std::for_each(dbDirectoryLeft.files.begin(), dbDirectoryLeft.files.end(), + [&](const DirContainer::FileList::value_type& entryLeft) + { + auto iterRight = dbDirectoryRight.files.find(entryLeft.first); + if (iterRight != dbDirectoryRight.files.end()) + { + if (entryLeft. second.id != FileId() && + iterRight->second.id != FileId() && + DataSetFile(entryLeft.first, entryLeft.second) == DataSetFile(iterRight->first, iterRight->second)) + onceEqual.insert(std::make_pair(getAssocKey(entryLeft.second), getAssocKey(iterRight->second))); + } + }); + + std::for_each(dbDirectoryLeft.dirs.begin(), dbDirectoryLeft.dirs.end(), + [&](const DirContainer::DirList::value_type& entryLeft) + { + auto iterRight = dbDirectoryRight.dirs.find(entryLeft.first); + if (iterRight != dbDirectoryRight.dirs.end()) + findEqualDbEntries(entryLeft.second, iterRight->second); + }); + } + + typedef std::tuple<Int64, UInt64, FileId> AssocKey; //(date, size, file ID) + + + //modification date is *not* considered as part of container key, so check here! + template <class Container> + static typename Container::const_iterator findValue(const Container& cnt, const AssocKey& key) + { + auto iterPair = cnt.equal_range(key); //since file id is already unique, we expect a single-element range at most + auto iter = std::find_if(iterPair.first, iterPair.second, + [&](const typename Container::value_type& item) + { + return sameFileTime(std::get<0>(item.first), std::get<0>(key), 2); //respect 2 second FAT/FAT32 precision + }); + return iter == iterPair.second ? cnt.end() : iter; + } + + void detectRenamedFiles() const + { + std::for_each(exLeftOnly.begin(), exLeftOnly.end(), + [&](FileMapping* fileLeftOnly) + { + const AssocKey& keyLeft = RedetermineAuto::getAssocKey<LEFT_SIDE>(*fileLeftOnly); + + auto iter = findValue(onceEqual, keyLeft); + if (iter != onceEqual.end()) + { + const AssocKey& keyRight = iter->second; + + auto iter2 = findValue(exRightOnly, keyRight); + if (iter2 != exRightOnly.end()) + { + FileMapping* fileRightOnly = iter2->second; + + //found a pair, mark it! + fileLeftOnly ->setMoveRef(fileRightOnly->getId()); + fileRightOnly->setMoveRef(fileLeftOnly ->getId()); + } + } + }); + } + + const std::wstring txtBothSidesChanged; const std::wstring txtNoSideChanged; const std::wstring txtFilterChanged; const std::wstring txtLastSyncFail; - //const HardFilter* dbFilterLeft; //optional - //const HardFilter* dbFilterRight; //optional - DeterminationProblem* const handler_; + + //detection of renamed files + template <SelectedSide side> + static AssocKey getAssocKey(const FileMapping& fsObj) { return std::make_tuple(fsObj.getLastWriteTime<side>(), fsObj.getFileSize<side>(), fsObj.getFileId<side>()); } + static AssocKey getAssocKey(const FileDescriptor& fileDescr) { return std::make_tuple(fileDescr.lastWriteTimeRaw, fileDescr.fileSize, fileDescr.id); } + + struct LessAssocKey + { + bool operator()(const AssocKey& lhs, const AssocKey& rhs) const + { + //caveat: *don't* allow 2 sec tolerance as container predicate!! + // => no strict weak ordering relation! reason: no transitivity of equivalence! + + //-> bad: if (!sameFileTime(std::get<0>(lhs), std::get<0>(rhs), 2)) + // return std::get<0>(lhs) < std::get<0>(rhs); + + if (std::get<1>(lhs) != std::get<1>(rhs)) //file size + return std::get<1>(lhs) < std::get<1>(rhs); + + return std::get<2>(lhs) < std::get<2>(rhs); //file id + } + }; + + std::vector<FileMapping*> exLeftOnly; + + std::multimap<AssocKey, AssocKey, LessAssocKey> onceEqual; //keys for left and right files which are considered "equal" by database + + std::multimap<AssocKey, FileMapping*, LessAssocKey> exRightOnly; + + /* + detect renamed files + + X -> |_| Create right + |_| -> Y Delete right + + is detected as: + + Rename Y to X on right + + Algorithm: + ---------- + DB-file left --- name, size, date ---> DB-file right + /|\ | + | file ID, size, date + file ID, size, date | + | \|/ + X Y + */ }; @@ -750,11 +897,11 @@ std::vector<DirectionConfig> zen::extractDirectionCfg(const MainConfiguration& m void zen::redetermineSyncDirection(const DirectionConfig& directConfig, BaseDirMapping& baseDirectory, DeterminationProblem* handler) { if (directConfig.var == DirectionConfig::AUTOMATIC) - RedetermineAuto(baseDirectory, handler); + RedetermineAuto::execute(baseDirectory, handler); else { DirectionSet dirCfg = extractDirections(directConfig); - Redetermine(dirCfg).execute(baseDirectory); + Redetermine::execute(dirCfg, baseDirectory); } } diff --git a/algorithm.h b/algorithm.h index 6eb9f24d..96ff6b1a 100644 --- a/algorithm.h +++ b/algorithm.h @@ -17,7 +17,7 @@ void swapGrids(const MainConfiguration& config, FolderComparison& folderCmp); struct DeterminationProblem //callback { virtual ~DeterminationProblem() {} - virtual void reportWarning(const wxString& text) = 0; + virtual void reportWarning(const std::wstring& text) = 0; }; std::vector<DirectionConfig> extractDirectionCfg(const MainConfiguration& mainCfg); @@ -56,7 +56,7 @@ public: IGNORE_ERROR = 10, RETRY }; - virtual Response reportError(const wxString& errorMessage) = 0; + virtual Response reportError(const std::wstring& errorMessage) = 0; //virtual void totalFilesToDelete(int objectsTotal) = 0; //informs about the total number of files to be deleted virtual void notifyDeletion(const Zstring& currentObject) = 0; //called for each file/folder that has been deleted diff --git a/comparison.cpp b/comparison.cpp index 79b18ae9..f66c291e 100644 --- a/comparison.cpp +++ b/comparison.cpp @@ -5,16 +5,16 @@ // ************************************************************************** #include "comparison.h" +#include <stdexcept> +#include <zen/scope_guard.h> +#include <wx+/string_conv.h> +#include <wx+/format_unit.h> #include "lib/parallel_scan.h" #include "lib/resolve_path.h" -#include <stdexcept> #include "lib/dir_exist_async.h" -#include <wx+/string_conv.h> -#include <zen/scope_guard.h> #include "lib/binary.h" -#include "algorithm.h" -#include <wx+/format_unit.h> #include "lib/cmp_filetime.h" +#include "algorithm.h" #ifdef FFS_WIN #include <zen/perf.h> @@ -120,39 +120,33 @@ void checkDirectoryExistence(const std::set<Zstring, LessFilename>& dirnames, } -namespace -{ -struct EqualDependentDirectory : public std::binary_function<Zstring, Zstring, bool> -{ - bool operator()(const Zstring& lhs, const Zstring& rhs) const - { - return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), - Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); - } -}; -} - //check whether one side is subdirectory of other side (folder pair wise!) //similar check if one directory is read/written by multiple pairs not before beginning of synchronization -wxString checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm) //returns warning message, empty if all ok +std::wstring checkFolderDependency(const std::vector<FolderPairCfg>& folderPairsForm) //returns warning message, empty if all ok { - typedef std::vector<std::pair<wxString, wxString> > DirDirList; + typedef std::vector<std::pair<std::wstring, std::wstring> > DirDirList; DirDirList dependentDirs; + auto dependentDir = [](const Zstring& lhs, const Zstring& rhs) + { + return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), //note: this is NOT an equivalence relation! + Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); + }; + for (std::vector<FolderPairCfg>::const_iterator i = folderPairsForm.begin(); i != folderPairsForm.end(); ++i) if (!i->leftDirectoryFmt.empty() && !i->rightDirectoryFmt.empty()) //empty folders names may be accepted by user { - if (EqualDependentDirectory()(i->leftDirectoryFmt, i->rightDirectoryFmt)) //test wheter leftDirectory begins with rightDirectory or the other way round - dependentDirs.push_back(std::make_pair(toWx(i->leftDirectoryFmt), toWx(i->rightDirectoryFmt))); + if (dependentDir(i->leftDirectoryFmt, i->rightDirectoryFmt)) //test wheter leftDirectory begins with rightDirectory or the other way round + dependentDirs.push_back(std::make_pair(utf8CvrtTo<std::wstring>(i->leftDirectoryFmt), utf8CvrtTo<std::wstring>(i->rightDirectoryFmt))); } - wxString warningMsg; + std::wstring warningMsg; if (!dependentDirs.empty()) { warningMsg = _("Directories are dependent! Be careful when setting up synchronization rules:"); for (auto i = dependentDirs.begin(); i != dependentDirs.end(); ++i) - warningMsg += wxString(L"\n\n") + + warningMsg += std::wstring(L"\n\n") + L"\"" + i->first + L"\"\n" + L"\"" + i->second + L"\""; } @@ -214,17 +208,17 @@ CompareProcess::CompareProcess(size_t fileTimeTol, m_warnings(warnings), allowUserInteraction_(allowUserInteraction), procCallback(handler) - { -if (runWithBackgroundPriority) -procBackground.reset(new ScheduleForBackgroundProcessing); - } +{ + if (runWithBackgroundPriority) + procBackground.reset(new ScheduleForBackgroundProcessing); +} void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgList, FolderComparison& output) { - //prevent shutdown while (binary) comparison is in progress - DisableStandby dummy2; - (void)dummy2; + //prevent shutdown while (binary) comparison is in progress + PreventStandby dummy2; + (void)dummy2; /* #ifdef NDEBUG @@ -257,9 +251,9 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgLi { //check if folders have dependencies - wxString warningMessage = checkFolderDependency(cfgList); + std::wstring warningMessage = checkFolderDependency(cfgList); if (!warningMessage.empty()) - procCallback.reportWarning(warningMessage.c_str(), m_warnings.warningDependentFolders); + procCallback.reportWarning(warningMessage, m_warnings.warningDependentFolders); } //-------------------end of basic checks------------------------------------------ @@ -364,7 +358,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& cfgLi warningSyncDatabase_(warningSyncDatabase), procCallback_(procCallback) {} - virtual void reportWarning(const wxString& text) + virtual void reportWarning(const std::wstring& text) { procCallback_.reportWarning(text, warningSyncDatabase_); } @@ -404,25 +398,14 @@ std::wstring getConflictInvalidDate(const Zstring& fileNameFull, Int64 utcTime) namespace { -inline -void makeSameLength(wxString& first, wxString& second) -{ - const size_t maxPref = std::max(first.length(), second.length()); - first.Pad(maxPref - first.length(), wxT(' '), true); - second.Pad(maxPref - second.length(), wxT(' '), true); -} - - //check for changed files with same modification date std::wstring getConflictSameDateDiffSize(const FileMapping& fileObj) { std::wstring msg = _("Files %x have the same date but a different size!"); replace(msg, L"%x", std::wstring(L"\"") + fileObj.getRelativeName<LEFT_SIDE>() + L"\""); msg += L"\n\n"; - msg += L"<-- \t" + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<LEFT_SIDE>()) + - L" \t" + _("Size") + L": " + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + L"\n"; - msg += L"--> \t" + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<RIGHT_SIDE>()) + - L" \t" + _("Size") + L": " + toStringSep(fileObj.getFileSize<RIGHT_SIDE>()); + msg += L"<-- " + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<LEFT_SIDE >()) + L" " + _("Size") + L": " + toStringSep(fileObj.getFileSize<LEFT_SIDE>()) + L"\n"; + msg += L"--> " + _("Date") + L": " + utcToLocalTimeString(fileObj.getLastWriteTime<RIGHT_SIDE>()) + L" " + _("Size") + L": " + toStringSep(fileObj.getFileSize<RIGHT_SIDE>()); return _("Conflict detected:") + L"\n" + msg; } } @@ -625,7 +608,7 @@ void CompareProcess::compareByContent(std::vector<std::pair<FolderPairCfg, BaseD const CmpFileTime timeCmp(fileTimeTolerance); -const std::wstring txtComparingContentOfFiles = replaceCpy(_("Comparing content of files %x"), L"%x", L"\n\"%x\"", false); + const std::wstring txtComparingContentOfFiles = replaceCpy(_("Comparing content of files %x"), L"%x", L"\n\"%x\"", false); //compare files (that have same size) bytewise... std::for_each(filesToCompareBytewise.begin(), filesToCompareBytewise.end(), @@ -697,36 +680,19 @@ private: }; -template <> -void MergeSides::fillOneSide<LEFT_SIDE>(const DirContainer& dirCont, HierarchyObject& output) -{ - for (DirContainer::FileList::const_iterator i = dirCont.files.begin(); i != dirCont.files.end(); ++i) - output.addSubFile(i->second, i->first); - - for (DirContainer::LinkList::const_iterator i = dirCont.links.begin(); i != dirCont.links.end(); ++i) - output.addSubLink(i->second, i->first); - - for (DirContainer::DirList::const_iterator i = dirCont.dirs.begin(); i != dirCont.dirs.end(); ++i) - { - DirMapping& newDirMap = output.addSubDir(i->first, Zstring()); - fillOneSide<LEFT_SIDE>(i->second, newDirMap); //recurse into subdirectories - } -} - - -template <> -void MergeSides::fillOneSide<RIGHT_SIDE>(const DirContainer& dirCont, HierarchyObject& output) +template <SelectedSide side> +void MergeSides::fillOneSide(const DirContainer& dirCont, HierarchyObject& output) { - for (DirContainer::FileList::const_iterator i = dirCont.files.begin(); i != dirCont.files.end(); ++i) - output.addSubFile(i->first, i->second); + for (auto iter = dirCont.files.cbegin(); iter != dirCont.files.cend(); ++iter) + output.addSubFile<side>(iter->first, iter->second); - for (DirContainer::LinkList::const_iterator i = dirCont.links.begin(); i != dirCont.links.end(); ++i) - output.addSubLink(i->first, i->second); + for (auto iter = dirCont.links.cbegin(); iter != dirCont.links.cend(); ++iter) + output.addSubLink<side>(iter->first, iter->second); - for (DirContainer::DirList::const_iterator i = dirCont.dirs.begin(); i != dirCont.dirs.end(); ++i) + for (auto iter = dirCont.dirs.cbegin(); iter != dirCont.dirs.cend(); ++iter) { - DirMapping& newDirMap = output.addSubDir(Zstring(), i->first); - fillOneSide<RIGHT_SIDE>(i->second, newDirMap); //recurse into subdirectories + DirMapping& newDirMap = output.addSubDir<side>(iter->first); + fillOneSide<side>(iter->second, newDirMap); //recurse } } @@ -777,8 +743,8 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right typedef const DirContainer::FileList::value_type FileData; linearMerge(leftSide.files, rightSide.files, - [&](const FileData& fileLeft) { output.addSubFile(fileLeft.second, fileLeft.first); }, //left only - [&](const FileData& fileRight) { output.addSubFile(fileRight.first, fileRight.second); }, //right only + [&](const FileData& fileLeft) { output.addSubFile<LEFT_SIDE> (fileLeft.first, fileLeft.second); }, //left only + [&](const FileData& fileRight) { output.addSubFile<RIGHT_SIDE>(fileRight.first, fileRight.second); }, //right only [&](const FileData& fileLeft, const FileData& fileRight) //both sides { @@ -794,8 +760,8 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right typedef const DirContainer::LinkList::value_type LinkData; linearMerge(leftSide.links, rightSide.links, - [&](const LinkData& linkLeft) { output.addSubLink(linkLeft.second, linkLeft.first); }, //left only - [&](const LinkData& linkRight) { output.addSubLink(linkRight.first, linkRight.second); }, //right only + [&](const LinkData& linkLeft) { output.addSubLink<LEFT_SIDE >(linkLeft.first, linkLeft.second); }, //left only + [&](const LinkData& linkRight) { output.addSubLink<RIGHT_SIDE>(linkRight.first, linkRight.second); }, //right only [&](const LinkData& linkLeft, const LinkData& linkRight) //both sides { @@ -813,12 +779,12 @@ void MergeSides::execute(const DirContainer& leftSide, const DirContainer& right linearMerge(leftSide.dirs, rightSide.dirs, [&](const DirData& dirLeft) //left only { - DirMapping& newDirMap = output.addSubDir(dirLeft.first, Zstring()); + DirMapping& newDirMap = output.addSubDir<LEFT_SIDE>(dirLeft.first); this->fillOneSide<LEFT_SIDE>(dirLeft.second, newDirMap); //recurse into subdirectories }, [&](const DirData& dirRight) //right only { - DirMapping& newDirMap = output.addSubDir(Zstring(), dirRight.first); + DirMapping& newDirMap = output.addSubDir<RIGHT_SIDE>(dirRight.first); this->fillOneSide<RIGHT_SIDE>(dirRight.second, newDirMap); //recurse into subdirectories }, @@ -839,7 +805,7 @@ void processFilteredDirs(HierarchyObject& hierObj, const HardFilter& filterProc) std::for_each(subDirs.begin(), subDirs.end(), [&](DirMapping& dirObj) { - dirObj.setActive(filterProc.passDirFilter(dirObj.getObjRelativeName().c_str(), NULL)); //subObjMightMatch is always true in this context! + dirObj.setActive(filterProc.passDirFilter(dirObj.getObjRelativeName(), NULL)); //subObjMightMatch is always true in this context! processFilteredDirs(dirObj, filterProc); }); @@ -878,7 +844,6 @@ void CompareProcess::performComparison(const FolderPairCfg& fpCfg, const DirectoryValue& bufValueRight = getDirValue(fpCfg.rightDirectoryFmt); procCallback.reportStatus(_("Generating file list...")); - procCallback.forceUiRefresh(); //keep total number of scanned files up to date //PERF_START; MergeSides(undefinedFiles, undefinedLinks).execute(bufValueLeft.dirCont, bufValueRight.dirCont, output); diff --git a/comparison.h b/comparison.h index 3928f44e..f3226e90 100644 --- a/comparison.h +++ b/comparison.h @@ -7,11 +7,11 @@ #ifndef COMPARISON_H_INCLUDED #define COMPARISON_H_INCLUDED +#include <zen/process_status.h> #include "file_hierarchy.h" #include "lib/process_xml.h" #include "lib/status_handler.h" #include "structures.h" -#include <zen/process_status.h> #include "lib/norm_filter.h" #include "lib/parallel_scan.h" diff --git a/file_hierarchy.cpp b/file_hierarchy.cpp index cfe1b6a0..39b789fd 100644 --- a/file_hierarchy.cpp +++ b/file_hierarchy.cpp @@ -5,6 +5,8 @@ // ************************************************************************** #include "file_hierarchy.h" +#include <zen/i18n.h> +#include <zen/utf8.h> using namespace zen; @@ -31,12 +33,12 @@ void HierarchyObject::removeEmptyRec() std::for_each(refSubDirs().begin(), refSubDirs().end(), std::mem_fun_ref(&HierarchyObject::removeEmptyRec)); } - -SyncOperation FileSystemObject::getSyncOperation( - CompareFilesResult cmpResult, - bool selectedForSynchronization, - SyncDirection syncDir, - const std::wstring& syncDirConflict) +namespace +{ +SyncOperation proposedSyncOperation(CompareFilesResult cmpResult, + bool selectedForSynchronization, + SyncDirection syncDir, + const std::wstring& syncDirConflict) { if (!selectedForSynchronization) return cmpResult == FILE_EQUAL ? @@ -105,8 +107,6 @@ SyncOperation FileSystemObject::getSyncOperation( } -namespace -{ template <class Predicate> inline bool hasDirectChild(const HierarchyObject& hierObj, Predicate p) { @@ -117,6 +117,22 @@ bool hasDirectChild(const HierarchyObject& hierObj, Predicate p) } +SyncOperation FileSystemObject::testSyncOperation(SyncDirection testSyncDir) const +{ + return proposedSyncOperation(getCategory(), selectedForSynchronization, testSyncDir, syncDirConflict); +} + + +SyncOperation FileSystemObject::getSyncOperation() const +{ + return FileSystemObject::testSyncOperation(syncDir); + //no *not* make a virtual call to testSyncOperation()! See FileMapping::testSyncOperation()! +} + + +//SyncOperation DirMapping::testSyncOperation() const -> not required: we do NOT want to consider child elements when testing! + + SyncOperation DirMapping::getSyncOperation() const { if (!syncOpUpToDate) @@ -124,7 +140,7 @@ SyncOperation DirMapping::getSyncOperation() const syncOpUpToDate = true; //redetermine... - //suggested operation for directory only + //suggested operation *not* considering child elements syncOpBuffered = FileSystemObject::getSyncOperation(); //action for child elements may occassionally have to overwrite parent task: @@ -132,6 +148,10 @@ SyncOperation DirMapping::getSyncOperation() const { case SO_OVERWRITE_LEFT: case SO_OVERWRITE_RIGHT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: assert(false); case SO_CREATE_NEW_LEFT: case SO_CREATE_NEW_RIGHT: @@ -149,19 +169,32 @@ SyncOperation DirMapping::getSyncOperation() const //1. if at least one child-element is to be created, make sure parent folder is created also //note: this automatically fulfills "create parent folders even if excluded"; //see http://sourceforge.net/tracker/index.php?func=detail&aid=2628943&group_id=234430&atid=1093080 - if (hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() == SO_CREATE_NEW_LEFT; })) - syncOpBuffered = SO_CREATE_NEW_LEFT; + if (hasDirectChild(*this, + [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_LEFT || op == SO_MOVE_LEFT_TARGET; })) + syncOpBuffered = SO_CREATE_NEW_LEFT; //2. cancel parent deletion if only a single child is not also scheduled for deletion else if (syncOpBuffered == SO_DELETE_RIGHT && - hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() != SO_DELETE_RIGHT; })) + hasDirectChild(*this, + [](const FileSystemObject& fsObj) -> bool + { + if (fsObj.isEmpty()) return false; //fsObj may already be empty because it once contained a "move source" + const SyncOperation op = fsObj.getSyncOperation(); return op != SO_DELETE_RIGHT && op != SO_MOVE_RIGHT_SOURCE; + })) syncOpBuffered = SO_DO_NOTHING; } else if (isEmpty<RIGHT_SIDE>()) { - if (hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() == SO_CREATE_NEW_RIGHT; })) - syncOpBuffered = SO_CREATE_NEW_RIGHT; + if (hasDirectChild(*this, + [](const FileSystemObject& fsObj) -> bool { const SyncOperation op = fsObj.getSyncOperation(); return op == SO_CREATE_NEW_RIGHT || op == SO_MOVE_RIGHT_TARGET; })) + syncOpBuffered = SO_CREATE_NEW_RIGHT; else if (syncOpBuffered == SO_DELETE_LEFT && - hasDirectChild(*this, [](const FileSystemObject& fsObj) { return fsObj.getSyncOperation() != SO_DELETE_LEFT; })) + hasDirectChild(*this, + [](const FileSystemObject& fsObj) -> bool + { + if (fsObj.isEmpty()) return false; + const SyncOperation op = fsObj.getSyncOperation(); + return op != SO_DELETE_LEFT && op != SO_MOVE_LEFT_SOURCE; + })) syncOpBuffered = SO_DO_NOTHING; } } @@ -170,3 +203,167 @@ SyncOperation DirMapping::getSyncOperation() const } return syncOpBuffered; } + + +SyncOperation FileMapping::testSyncOperation(SyncDirection testSyncDir) const +{ + SyncOperation op = FileSystemObject::testSyncOperation(testSyncDir); + + /* + check whether we can optimize "create + delete" via "move": + note: as long as we consider "create + delete" cases only, detection of renamed files, should be fine even for "binary" comparison variant! + */ + if (const FileMapping* refFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(moveFileRef))) + { + SyncOperation opRef = refFile->FileSystemObject::getSyncOperation(); //do *not* make a virtual call! + + if (op == SO_CREATE_NEW_LEFT && + opRef == SO_DELETE_LEFT) + op = SO_MOVE_LEFT_TARGET; + else if (op == SO_DELETE_LEFT && + opRef == SO_CREATE_NEW_LEFT) + op = SO_MOVE_LEFT_SOURCE; + else if (op == SO_CREATE_NEW_RIGHT && + opRef == SO_DELETE_RIGHT) + op = SO_MOVE_RIGHT_TARGET; + else if (op == SO_DELETE_RIGHT && + opRef == SO_CREATE_NEW_RIGHT) + op = SO_MOVE_RIGHT_SOURCE; + } + return op; +} + + +SyncOperation FileMapping::getSyncOperation() const +{ + return FileMapping::testSyncOperation(getSyncDir()); +} + + +std::wstring zen::getCategoryDescription(CompareFilesResult cmpRes) +{ + switch (cmpRes) + { + case FILE_LEFT_SIDE_ONLY: + return _("File/folder exists on left side only"); + case FILE_RIGHT_SIDE_ONLY: + return _("File/folder exists on right side only"); + case FILE_LEFT_NEWER: + return _("Left file is newer"); + case FILE_RIGHT_NEWER: + return _("Right file is newer"); + case FILE_DIFFERENT: + return _("Files have different content"); + case FILE_EQUAL: + return _("Both sides are equal"); + case FILE_DIFFERENT_METADATA: + return _("Files/folders differ in attributes only"); + case FILE_CONFLICT: + return _("Conflict/file cannot be categorized"); + } + assert(false); + return std::wstring(); +} + + +std::wstring zen::getCategoryDescription(const FileSystemObject& fsObj) +{ + const CompareFilesResult cmpRes = fsObj.getCategory(); + if (cmpRes == FILE_CONFLICT) + return fsObj.getCatConflict(); + + return getCategoryDescription(cmpRes); +} + + +std::wstring zen::getSyncOpDescription(SyncOperation op) +{ + switch (op) + { + case SO_CREATE_NEW_LEFT: + return _("Copy new file/folder to left"); + case SO_CREATE_NEW_RIGHT: + return _("Copy new file/folder to right"); + case SO_DELETE_LEFT: + return _("Delete left file/folder"); + case SO_DELETE_RIGHT: + return _("Delete right file/folder"); + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + return _("Move file on left"); + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: + return _("Move file on right"); + case SO_OVERWRITE_LEFT: + return _("Overwrite left file/folder with right one"); + case SO_OVERWRITE_RIGHT: + return _("Overwrite right file/folder with left one"); + case SO_DO_NOTHING: + return _("Do nothing"); + case SO_EQUAL: + return _("Both sides are equal"); + case SO_COPY_METADATA_TO_LEFT: + return _("Copy file attributes only to left"); + case SO_COPY_METADATA_TO_RIGHT: + return _("Copy file attributes only to right"); + case SO_UNRESOLVED_CONFLICT: //not used on GUI, but in .csv + _("Conflict/file cannot be categorized"); + } + assert(false); + return std::wstring(); +} + + +std::wstring zen::getSyncOpDescription(const FileSystemObject& fsObj) +{ + const SyncOperation op = fsObj.getSyncOperation(); + switch (op) + { + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + case SO_OVERWRITE_LEFT: + case SO_OVERWRITE_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + return getSyncOpDescription(op); //use generic description + + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: + if (const FileMapping* sourceFile = dynamic_cast<const FileMapping*>(&fsObj)) + if (const FileMapping* targetFile = dynamic_cast<const FileMapping*>(FileSystemObject::retrieve(sourceFile->getMoveRef()))) + { + const bool onLeft = op == SO_MOVE_LEFT_SOURCE || op == SO_MOVE_LEFT_TARGET; + const bool isSource = op == SO_MOVE_LEFT_SOURCE || op == SO_MOVE_RIGHT_SOURCE; + + if (!isSource) + std::swap(sourceFile, targetFile); + + auto getRelName = [&](const FileSystemObject& fso, bool leftSide) { return leftSide ? fso.getRelativeName<LEFT_SIDE>() : fso.getRelativeName<RIGHT_SIDE>(); }; + + const Zstring relSource = getRelName(*sourceFile, onLeft); + const Zstring relTarget = getRelName(*targetFile, !onLeft); + + return getSyncOpDescription(op) + L"\n" + + (EqualFilename()(beforeLast(relSource, FILE_NAME_SEPARATOR), beforeLast(relTarget, FILE_NAME_SEPARATOR)) ? //returns empty string if ch not found + //detected pure "rename" + L"\"" + utf8CvrtTo<std::wstring>(afterLast(relSource, FILE_NAME_SEPARATOR)) + L"\"" + L" ->\n" + //show short name only + L"\"" + utf8CvrtTo<std::wstring>(afterLast(relTarget, FILE_NAME_SEPARATOR)) + L"\"" : + //"move" or "move + rename" + L"\"" + utf8CvrtTo<std::wstring>(relSource) + L"\"" + L" ->\n" + + L"\"" + utf8CvrtTo<std::wstring>(relTarget) + L"\""); + //attention: ::SetWindowText() doesn't handle tab characters correctly in combination with certain file names, so don't use them + } + break; + case SO_UNRESOLVED_CONFLICT: + return fsObj.getSyncOpConflict(); + } + + assert(false); + return std::wstring(); +} diff --git a/file_hierarchy.h b/file_hierarchy.h index 6ea9d244..cfa71ab2 100644 --- a/file_hierarchy.h +++ b/file_hierarchy.h @@ -15,6 +15,7 @@ #include <zen/fixed_list.h> #include "structures.h" #include <zen/int64.h> +#include <zen/file_id_def.h> #include "structures.h" #include "lib/hard_filter.h" @@ -24,13 +25,16 @@ namespace zen struct FileDescriptor { FileDescriptor() {} - FileDescriptor(zen::Int64 lastWriteTimeRawIn, - zen::UInt64 fileSizeIn) : + FileDescriptor(Int64 lastWriteTimeRawIn, + UInt64 fileSizeIn, + const FileId& idIn) : lastWriteTimeRaw(lastWriteTimeRawIn), - fileSize(fileSizeIn) {} + fileSize(fileSizeIn), + id(idIn) {} - zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) - zen::UInt64 fileSize; + Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) + UInt64 fileSize; + FileId id; //optional! (however, always set on Linux, and *generally* available on Windows) }; @@ -43,16 +47,16 @@ struct LinkDescriptor }; LinkDescriptor() : type(TYPE_FILE) {} - LinkDescriptor(zen::Int64 lastWriteTimeRawIn, + LinkDescriptor(Int64 lastWriteTimeRawIn, const Zstring& targetPathIn, LinkType lt) : lastWriteTimeRaw(lastWriteTimeRawIn), targetPath(targetPathIn), type(lt) {} - zen::Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) - Zstring targetPath; //symlink "content", may be empty if determination failed - LinkType type; //type is required for Windows only! On Linux there is no such thing => consider this when comparing Symbolic Links! + Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) + Zstring targetPath; //symlink "content", may be empty if determination failed + LinkType type; //type is required for Windows only! On Linux there is no such thing => consider this when comparing Symbolic Links! }; @@ -119,6 +123,9 @@ struct DirContainer //------------------------------------------------------------------ /* inheritance diagram: + ObjectMgr + /|\ + | FileSystemObject HierarchyObject /|\ /|\ _______________|______________ ______|______ @@ -133,32 +140,36 @@ class HierarchyObject friend class FileSystemObject; typedef zen::FixedList<FileMapping> SubFileVec; //MergeSides::execute() requires a structure that doesn't invalidate pointers after push_back() - typedef zen::FixedList<SymLinkMapping> SubLinkVec; //Note: deque<> has circular reference in VCPP! + typedef zen::FixedList<SymLinkMapping> SubLinkVec; //Note: deque<> has circular dependency in VCPP! typedef zen::FixedList<DirMapping> SubDirVec; public: DirMapping& addSubDir(const Zstring& shortNameLeft, const Zstring& shortNameRight); + template <SelectedSide side> + DirMapping& addSubDir(const Zstring& shortName); //dir exists on one side only + + FileMapping& addSubFile(const Zstring& shortNameLeft, const FileDescriptor& left, //file exists on both sides CompareFilesResult defaultCmpResult, const Zstring& shortNameRight, const FileDescriptor& right); - void addSubFile(const FileDescriptor& left, //file exists on left side only - const Zstring& shortNameLeft); - void addSubFile(const Zstring& shortNameRight, //file exists on right side only - const FileDescriptor& right); + + template <SelectedSide side> + FileMapping& addSubFile(const Zstring& shortNameRight, //file exists on one side only + const FileDescriptor& right); SymLinkMapping& addSubLink(const Zstring& shortNameLeft, const LinkDescriptor& left, //link exists on both sides CompareSymlinkResult defaultCmpResult, const Zstring& shortNameRight, const LinkDescriptor& right); - void addSubLink(const LinkDescriptor& left, //link exists on left side only - const Zstring& shortNameLeft); - void addSubLink(const Zstring& shortNameRight, //link exists on right side only - const LinkDescriptor& right); + + template <SelectedSide side> + SymLinkMapping& addSubLink(const Zstring& shortName, //link exists on one side only + const LinkDescriptor& descr); const SubFileVec& refSubFiles() const { return subFiles; } /**/ SubFileVec& refSubFiles() { return subFiles; } @@ -225,7 +236,7 @@ public: virtual void flip(); private: - BaseDirMapping(const BaseDirMapping&); //this class is referenced by HierarchyObject => make it non-copyable/movable! + BaseDirMapping(const BaseDirMapping&); //this class is referenced by HierarchyObject => make it non-copyable/movable! BaseDirMapping& operator=(const BaseDirMapping&); // //this member is currently not used by the business logic -> may be removed! @@ -286,7 +297,7 @@ public: virtual void visit(const DirMapping& dirObj) = 0; }; -//inherit from this class to allow safe access by id instead of unsafe raw pointer +//inherit from this class to allow safe random access by id instead of unsafe raw pointer //allow for similar semantics like std::weak_ptr without having to use std::shared_ptr template <class T> class ObjectMgr @@ -296,9 +307,9 @@ public: ObjectID getId() { activeObjects().insert(this); return this; } //unfortunately we need to keep this method non-const to get non-const "this" pointer - //we could instead put this into the constructor, but temporaries created by STL would lead to some overhead + //we could instead put this into the constructor, but temporaries created by STL could lead to some overhead - static T* retrieve(ObjectID id) //returns NULL if object is not found + static T* retrieve(ObjectID id) //returns NULL if object is not valid anymore { auto iter = activeObjects().find(const_cast<ObjectMgr*>(id)); return static_cast<T*>(iter == activeObjects().end() ? NULL : *iter); //static down-cast @@ -337,13 +348,14 @@ public: virtual CompareFilesResult getCategory() const = 0; virtual std::wstring getCatConflict() const = 0; //only filled if getCategory() == FILE_CONFLICT //sync operation + virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; virtual SyncOperation getSyncOperation() const; std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or during categorization - SyncOperation testSyncOperation(SyncDirection syncDir) const; //get syncOp with provided settings //sync settings void setSyncDir(SyncDirection newDir); void setSyncDirConflict(const std::wstring& description); //set syncDir = SYNC_DIR_NONE + fill conflict description + SyncDirection getSyncDir() const { return syncDir; } bool isActive() const; void setActive(bool active); @@ -383,11 +395,6 @@ private: virtual void removeObjectL() = 0; virtual void removeObjectR() = 0; - static SyncOperation getSyncOperation(CompareFilesResult cmpResult, - bool selectedForSynchronization, - SyncDirection syncDir, - const std::wstring& syncDirConflict); //evaluate comparison result and sync direction - bool selectedForSynchronization; SyncDirection syncDir; std::wstring syncDirConflict; //non-empty if we have a conflict setting sync-direction @@ -461,25 +468,33 @@ class FileMapping : public FileSystemObject public: virtual void accept(FSObjectVisitor& visitor) const; - FileMapping(const Zstring& shortNameLeft, //use empty string if "not existing" - const FileDescriptor& left, - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, // - const FileDescriptor& right, + FileMapping(const Zstring& shortNameLeft, //use empty string if "not existing" + const FileDescriptor& left, + CompareFilesResult defaultCmpResult, + const Zstring& shortNameRight, // + const FileDescriptor& right, HierarchyObject& parentObj) : FileSystemObject(shortNameLeft, shortNameRight, parentObj), cmpResult(defaultCmpResult), dataLeft(left), - dataRight(right) {} + dataRight(right), + moveFileRef(NULL) {} template <SelectedSide side> Int64 getLastWriteTime() const; - template <SelectedSide side> UInt64 getFileSize() const; + template <SelectedSide side> UInt64 getFileSize () const; + template <SelectedSide side> FileId getFileId () const; template <SelectedSide side> const Zstring getExtension() const; + void setMoveRef(ObjectID refId) { moveFileRef = refId; } //reference to corresponding renamed file + ObjectID getMoveRef() const { return moveFileRef; } //may be NULL + virtual CompareFilesResult getCategory() const; virtual std::wstring getCatConflict() const; - template <SelectedSide side> void copyTo(const FileDescriptor* srcDescr); //copy + update file attributes + virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; + virtual SyncOperation getSyncOperation() const; + + template <SelectedSide side> void syncTo(const FileDescriptor& descrTarget, const FileDescriptor* descrSource = NULL); //copy + update file attributes (optional) private: template <CompareFilesResult res> @@ -497,6 +512,8 @@ private: FileDescriptor dataLeft; FileDescriptor dataRight; + + ObjectID moveFileRef; }; //------------------------------------------------------------------ @@ -549,7 +566,15 @@ private: //------------------------------------------------------------------ +//generic type descriptions (usecase CSV legend, sync config) +std::wstring getCategoryDescription(CompareFilesResult cmpRes); +std::wstring getSyncOpDescription (SyncOperation op); +//item-specific type descriptions +std::wstring getCategoryDescription(const FileSystemObject& fsObj); +std::wstring getSyncOpDescription (const FileSystemObject& fsObj); + +//------------------------------------------------------------------ @@ -681,20 +706,6 @@ void FileSystemObject::setActive(bool active) } -inline -SyncOperation FileSystemObject::getSyncOperation() const -{ - return getSyncOperation(getCategory(), selectedForSynchronization, syncDir, syncDirConflict); -} - - -inline -SyncOperation FileSystemObject::testSyncOperation(SyncDirection proposedDir) const -{ - return getSyncOperation(getCategory(), true, proposedDir, std::wstring()); //should be safe by design -} - - template <> inline bool FileSystemObject::isEmpty<LEFT_SIDE>() const { @@ -839,6 +850,22 @@ DirMapping& HierarchyObject::addSubDir(const Zstring& shortNameLeft, } +template <> inline +DirMapping& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName) +{ + subDirs.emplace_back(shortName, Zstring(), *this); + return subDirs.back(); +} + + +template <> inline +DirMapping& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName) +{ + subDirs.emplace_back(Zstring(), shortName, *this); + return subDirs.back(); +} + + inline FileMapping& HierarchyObject::addSubFile( const Zstring& shortNameLeft, @@ -852,19 +879,19 @@ FileMapping& HierarchyObject::addSubFile( } -inline -void HierarchyObject::addSubFile(const FileDescriptor& left, //file exists on left side only - const Zstring& shortNameLeft) +template <> inline +FileMapping& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) { - subFiles.emplace_back(shortNameLeft, left, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this); + subFiles.emplace_back(shortName, descr, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this); + return subFiles.back(); } -inline -void HierarchyObject::addSubFile(const Zstring& shortNameRight, //file exists on right side only - const FileDescriptor& right) +template <> inline +FileMapping& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) { - subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortNameRight, right, *this); + subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortName, descr, *this); + return subFiles.back(); } @@ -881,19 +908,19 @@ SymLinkMapping& HierarchyObject::addSubLink( } -inline -void HierarchyObject::addSubLink(const LinkDescriptor& left, //link exists on left side only - const Zstring& shortNameLeft) +template <> inline +SymLinkMapping& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) { - subLinks.emplace_back(shortNameLeft, left, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this); + subLinks.emplace_back(shortName, descr, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this); + return subLinks.back(); } -inline -void HierarchyObject::addSubLink(const Zstring& shortNameRight, //link exists on right side only - const LinkDescriptor& right) +template <> inline +SymLinkMapping& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) { - subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortNameRight, right, *this); + subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortName, descr, *this); + return subLinks.back(); } @@ -1062,6 +1089,20 @@ zen::UInt64 FileMapping::getFileSize<RIGHT_SIDE>() const } +template <> inline +FileId FileMapping::getFileId<LEFT_SIDE>() const +{ + return dataLeft.id; +} + + +template <> inline +FileId FileMapping::getFileId<RIGHT_SIDE>() const +{ + return dataRight.id; +} + + template <SelectedSide side> inline const Zstring FileMapping::getExtension() const { @@ -1076,24 +1117,26 @@ const Zstring FileMapping::getExtension() const template <> inline -void FileMapping::copyTo<LEFT_SIDE>(const FileDescriptor* srcDescr) //copy + update file attributes +void FileMapping::syncTo<LEFT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes { - if (srcDescr) - dataRight = *srcDescr; - dataLeft = dataRight; + dataLeft = descrTarget; + if (descrSource) + dataRight = *descrSource; + moveFileRef = NULL; cmpResult = FILE_EQUAL; copyToL(); //copy FileSystemObject specific part } template <> inline -void FileMapping::copyTo<RIGHT_SIDE>(const FileDescriptor* srcDescr) //copy + update file attributes +void FileMapping::syncTo<RIGHT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes { - if (srcDescr) - dataLeft = *srcDescr; - dataRight = dataLeft; + dataRight = descrTarget; + if (descrSource) + dataLeft = *descrSource; + moveFileRef = NULL; cmpResult = FILE_EQUAL; copyToR(); //copy FileSystemObject specific part } diff --git a/lib/custom_grid.cpp b/lib/custom_grid.cpp index 97db1676..f2892624 100644 --- a/lib/custom_grid.cpp +++ b/lib/custom_grid.cpp @@ -557,23 +557,24 @@ private: case SO_CREATE_NEW_LEFT: case SO_OVERWRITE_LEFT: case SO_DELETE_LEFT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_COPY_METADATA_TO_LEFT: result.first = *wxBLACK; result.second = COLOR_SYNC_BLUE; break; - case SO_COPY_METADATA_TO_LEFT: - result.first = *wxBLACK; - result.second = COLOR_SYNC_BLUE_LIGHT; + // result.second = COLOR_SYNC_BLUE_LIGHT; break; case SO_CREATE_NEW_RIGHT: case SO_OVERWRITE_RIGHT: case SO_DELETE_RIGHT: - result.first = *wxBLACK; - result.second = COLOR_SYNC_GREEN; - break; + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: case SO_COPY_METADATA_TO_RIGHT: result.first = *wxBLACK; - result.second = COLOR_SYNC_GREEN_LIGHT; + result.second = COLOR_SYNC_GREEN; break; + // result.second = COLOR_SYNC_GREEN_LIGHT; case SO_UNRESOLVED_CONFLICT: result.first = *wxBLACK; result.second = COLOR_YELLOW; @@ -2038,70 +2039,77 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) if (getGridDataTableMiddle()->syncPreviewIsActive()) //synchronization preview { - const SyncOperation syncOp = fsObj->getSyncOperation(); - switch (syncOp) + const wchar_t* imageName = [&]() -> const wchar_t* { - case SO_CREATE_NEW_LEFT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createLeft"))); - break; - case SO_CREATE_NEW_RIGHT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("createRight"))); - break; - case SO_DELETE_LEFT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteLeft"))); - break; - case SO_DELETE_RIGHT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("deleteRight"))); - break; - case SO_OVERWRITE_LEFT: - case SO_COPY_METADATA_TO_LEFT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateLeft"))); - break; - case SO_OVERWRITE_RIGHT: - case SO_COPY_METADATA_TO_RIGHT: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("updateRight"))); - break; - case SO_DO_NOTHING: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("none"))); - break; - case SO_EQUAL: - toolTip.show(getDescription(syncOp), pos, &GlobalResources::getImage(wxT("equal"))); - break; - case SO_UNRESOLVED_CONFLICT: - toolTip.show(fsObj->getSyncOpConflict(), pos, &GlobalResources::getImage(wxT("conflict"))); - break; - }; + const SyncOperation syncOp = fsObj->getSyncOperation(); + switch (syncOp) + { + case SO_CREATE_NEW_LEFT: + return L"createLeft"; + case SO_CREATE_NEW_RIGHT: + return L"createRight"; + case SO_DELETE_LEFT: + return L"deleteLeft"; + case SO_DELETE_RIGHT: + return L"deleteRight"; + case SO_MOVE_LEFT_SOURCE: + return L"moveLeftSource"; + case SO_MOVE_LEFT_TARGET: + return L"moveLeftTarget"; + case SO_MOVE_RIGHT_SOURCE: + return L"moveRightSource"; + case SO_MOVE_RIGHT_TARGET: + return L"moveRightTarget"; + case SO_OVERWRITE_LEFT: + return L"updateLeft"; + case SO_COPY_METADATA_TO_LEFT: + return L"moveLeft"; + case SO_OVERWRITE_RIGHT: + return L"updateRight"; + case SO_COPY_METADATA_TO_RIGHT: + return L"moveRight"; + case SO_DO_NOTHING: + return L"none"; + case SO_EQUAL: + return L"equal"; + case SO_UNRESOLVED_CONFLICT: + return L"conflict"; + }; + assert(false); + return L""; + }(); + + toolTip.show(getSyncOpDescription(*fsObj), pos, &GlobalResources::getImage(imageName)); } else { - const CompareFilesResult cmpRes = fsObj->getCategory(); - switch (cmpRes) + const wchar_t* imageName = [&]() -> const wchar_t* { - case FILE_LEFT_SIDE_ONLY: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftOnly"))); - break; - case FILE_RIGHT_SIDE_ONLY: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightOnly"))); - break; - case FILE_LEFT_NEWER: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("leftNewer"))); - break; - case FILE_RIGHT_NEWER: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("rightNewer"))); - break; - case FILE_DIFFERENT: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("different"))); - break; - case FILE_EQUAL: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("equal"))); - break; - case FILE_DIFFERENT_METADATA: - toolTip.show(getDescription(cmpRes), pos, &GlobalResources::getImage(wxT("conflict"))); - break; - case FILE_CONFLICT: - toolTip.show(fsObj->getCatConflict(), pos, &GlobalResources::getImage(wxT("conflict"))); - break; - } + const CompareFilesResult cmpRes = fsObj->getCategory(); + switch (cmpRes) + { + case FILE_LEFT_SIDE_ONLY: + return L"leftOnly"; + case FILE_RIGHT_SIDE_ONLY: + return L"rightOnly"; + case FILE_LEFT_NEWER: + return L"leftNewer"; + case FILE_RIGHT_NEWER: + return L"rightNewer"; + case FILE_DIFFERENT: + return L"different"; + case FILE_EQUAL: + return L"equal"; + case FILE_DIFFERENT_METADATA: + return L"conflict"; + case FILE_CONFLICT: + return L"conflict"; + } + assert(false); + return L""; + }(); + + toolTip.show(getCategoryDescription(*fsObj), pos, &GlobalResources::getImage(imageName)); } } @@ -2284,6 +2292,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, //HIGHLIGHTNING (sync direction): if (rowIsHighlighted && m_gridMiddle.highlightedPos != CustomGridMiddle::BLOCKPOS_CHECK_BOX) //don't allow changing direction for "=="-files + switch (m_gridMiddle.highlightedPos) { case CustomGridMiddle::BLOCKPOS_CHECK_BOX: @@ -2374,25 +2383,35 @@ const wxBitmap& zen::getSyncOpImage(SyncOperation syncOp) switch (syncOp) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: - return GlobalResources::getImage(wxT("createLeftSmall")); + return GlobalResources::getImage(L"createLeftSmall"); case SO_CREATE_NEW_RIGHT: - return GlobalResources::getImage(wxT("createRightSmall")); + return GlobalResources::getImage(L"createRightSmall"); case SO_DELETE_LEFT: - return GlobalResources::getImage(wxT("deleteLeftSmall")); + return GlobalResources::getImage(L"deleteLeftSmall"); case SO_DELETE_RIGHT: - return GlobalResources::getImage(wxT("deleteRightSmall")); + return GlobalResources::getImage(L"deleteRightSmall"); + case SO_MOVE_LEFT_SOURCE: + return GlobalResources::getImage(L"moveLeftSourceSmall"); + case SO_MOVE_LEFT_TARGET: + return GlobalResources::getImage(L"moveLeftTargetSmall"); + case SO_MOVE_RIGHT_SOURCE: + return GlobalResources::getImage(L"moveRightSourceSmall"); + case SO_MOVE_RIGHT_TARGET: + return GlobalResources::getImage(L"moveRightTargetSmall"); case SO_OVERWRITE_RIGHT: + return GlobalResources::getImage(L"updateRightSmall"); case SO_COPY_METADATA_TO_RIGHT: - return GlobalResources::getImage(wxT("updateRightSmall")); + return GlobalResources::getImage(L"moveRightSmall"); case SO_OVERWRITE_LEFT: + return GlobalResources::getImage(L"updateLeftSmall"); case SO_COPY_METADATA_TO_LEFT: - return GlobalResources::getImage(wxT("updateLeftSmall")); + return GlobalResources::getImage(L"moveLeftSmall"); case SO_DO_NOTHING: - return GlobalResources::getImage(wxT("noneSmall")); + return GlobalResources::getImage(L"noneSmall"); case SO_EQUAL: - return GlobalResources::getImage(wxT("equalSmall")); + return GlobalResources::getImage(L"equalSmall"); case SO_UNRESOLVED_CONFLICT: - return GlobalResources::getImage(wxT("conflictSmall")); + return GlobalResources::getImage(L"conflictSmall"); } return wxNullBitmap; //dummy diff --git a/lib/db_file.cpp b/lib/db_file.cpp index faee4c8a..60a721b1 100644 --- a/lib/db_file.cpp +++ b/lib/db_file.cpp @@ -15,7 +15,7 @@ #include <zen/file_io.h> #include <zen/scope_guard.h> #include <zen/guid.h> -#include <boost/bind.hpp> +#include <zen/utf8.h> #ifdef FFS_WIN #include <zen/win.h> //includes "windows.h" @@ -29,15 +29,24 @@ namespace { //------------------------------------------------------------------------------------------------------------------------------- const char FILE_FORMAT_DESCR[] = "FreeFileSync"; -const int FILE_FORMAT_VER = 7; +const int FILE_FORMAT_VER = 8; //------------------------------------------------------------------------------------------------------------------------------- +typedef std::string UniqueId; +typedef Zbase<char> MemoryStream; //ref-counted byte stream representing DirInformation +typedef std::map<UniqueId, MemoryStream> StreamMapping; //list of streams ordered by session UUID + + +//------------------------------------------------------------------------------------ +//| ensure 32/64 bit portability: used fixed size data types only e.g. std::uint32_t | +//------------------------------------------------------------------------------------ + template <SelectedSide side> inline Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false) { - //Linux and Windows builds are binary incompatible: char/wchar_t case, sensitive/insensitive - //32 and 64 bit db files ARE designed to be binary compatible! + //Linux and Windows builds are binary incompatible: different file id?, problem with case sensitivity? + //however 32 and 64 bit db files *are* designed to be binary compatible! //Give db files different names. //make sure they end with ".ffs_db". These files will not be included into comparison when located in base sync directories #ifdef FFS_WIN @@ -51,255 +60,209 @@ Zstring getDBFilename(const BaseDirMapping& baseMap, bool tempfile = false) } - -class FileInputStreamDB : public FileInputStream +StreamMapping loadStreams(const Zstring& filename) //throw FileError { -public: - FileInputStreamDB(const Zstring& filename) : //throw FileError - FileInputStream(filename) + if (!zen::fileExists(filename)) + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + + _("One of the FreeFileSync database files is not yet existing:") + L" \n" + + L"\"" + filename + L"\""); + try { + //read format description (uncompressed) + FileInputStream rawStream(filename); //throw FileError + //read FreeFileSync file identifier char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {}; - Read(formatDescr, sizeof(formatDescr)); //throw FileError + rawStream.Read(formatDescr, sizeof(formatDescr)); //throw FileError if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr)) throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\""); - } -private: -}; + wxZlibInputStream decompressed(rawStream, wxZLIB_ZLIB); + CheckedReader cr(decompressed, filename); -class FileOutputStreamDB : public FileOutputStream -{ -public: - FileOutputStreamDB(const Zstring& filename) : //throw FileError - FileOutputStream(filename) + std::int32_t version = cr.readNumberC<std::int32_t>(); + if (version != FILE_FORMAT_VER) //read file format version# + throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\""); + + //read stream lists + StreamMapping output; + + std::uint32_t dbCount = cr.readNumberC<std::uint32_t>(); //number of databases: one for each sync-pair + while (dbCount-- != 0) + { + //DB id of partner databases + const std::string sessionID = cr.readStringC<std::string>(); + const MemoryStream stream = cr.readStringC<MemoryStream>(); //read db-entry stream (containing DirInformation) + + output.insert(std::make_pair(sessionID, stream)); + } + return output; + } + catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file { - //write FreeFileSync file identifier - Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError + throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)"); } - -private: -}; } -//####################################################################################################################################### -class ReadDirInfo : public zen::ReadInputStream +class StreamParser : private CheckedReader { public: - ReadDirInfo(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName) + static DirInfoPtr execute(const MemoryStream& stream, const Zstring& fileName) //throw FileError -> return value always bound! { - //|------------------------------------------------------------------------------------- - //| ensure 32/64 bit portability: use fixed size data types only e.g. boost::uint32_t | - //|------------------------------------------------------------------------------------- - - //read filter settings -> currently not required, but persisting it doesn't hurt - dirInfo.filter = HardFilter::loadFilter(getStream()); - check(); - - //start recursion - execute(dirInfo.baseDirContainer); + try + { + //read streams into DirInfo + auto dirInfo = std::make_shared<DirInformation>(); + wxMemoryInputStream buffer(&*stream.begin(), stream.size()); //convert char-array to inputstream: no copying, ownership not transferred + StreamParser(buffer, fileName, *dirInfo); //throw FileError + return dirInfo; + } + catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file + { + throw FileError(_("Error reading from synchronization database:") + L" (bad alloc)"); + } } private: - void execute(DirContainer& dirCont) const + StreamParser(wxInputStream& stream, const Zstring& errorObjName, DirInformation& dirInfo) : CheckedReader(stream, errorObjName) { - while (readNumberC<bool>()) - readSubFile(dirCont); - - while (readNumberC<bool>()) - readSubLink(dirCont); - - while (readNumberC<bool>()) - readSubDirectory(dirCont); + recurse(dirInfo.baseDirContainer); } - void readSubFile(DirContainer& dirCont) const + Zstring readStringUtf8() const { - //attention: order of function argument evaluation is undefined! So do it one after the other... - const Zstring shortName = readStringC<Zstring>(); //file name - - const std::int64_t modTime = readNumberC<std::int64_t>(); - const std::uint64_t fileSize = readNumberC<std::uint64_t>(); - - //const util::FileID fileIdentifier(stream_); - //check(); - - dirCont.addSubFile(shortName, - FileDescriptor(modTime, fileSize)); + return utf8CvrtTo<Zstring>(readStringC<Zbase<char>>()); } - - void readSubLink(DirContainer& dirCont) const + FileId readFileId() const { - //attention: order of function argument evaluation is undefined! So do it one after the other... - const Zstring shortName = readStringC<Zstring>(); //file name - const std::int64_t modTime = readNumberC<std::int64_t>(); - const Zstring targetPath = readStringC<Zstring>(); //file name - const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>()); - - dirCont.addSubLink(shortName, - LinkDescriptor(modTime, targetPath, linkType)); - } + assert_static(sizeof(FileId().first ) <= sizeof(std::uint64_t)); + assert_static(sizeof(FileId().second) <= sizeof(std::uint64_t)); - - void readSubDirectory(DirContainer& dirCont) const - { - const Zstring shortName = readStringC<Zstring>(); //directory name - DirContainer& subDir = dirCont.addSubDir(shortName); - execute(subDir); //recurse + const auto devId = static_cast<decltype(FileId().first )>(readNumberC<std::uint64_t>()); // + const auto fId = static_cast<decltype(FileId().second)>(readNumberC<std::uint64_t>()); //silence "loss of precision" compiler warnings + return std::make_pair(devId, fId); } -}; -namespace -{ -typedef std::string UniqueId; -typedef std::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation -typedef std::map<UniqueId, MemoryStreamPtr> StreamMapping; //list of streams ordered by session UUID -} - -class ReadFileStream : public zen::ReadInputStream -{ -public: - ReadFileStream(wxInputStream& stream, const Zstring& filename, StreamMapping& streamList) : ReadInputStream(stream, filename) + void recurse(DirContainer& dirCont) const { - //|------------------------------------------------------------------------------------- - //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t | - //|------------------------------------------------------------------------------------- - - std::int32_t version = readNumberC<std::int32_t>(); + while (readNumberC<bool>()) //files + { + //attention: order of function argument evaluation is undefined! So do it one after the other... + const Zstring shortName = readStringUtf8(); //file name - if (version != FILE_FORMAT_VER) //read file format version - throw FileError(_("Incompatible synchronization database format:") + L" \n" + L"\"" + filename + L"\""); + const std::int64_t modTime = readNumberC<std::int64_t>(); + const std::uint64_t fileSize = readNumberC<std::uint64_t>(); + const FileId fileID = readFileId(); - streamList.clear(); + dirCont.addSubFile(shortName, + FileDescriptor(modTime, fileSize, fileID)); + } - boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair - while (dbCount-- != 0) + while (readNumberC<bool>()) //symlinks { - //DB id of partner databases - const CharArray tmp2 = readArrayC(); - const std::string sessionID(tmp2->begin(), tmp2->end()); - - CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation) + //attention: order of function argument evaluation is undefined! So do it one after the other... + const Zstring shortName = readStringUtf8(); //file name + const std::int64_t modTime = readNumberC<std::int64_t>(); + const Zstring targetPath = readStringUtf8(); //file name + const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<std::int32_t>()); + + dirCont.addSubLink(shortName, + LinkDescriptor(modTime, targetPath, linkType)); + } - streamList.insert(std::make_pair(sessionID, buffer)); + while (readNumberC<bool>()) //directories + { + const Zstring shortName = readStringUtf8(); //directory name + DirContainer& subDir = dirCont.addSubDir(shortName); + recurse(subDir); } } }; -namespace -{ -StreamMapping loadStreams(const Zstring& filename) //throw FileError -{ - if (!zen::fileExists(filename)) - throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + - _("One of the FreeFileSync database files is not yet existing:") + L" \n" + - L"\"" + filename + L"\""); - - try - { - //read format description (uncompressed) - FileInputStreamDB uncompressed(filename); //throw FileError - - wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); - StreamMapping streamList; - ReadFileStream(input, filename, streamList); - return streamList; - } - catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file +//save/load DirContainer +void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError +{ { - throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)"); - } -} + FileOutputStream rawStream(filename); //throw FileError + //write FreeFileSync file identifier + rawStream.Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); //throw FileError -DirInfoPtr parseStream(const std::vector<char>& stream, const Zstring& fileName) //throw FileError -> return value always bound! -{ - try - { - //read streams into DirInfo - auto dirInfo = std::make_shared<DirInformation>(); - wxMemoryInputStream buffer(&stream[0], stream.size()); //convert char-array to inputstream: no copying, ownership not transferred - ReadDirInfo(buffer, fileName, *dirInfo); //throw FileError - return dirInfo; - } - catch (const std::bad_alloc&) //this is most likely caused by a corrupted database file - { - throw FileError(_("Error reading from synchronization database:") + L" (bad_alloc)"); - } -} -} + wxZlibOutputStream compressed(rawStream, 4, wxZLIB_ZLIB); + /* 4 - best compromise between speed and compression: (scanning 200.000 objects) + 0 (uncompressed) 8,95 MB - 422 ms + 2 2,07 MB - 470 ms + 4 1,87 MB - 500 ms + 6 1,77 MB - 613 ms + 9 (maximal compression) 1,74 MB - 3330 ms */ + CheckedWriter cw(compressed, filename); -std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError -{ - const Zstring fileNameLeft = getDBFilename<LEFT_SIDE>(baseMapping); - const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping); + //save file format version + cw.writeNumberC<std::int32_t>(FILE_FORMAT_VER); - //read file data: list of session ID + DirInfo-stream - const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError - const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError + //save stream list + cw.writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(streamList.size())); //number of database records: one for each sync-pair - //find associated session: there can be at most one session within intersection of left and right ids - StreamMapping::const_iterator streamLeft = streamListLeft .end(); - StreamMapping::const_iterator streamRight = streamListRight.end(); - for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft) - { - auto iterRight = streamListRight.find(iterLeft->first); - if (iterRight != streamListRight.end()) + for (auto iter = streamList.begin(); iter != streamList.end(); ++iter) { - streamLeft = iterLeft; - streamRight = iterRight; - break; + cw.writeStringC<std::string >(iter->first ); //sync session id + cw.writeStringC<MemoryStream>(iter->second); //DirInformation stream } } - - if (streamLeft == streamListLeft .end() || - streamRight == streamListRight.end() || - !streamLeft ->second.get() || - !streamRight->second.get()) - throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + - _("Database files do not share a common synchronization session:") + L" \n" + - L"\"" + fileNameLeft + L"\"\n" + - L"\"" + fileNameRight + L"\""); - //read streams into DirInfo - DirInfoPtr dirInfoLeft = parseStream(*streamLeft ->second, fileNameLeft); //throw FileError - DirInfoPtr dirInfoRight = parseStream(*streamRight->second, fileNameRight); //throw FileError - - return std::make_pair(dirInfoLeft, dirInfoRight); + //(try to) hide database file +#ifdef FFS_WIN + ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN); +#endif } -//------------------------------------------------------------------------------------------------------------------------- template <SelectedSide side> -class SaveDirInfo : public WriteOutputStream +class StreamGenerator : private CheckedWriter { public: - SaveDirInfo(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : WriteOutputStream(errorObjName, stream) + static MemoryStream execute(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName) { - //save filter settings - baseMapping.getFilter()->saveFilter(getStream()); - check(); + wxMemoryOutputStream buffer; + StreamGenerator(baseMapping, oldDirInfo, errorObjName, buffer); - //start recursion - execute(baseMapping, oldDirInfo); + MemoryStream output; + output.resize(buffer.GetSize()); + buffer.CopyTo(&*output.begin(), buffer.GetSize()); + return output; } private: - void execute(const HierarchyObject& hierObj, const DirContainer* oldDirInfo) + StreamGenerator(const BaseDirMapping& baseMapping, const DirContainer* oldDirInfo, const Zstring& errorObjName, wxOutputStream& stream) : CheckedWriter(stream, errorObjName) + { + recurse(baseMapping, oldDirInfo); + } + + void recurse(const HierarchyObject& hierObj, const DirContainer* oldDirInfo) { - std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), boost::bind(&SaveDirInfo::processFile, this, _1, oldDirInfo)); + // for (const auto& fileMap : hierObj.refSubFiles()) { processFile(fileMap, oldDirInfo); }); ! + + std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](const FileMapping& fileMap) { this->processFile(fileMap, oldDirInfo); }); writeNumberC<bool>(false); //mark last entry - std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), boost::bind(&SaveDirInfo::processLink, this, _1, oldDirInfo)); + std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), [&](const SymLinkMapping& linkObj) { this->processLink(linkObj, oldDirInfo); }); writeNumberC<bool>(false); //mark last entry - std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), boost::bind(&SaveDirInfo::processDir, this, _1, oldDirInfo)); + std::for_each(hierObj.refSubDirs ().begin(), hierObj.refSubDirs ().end(), [&](const DirMapping& dirMap) { this->processDir(dirMap, oldDirInfo); }); writeNumberC<bool>(false); //mark last entry } + void writeStringUtf8(const Zstring& str) { writeStringC(utf8CvrtTo<Zbase<char>>(str)); } + + void writeFileId(const FileId& id) + { + writeNumberC<std::uint64_t>(id.first ); //device id + writeNumberC<std::uint64_t>(id.second); //file id + } + void processFile(const FileMapping& fileMap, const DirContainer* oldParentDir) { if (fileMap.getCategory() == FILE_EQUAL) //data in sync: write current state @@ -307,9 +270,10 @@ private: if (!fileMap.isEmpty<side>()) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(fileMap.getShortName<side>()); //save respecting case! (Windows) - writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>())); //last modification time - writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>())); //filesize + writeStringUtf8(fileMap.getShortName<side>()); //save respecting case! (Windows) + writeNumberC<std:: int64_t>(to<std:: int64_t>(fileMap.getLastWriteTime<side>())); + writeNumberC<std::uint64_t>(to<std::uint64_t>(fileMap.getFileSize<side>())); + writeFileId(fileMap.getFileId<side>()); } } else //not in sync: reuse last synchronous state @@ -320,9 +284,10 @@ private: if (iter != oldParentDir->files.end()) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(iter->first); //save respecting case! (Windows) - writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw)); //last modification time - writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize)); //filesize + writeStringUtf8(iter->first); //save respecting case! (Windows) + writeNumberC<std:: int64_t>(to<std:: int64_t>(iter->second.lastWriteTimeRaw)); + writeNumberC<std::uint64_t>(to<std::uint64_t>(iter->second.fileSize)); + writeFileId(iter->second.id); } } } @@ -335,9 +300,9 @@ private: if (!linkObj.isEmpty<side>()) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(linkObj.getShortName<side>()); //save respecting case! (Windows) - writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>())); //last modification time - writeStringC(linkObj.getTargetPath<side>()); + writeStringUtf8(linkObj.getShortName<side>()); //save respecting case! (Windows) + writeNumberC<std::int64_t>(to<std::int64_t>(linkObj.getLastWriteTime<side>())); + writeStringUtf8(linkObj.getTargetPath<side>()); writeNumberC<std::int32_t>(linkObj.getLinkType<side>()); } } @@ -349,9 +314,9 @@ private: if (iter != oldParentDir->links.end()) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(iter->first); //save respecting case! (Windows) - writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw)); //last modification time - writeStringC(iter->second.targetPath); + writeStringUtf8(iter->first); //save respecting case! (Windows) + writeNumberC<std::int64_t>(to<std::int64_t>(iter->second.lastWriteTimeRaw)); + writeStringUtf8(iter->second.targetPath); writeNumberC<std::int32_t>(iter->second.type); } } @@ -379,8 +344,8 @@ private: if (!dirMap.isEmpty<side>()) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(dirMap.getShortName<side>()); //save respecting case! (Windows) - execute(dirMap, oldDir); //recurse + writeStringUtf8(dirMap.getShortName<side>()); //save respecting case! (Windows) + recurse(dirMap, oldDir); } } else //not in sync: reuse last synchronous state @@ -388,8 +353,8 @@ private: if (oldDir) { writeNumberC<bool>(true); //mark beginning of entry - writeStringC(*oldDirName); //save respecting case! (Windows) - execute(dirMap, oldDir); //recurse + writeStringUtf8(*oldDirName); //save respecting case! (Windows) + recurse(dirMap, oldDir); return; } //no data is also a "synchronous state"! @@ -408,69 +373,53 @@ private: break; case DIR_DIFFERENT_METADATA: writeNumberC<bool>(true); - writeStringC(dirMap.getShortName<side>()); + writeStringUtf8(dirMap.getShortName<side>()); //ATTENTION: strictly this is a violation of the principle of reporting last synchronous state! //however in this case this will result in "last sync unsuccessful" for this directory within <automatic> algorithm, which is fine - execute(dirMap, oldDir); //recurse and save sub-items which are in sync + recurse(dirMap, oldDir); //recurse and save sub-items which are in sync break; } } } }; +} +//####################################################################################################################################### -class WriteFileStream : public WriteOutputStream +std::pair<DirInfoPtr, DirInfoPtr> zen::loadFromDisk(const BaseDirMapping& baseMapping) //throw FileError { -public: - WriteFileStream(const StreamMapping& streamList, const Zstring& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) - { - //save file format version - writeNumberC<std::int32_t>(FILE_FORMAT_VER); + const Zstring fileNameLeft = getDBFilename<LEFT_SIDE >(baseMapping); + const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping); - writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(streamList.size())); //number of database records: one for each sync-pair + //read file data: list of session ID + DirInfo-stream + const StreamMapping streamListLeft = ::loadStreams(fileNameLeft); //throw FileError + const StreamMapping streamListRight = ::loadStreams(fileNameRight); //throw FileError - for (StreamMapping::const_iterator i = streamList.begin(); i != streamList.end(); ++i) + //find associated session: there can be at most one session within intersection of left and right ids + StreamMapping::const_iterator streamLeft = streamListLeft .end(); + StreamMapping::const_iterator streamRight = streamListRight.end(); + for (auto iterLeft = streamListLeft.begin(); iterLeft != streamListLeft.end(); ++iterLeft) + { + auto iterRight = streamListRight.find(iterLeft->first); + if (iterRight != streamListRight.end()) { - //sync session id - writeArrayC(std::vector<char>(i->first.begin(), i->first.end())); - - //write DirInformation stream - writeArrayC(*(i->second)); + streamLeft = iterLeft; + streamRight = iterRight; + break; } } -}; + if (streamLeft == streamListLeft .end() || + streamRight == streamListRight.end()) + throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n\n" + + _("Database files do not share a common synchronization session:") + L" \n" + + L"\"" + fileNameLeft + L"\"\n" + + L"\"" + fileNameRight + L"\""); + //read streams into DirInfo + DirInfoPtr dirInfoLeft = StreamParser::execute(streamLeft ->second, fileNameLeft); //throw FileError + DirInfoPtr dirInfoRight = StreamParser::execute(streamRight->second, fileNameRight); //throw FileError -//save/load DirContainer -void saveFile(const StreamMapping& streamList, const Zstring& filename) //throw FileError -{ - { - //write format description (uncompressed) - FileOutputStreamDB uncompressed(filename); //throw FileError - - wxZlibOutputStream output(uncompressed, 4, wxZLIB_ZLIB); - /* 4 - best compromise between speed and compression: (scanning 200.000 objects) - 0 (uncompressed) 8,95 MB - 422 ms - 2 2,07 MB - 470 ms - 4 1,87 MB - 500 ms - 6 1,77 MB - 613 ms - 9 (maximal compression) 1,74 MB - 3330 ms */ - - WriteFileStream(streamList, filename, output); - } - //(try to) hide database file -#ifdef FFS_WIN - ::SetFileAttributes(zen::applyLongPathPrefix(filename).c_str(), FILE_ATTRIBUTE_HIDDEN); -#endif -} - - -bool equalEntry(const MemoryStreamPtr& lhs, const MemoryStreamPtr& rhs) -{ - if (!lhs.get() || !rhs.get()) - return lhs.get() == rhs.get(); - - return *lhs == *rhs; + return std::make_pair(dirInfoLeft, dirInfoRight); } @@ -522,12 +471,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError try { if (streamLeft != streamListLeft .end() && - streamRight != streamListRight.end() && - streamLeft ->second.get() && - streamRight->second.get()) + streamRight != streamListRight.end()) { - oldDirInfoLeft = parseStream(*streamLeft ->second, dbNameLeft); //throw FileError - oldDirInfoRight = parseStream(*streamRight->second, dbNameRight); //throw FileError + oldDirInfoLeft = StreamParser::execute(streamLeft ->second, dbNameLeft ); //throw FileError + oldDirInfoRight = StreamParser::execute(streamRight->second, dbNameRight); //throw FileError } } catch (FileError&) @@ -538,28 +485,13 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError } //create new database entries - MemoryStreamPtr newStreamLeft = std::make_shared<std::vector<char>>(); - { - wxMemoryOutputStream buffer; - const DirContainer* oldDir = oldDirInfoLeft.get() ? &oldDirInfoLeft->baseDirContainer : NULL; - SaveDirInfo<LEFT_SIDE>(baseMapping, oldDir, dbNameLeft, buffer); - newStreamLeft->resize(buffer.GetSize()); //convert output stream to char-array - buffer.CopyTo(&(*newStreamLeft)[0], buffer.GetSize()); // - } - - MemoryStreamPtr newStreamRight = std::make_shared<std::vector<char>>(); - { - wxMemoryOutputStream buffer; - const DirContainer* oldDir = oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL; - SaveDirInfo<RIGHT_SIDE>(baseMapping, oldDir, dbNameRight, buffer); - newStreamRight->resize(buffer.GetSize()); //convert output stream to char-array - buffer.CopyTo(&(*newStreamRight)[0], buffer.GetSize()); // - } + MemoryStream newStreamLeft = StreamGenerator<LEFT_SIDE >::execute(baseMapping, oldDirInfoLeft .get() ? &oldDirInfoLeft ->baseDirContainer : NULL, dbNameLeft); + MemoryStream newStreamRight = StreamGenerator<RIGHT_SIDE>::execute(baseMapping, oldDirInfoRight.get() ? &oldDirInfoRight->baseDirContainer : NULL, dbNameRight); //check if there is some work to do at all { - const bool updateRequiredLeft = streamLeft == streamListLeft .end() || !equalEntry(newStreamLeft, streamLeft ->second); - const bool updateRequiredRight = streamRight == streamListRight.end() || !equalEntry(newStreamRight, streamRight->second); + const bool updateRequiredLeft = streamLeft == streamListLeft .end() || newStreamLeft != streamLeft ->second; + const bool updateRequiredRight = streamRight == streamListRight.end() || newStreamRight != streamRight->second; //some users monitor the *.ffs_db file with RTS => don't touch the file if it isnt't strictly needed if (!updateRequiredLeft && !updateRequiredRight) return; @@ -579,10 +511,10 @@ void zen::saveToDisk(const BaseDirMapping& baseMapping) //throw FileError streamListRight.insert(std::make_pair(sessionID, newStreamRight)); //write (temp-) files... - zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&]() {zen::removeFile(dbNameLeftTmp); }); + zen::ScopeGuard guardTempFileLeft = zen::makeGuard([&] {zen::removeFile(dbNameLeftTmp); }); saveFile(streamListLeft, dbNameLeftTmp); //throw FileError - zen::ScopeGuard guardTempFileRight = zen::makeGuard([&]() {zen::removeFile(dbNameRightTmp); }); + zen::ScopeGuard guardTempFileRight = zen::makeGuard([&] {zen::removeFile(dbNameRightTmp); }); saveFile(streamListRight, dbNameRightTmp); //throw FileError //operation finished: rename temp files -> this should work transactionally: diff --git a/lib/db_file.h b/lib/db_file.h index d6d765cc..0413c404 100644 --- a/lib/db_file.h +++ b/lib/db_file.h @@ -14,11 +14,8 @@ namespace zen { const Zstring SYNC_DB_FILE_ENDING = Zstr(".ffs_db"); -void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError - struct DirInformation { - HardFilter::FilterRef filter; //filter settings (used when retrieving directory data) DirContainer baseDirContainer; //hierarchical directory information }; typedef std::shared_ptr<const DirInformation> DirInfoPtr; @@ -26,6 +23,8 @@ typedef std::shared_ptr<const DirInformation> DirInfoPtr; DEFINE_NEW_FILE_ERROR(FileErrorDatabaseNotExisting); std::pair<DirInfoPtr, DirInfoPtr> loadFromDisk(const BaseDirMapping& baseMapping); //throw FileError, FileErrorDatabaseNotExisting -> return value always bound! + +void saveToDisk(const BaseDirMapping& baseMapping); //throw FileError } #endif // DBFILE_H_INCLUDED diff --git a/lib/detect_renaming.cpp b/lib/detect_renaming.cpp deleted file mode 100644 index 39e7eb4b..00000000 --- a/lib/detect_renaming.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#include "detect_renaming.h" -#include <map> -#include <vector> -#include <boost/bind.hpp> - -using namespace FreeFileSync; - -/*detect renamed files: -Example: - X -> |_| Create right -|_| -> Y Delete right - -is detected as: - -Rename Y to X on right - -Algorithm: ----------- -DB-file left ---filename, Metadata(=:MD)---> DB-file right - /|\ | - | fileID, MD - fileID, MD | - | \|/ - X Y - -*/ - - -class FindDBAssoc -{ - /* - load and associate db-files by filename and metadata(size, date) - fileID, MD |-> fileID - */ -public: - struct AssocKey - { - AssocKey(const Utility::FileID& fileId, - const wxLongLong& lastWriteTimeRaw, - const wxULongLong& fileSize); - - bool operator<(const AssocKey& other) const; - - Utility::FileID fileId_; - wxLongLong lastWriteTimeRaw_; - wxULongLong fileSize_; - }; - - FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping, - std::map<AssocKey, Utility::FileID>& assocDBLeftToRight); - -private: - void recurse(const DirContainer& leftSide, const DirContainer& rightSide); - - std::map<AssocKey, Utility::FileID>& assocDBLeftToRight_; //--> -}; - - -inline -FindDBAssoc::AssocKey::AssocKey(const Utility::FileID& fileId, - const wxLongLong& lastWriteTimeRaw, - const wxULongLong& fileSize) : - fileId_(fileId), - lastWriteTimeRaw_(lastWriteTimeRaw), - fileSize_(fileSize) {} - - -inline -bool FindDBAssoc::AssocKey::operator<(const AssocKey& other) const -{ - if (fileId_ != other.fileId_) - return fileId_ < other.fileId_; - - if (lastWriteTimeRaw_ != other.lastWriteTimeRaw_) - return lastWriteTimeRaw_ < other.lastWriteTimeRaw_; - - return fileSize_ < other.fileSize_; -} - - -FindDBAssoc::FindDBAssoc(const FreeFileSync::BaseDirMapping& baseMapping, - std::map<AssocKey, Utility::FileID>& assocDBLeftToRight) : assocDBLeftToRight_(assocDBLeftToRight) -{ - try - { - std::pair<FreeFileSync::DirInfoPtr, FreeFileSync::DirInfoPtr> dbInfo = - FreeFileSync::loadFromDisk(baseMapping); //throw (FileError) - - recurse(dbInfo.first->baseDirContainer, - dbInfo.second->baseDirContainer); - } - catch (...) {} //swallow... -} - - -void FindDBAssoc::recurse(const DirContainer& leftSide, const DirContainer& rightSide) -{ - for (DirContainer::SubFileList::const_iterator i = leftSide.getSubFiles().begin(); i != leftSide.getSubFiles().end(); ++i) - { - const FileDescriptor& fileDescrI = i->second.getData(); - if (!fileDescrI.fileIdentifier.isNull()) //fileIdentifier may be NULL - { - const DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().find(i->first); - - //find files that exist on left and right - if (j != rightSide.getSubFiles().end()) - { - const FileDescriptor& fileDescrJ = j->second.getData(); - if (!fileDescrJ.fileIdentifier.isNull()) //fileIdentifier may be NULL - { - if ( fileDescrI.lastWriteTimeRaw == fileDescrJ.lastWriteTimeRaw && - fileDescrI.fileSize == fileDescrJ.fileSize) - { - assocDBLeftToRight_[AssocKey(fileDescrI.fileIdentifier, - fileDescrI.lastWriteTimeRaw, - fileDescrI.fileSize)] = fileDescrJ.fileIdentifier; - } - } - } - } - } - - //----------------------------------------------------------------------------------------------- - for (DirContainer::SubDirList::const_iterator i = leftSide.getSubDirs().begin(); i != leftSide.getSubDirs().end(); ++i) - { - const DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(i->first); - - //directories that exist on both sides - if (j != rightSide.getSubDirs().end()) - { - recurse(i->second, j->second); //recurse into subdirectories - } - } -} - - - -class FindRenameCandidates -{ -public: - FindRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping) - { - FindDBAssoc(baseMapping, - assocDBLeftToRight); - - if (!assocDBLeftToRight.empty()) - recurse(baseMapping); - } - - void getRenameCandidates(std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft, - std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight); - -private: - void recurse(HierarchyObject& hierObj) - { - //files - std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), - boost::bind(&FindRenameCandidates::processFile, this, _1)); - - //directories - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), - boost::bind(&FindRenameCandidates::recurse, this, _1));//recursion - } - - void processFile(FileMapping& fileObj) - { - switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL - createLeft[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), - fileObj.getLastWriteTime<RIGHT_SIDE>(), - fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; - break; - - case SO_CREATE_NEW_RIGHT: - if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL - createRight.push_back(&fileObj); - break; - - case SO_DELETE_LEFT: - if (!fileObj.getFileID<LEFT_SIDE>().isNull()) //fileIdentifier may be NULL - deleteLeft.push_back(&fileObj); - break; - - case SO_DELETE_RIGHT: - if (!fileObj.getFileID<RIGHT_SIDE>().isNull()) //fileIdentifier may be NULL - deleteRight[FindDBAssoc::AssocKey(fileObj.getFileID<RIGHT_SIDE>(), - fileObj.getLastWriteTime<RIGHT_SIDE>(), - fileObj.getFileSize<RIGHT_SIDE>())] = &fileObj; - break; - - case SO_OVERWRITE_RIGHT: - case SO_OVERWRITE_LEFT: - case SO_DO_NOTHING: - case SO_UNRESOLVED_CONFLICT: - break; - } - - } - - - std::vector<FileMapping*> createRight; //pointer always bound! - std::vector<FileMapping*> deleteLeft; // - // | - // \|/ - std::map<FindDBAssoc::AssocKey, Utility::FileID> assocDBLeftToRight; - // | - // \|/ - std::map<FindDBAssoc::AssocKey, FileMapping*> deleteRight; //pointer always bound! - std::map<FindDBAssoc::AssocKey, FileMapping*> createLeft; // - -}; - - - -void FindRenameCandidates::getRenameCandidates( - std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnLeft, - std::vector<std::pair<FileMapping*, FileMapping*> >& renameOnRight) -{ - for (std::vector<FileMapping*>::const_iterator crRightIter = createRight.begin(); - crRightIter != createRight.end(); - ++crRightIter) - { - const FindDBAssoc::AssocKey assocDbKey((*crRightIter)->getFileID<LEFT_SIDE>(), - (*crRightIter)->getLastWriteTime<LEFT_SIDE>(), - (*crRightIter)->getFileSize<LEFT_SIDE>()); - - const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter = - assocDBLeftToRight.find(assocDbKey); - - if (assocDBIter != assocDBLeftToRight.end()) - { - std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator delRightIter = - deleteRight.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side - assocDbKey.lastWriteTimeRaw_, - assocDbKey.fileSize_)); - - if (delRightIter != deleteRight.end()) - { - renameOnRight.push_back(std::make_pair(*crRightIter, delRightIter->second)); - } - } - } - //------------------------------------------------------------------------------------------------ - for (std::vector<FileMapping*>::const_iterator delLeftIter = deleteLeft.begin(); - delLeftIter != deleteLeft.end(); - ++delLeftIter) - { - const FindDBAssoc::AssocKey assocDbKey((*delLeftIter)->getFileID<LEFT_SIDE>(), - (*delLeftIter)->getLastWriteTime<LEFT_SIDE>(), - (*delLeftIter)->getFileSize<LEFT_SIDE>()); - - const std::map<FindDBAssoc::AssocKey, Utility::FileID>::const_iterator assocDBIter = - assocDBLeftToRight.find(assocDbKey); - - if (assocDBIter != assocDBLeftToRight.end()) - { - std::map<FindDBAssoc::AssocKey, FileMapping*>::const_iterator createLeftIter = - createLeft.find(FindDBAssoc::AssocKey(assocDBIter->second, //FileID of right side - assocDbKey.lastWriteTimeRaw_, - assocDbKey.fileSize_)); - - if (createLeftIter != createLeft.end()) - { - renameOnLeft.push_back(std::make_pair(createLeftIter->second, *delLeftIter)); - } - } - } -} - - -void FreeFileSync::getRenameCandidates(FreeFileSync::BaseDirMapping& baseMapping, //in - std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out - std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight) //out throw()! -{ - FindRenameCandidates(baseMapping).getRenameCandidates(renameOnLeft, renameOnRight); -} - diff --git a/lib/detect_renaming.h b/lib/detect_renaming.h deleted file mode 100644 index e94927c0..00000000 --- a/lib/detect_renaming.h +++ /dev/null @@ -1,26 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#ifndef DETECTRENAMING_H_INCLUDED -#define DETECTRENAMING_H_INCLUDED - -#include "../file_hierarchy.h" - - -//identify a file "create and delete"-operation as a file renaming! - -namespace zen -{ -typedef FileMapping* CreateOnLeft; -typedef FileMapping* DeleteOnLeft; -typedef FileMapping* CreateOnRight; -typedef FileMapping* DeleteOnRight; -void getRenameCandidates(zen::BaseDirMapping& baseMapping, //in - std::vector<std::pair<CreateOnLeft, DeleteOnLeft> >& renameOnLeft, //out - std::vector<std::pair<CreateOnRight, DeleteOnRight> >& renameOnRight); //out throw()! -} - -#endif // DETECTRENAMING_H_INCLUDED diff --git a/lib/dir_exist_async.h b/lib/dir_exist_async.h index 72741ee2..f59e9490 100644 --- a/lib/dir_exist_async.h +++ b/lib/dir_exist_async.h @@ -20,9 +20,7 @@ bool dirExistsUpdating(const Zstring& dirname, bool allowUserInteraction, Proces { using namespace zen; - std::wstring statusText = _("Searching for directory %x..."); - replace(statusText, L"%x", std::wstring(L"\"") + dirname + L"\"", false); - procCallback.reportStatus(statusText); + procCallback.reportStatus(replaceCpy(_("Searching for directory %x..."), L"%x", std::wstring(L"\"") + dirname + L"\"", false)); auto ft = async([=]() -> bool { diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp index 735fd7b6..ab3c84ea 100644 --- a/lib/dir_lock.cpp +++ b/lib/dir_lock.cpp @@ -74,10 +74,10 @@ public: //ATTENTION: setting file pointer IS required! => use CreateFile/FILE_GENERIC_WRITE + SetFilePointerEx! //although CreateFile/FILE_APPEND_DATA without SetFilePointerEx works locally, it MAY NOT work on some network shares creating a 4 gig file!!! - const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_.c_str()).c_str(), + const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename_).c_str(), GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp FILE_SHARE_READ, - 0, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -340,8 +340,8 @@ std::string retrieveLockId(const Zstring& lockfilename) //throw FileError, Error void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //throw FileError { - std::wstring infoMsg = _("Waiting while directory is locked (%x)..."); - replace(infoMsg, L"%x", std::wstring(L"\"") + lockfilename + L"\""); + const std::wstring infoMsg = replaceCpy(_("Waiting while directory is locked (%x)..."), L"%x", std::wstring(L"\"") + lockfilename + L"\""); + if (callback) callback->reportInfo(infoMsg); //--------------------------------------------------------------- @@ -408,8 +408,8 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr long remainingSeconds = ((DETECT_EXITUS_INTERVAL - (wxGetLocalTimeMillis() - lockSilentStart)) / 1000).ToLong(); remainingSeconds = std::max(0L, remainingSeconds); - std::wstring remSecMsg = _P("1 sec", "%x sec", remainingSeconds); - replace(remSecMsg, L"%x", toString<std::wstring>(remainingSeconds)); + const std::wstring remSecMsg = replaceCpy(_P("1 sec", "%x sec", remainingSeconds), L"%x", toString<std::wstring>(remainingSeconds)); + callback->reportInfo(infoMsg + L" " + remSecMsg); } else @@ -441,7 +441,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError const HANDLE fileHandle = ::CreateFile(applyLongPathPrefix(lockfilename).c_str(), GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - 0, + NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); @@ -472,7 +472,7 @@ bool tryLock(const Zstring& lockfilename) //throw FileError ::close(fileHandle); #endif - zen::ScopeGuard guardLockFile = zen::makeGuard([&]() { zen::removeFile(lockfilename); }); + ScopeGuard guardLockFile = zen::makeGuard([&] { zen::removeFile(lockfilename); }); //write UUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks, etc.) writeLockInfo(lockfilename); //throw FileError diff --git a/lib/dir_name.cpp b/lib/dir_name.cpp index 71a3e9ef..55a4185c 100644 --- a/lib/dir_name.cpp +++ b/lib/dir_name.cpp @@ -40,7 +40,7 @@ void setDirectoryNameImpl(const wxString& dirname, wxDirPickerCtrl* dirPicker, w if (dirPicker && !dirFormatted.empty()) { Zstring dir = toZ(dirFormatted); //convert to Zstring first: we don't want to pass wxString by value and risk MT issues! - auto ft = async([=]() { return zen::dirExists(dir); }); + auto ft = async([=] { return zen::dirExists(dir); }); if (ft.timed_wait(boost::posix_time::milliseconds(timeout)) && ft.get()) //potentially slow network access: wait 200ms at most dirPicker->SetPath(dirFormatted); diff --git a/lib/localization.cpp b/lib/localization.cpp index e8ff6040..574910ea 100644 --- a/lib/localization.cpp +++ b/lib/localization.cpp @@ -301,6 +301,7 @@ wxLanguage mapLanguageDialect(wxLanguage language) //case wxLANGUAGE_PORTUGUESE_BRAZILIAN: //case wxLANGUAGE_KOREAN: //case wxLANGUAGE_UKRAINIAN: + //case wxLANGUAGE_CROATIAN: //variants of wxLANGUAGE_ARABIC case wxLANGUAGE_ARABIC_ALGERIA: diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp index 96b167b8..1052a408 100644 --- a/lib/parallel_scan.cpp +++ b/lib/parallel_scan.cpp @@ -141,7 +141,7 @@ Windows 7: Windows XP: 1 Thread: 41s | 13s 1 Thread: 45s | 13s 2 Threads: 42s | 11s 2 Threads: 38s | 8s -=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead! +=> Traversing does not take any advantage of file locality so that even multiple threads operating on the same disk impose no performance overhead! (even faster on XP) */ @@ -196,7 +196,7 @@ public: errorMsg.clear(); errorResponse.reset(); - //dummy.unlock(); + dummy.unlock(); //optimization for condition_variable::notify_one() conditionCanReportError.notify_one(); return rv; @@ -204,13 +204,13 @@ public: void processErrors(FillBufferCallback& callback) //context of main thread, call repreatedly { - boost::lock_guard<boost::mutex> dummy(lockErrorMsg); + boost::unique_lock<boost::mutex> dummy(lockErrorMsg); if (!errorMsg.empty() && !errorResponse.get()) { FillBufferCallback::HandleError rv = callback.reportError(copyStringTo<std::wstring>(errorMsg)); //throw! errorResponse.reset(new FillBufferCallback::HandleError(rv)); - //dummy.unlock(); + dummy.unlock(); //optimization for condition_variable::notify_one() conditionGotResponse.notify_one(); } } @@ -293,6 +293,7 @@ private: }; //------------------------------------------------------------------------------------------------- + struct TraverserShared { public: @@ -372,7 +373,7 @@ void DirCallback::onFile(const Zchar* shortName, const Zstring& fullName, const Linux: retrieveFileID takes about 50% longer in VM! (avoidable because of redundant stat() call!) */ - output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize)); + output_.addSubFile(fileNameShort, FileDescriptor(details.lastWriteTimeRaw, details.fileSize, details.id)); cfg.acb_.incItemsScanned(); //add 1 element to the progress indicator } @@ -547,8 +548,8 @@ void zen::fillBuffer(const std::set<DirectoryKey>& keysToRead, //in zen::ScopeGuard guardWorker = zen::makeGuard([&]() { - std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::interrupt)); //interrupt all at once, then join - std::for_each(worker.begin(), worker.end(), std::mem_fun_ref(&boost::thread::join)); + std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.interrupt(); }); //interrupt all at once, then join + std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.join(); }); }); std::shared_ptr<AsyncCallback> acb = std::make_shared<AsyncCallback>(); diff --git a/lib/status_handler.h b/lib/status_handler.h index 390b4f0a..686c1f0e 100644 --- a/lib/status_handler.h +++ b/lib/status_handler.h @@ -7,7 +7,6 @@ #ifndef STATUSHANDLER_H_INCLUDED #define STATUSHANDLER_H_INCLUDED -#include <wx/string.h> #include <string> #include <zen/int64.h> @@ -45,21 +44,18 @@ struct ProcessCallback //note: this one must NOT throw in order to properly allow undoing setting of statistics! //it is in general paired with a call to requestUiRefresh() to compensate! - virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw() + virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed) = 0; //throw()!! //opportunity to abort must be implemented in a frequently executed method like requestUiRefresh() virtual void requestUiRefresh() = 0; //throw ? - //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events - virtual void forceUiRefresh() = 0; - //called periodically after data was processed: expected(!) to request GUI update - virtual void reportStatus(const wxString& text) = 0; //status info only, should not be logged! + virtual void reportStatus(const std::wstring& text) = 0; //status info only, should not be logged! //called periodically after data was processed: expected(!) to request GUI update - virtual void reportInfo(const wxString& text) = 0; + virtual void reportInfo(const std::wstring& text) = 0; - virtual void reportWarning(const wxString& warningMessage, bool& warningActive) = 0; + virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive) = 0; //error handling: enum Response @@ -67,8 +63,8 @@ struct ProcessCallback IGNORE_ERROR = 10, RETRY }; - virtual Response reportError (const wxString& errorMessage) = 0; //recoverable error situation - virtual void reportFatalError(const wxString& errorMessage) = 0; //non-recoverable error situation + virtual Response reportError (const std::wstring& errorMessage) = 0; //recoverable error situation + virtual void reportFatalError(const std::wstring& errorMessage) = 0; //non-recoverable error situation }; @@ -86,6 +82,8 @@ class StatusHandler : public ProcessCallback, public AbortCallback public: StatusHandler() : abortRequested(false) {} + virtual void forceUiRefresh() = 0; + virtual void requestUiRefresh() { if (updateUiIsAllowed()) //test if specific time span between ui updates is over diff --git a/structures.cpp b/structures.cpp index 1612445c..c3b20886 100644 --- a/structures.cpp +++ b/structures.cpp @@ -13,7 +13,7 @@ using namespace zen; -wxString zen::getVariantName(CompareVariant var) +std::wstring zen::getVariantName(CompareVariant var) { switch (var) { @@ -22,13 +22,12 @@ wxString zen::getVariantName(CompareVariant var) case CMP_BY_TIME_SIZE: return _("File time and size"); } - assert(false); - return wxEmptyString; + return _("Error"); } -wxString zen::getVariantName(DirectionConfig::Variant var) +std::wstring zen::getVariantName(DirectionConfig::Variant var) { switch (var) { @@ -41,6 +40,7 @@ wxString zen::getVariantName(DirectionConfig::Variant var) case DirectionConfig::CUSTOM: return _("Custom"); } + assert(false); return _("Error"); } @@ -92,7 +92,7 @@ DirectionSet zen::getTwoWaySet() } -wxString MainConfiguration::getCompVariantName() const +std::wstring MainConfiguration::getCompVariantName() const { const CompareVariant firstVariant = firstPair.altCmpConfig.get() ? firstPair.altCmpConfig->compareVar : @@ -113,7 +113,7 @@ wxString MainConfiguration::getCompVariantName() const } -wxString MainConfiguration::getSyncVariantName() const +std::wstring MainConfiguration::getSyncVariantName() const { const DirectionConfig::Variant firstVariant = firstPair.altSyncConfig.get() ? firstPair.altSyncConfig->directionCfg.var : @@ -134,120 +134,64 @@ wxString MainConfiguration::getSyncVariantName() const } -wxString zen::getDescription(CompareFilesResult cmpRes) +std::wstring zen::getSymbol(CompareFilesResult cmpRes) { switch (cmpRes) { case FILE_LEFT_SIDE_ONLY: - return _("File/folder exists on left side only"); + return L"only <-"; case FILE_RIGHT_SIDE_ONLY: - return _("File/folder exists on right side only"); + return L"only ->"; case FILE_LEFT_NEWER: - return _("Left file is newer"); + return L"newer <-"; case FILE_RIGHT_NEWER: - return _("Right file is newer"); + return L"newer ->"; case FILE_DIFFERENT: - return _("Files have different content"); + return L"!="; case FILE_EQUAL: - return _("Both sides are equal"); - case FILE_DIFFERENT_METADATA: - return _("Files/folders differ in attributes only"); - case FILE_CONFLICT: - return _("Conflict/file cannot be categorized"); - } - - assert(false); - return wxEmptyString; -} - - -wxString zen::getSymbol(CompareFilesResult cmpRes) -{ - switch (cmpRes) - { - case FILE_LEFT_SIDE_ONLY: - return wxT("<|"); - case FILE_RIGHT_SIDE_ONLY: - return wxT("|>"); - case FILE_LEFT_NEWER: - return wxT("<<"); - case FILE_RIGHT_NEWER: - return wxT(">>"); - case FILE_DIFFERENT: - return wxT("!="); - case FILE_EQUAL: - return wxT("'=="); //added quotation mark to avoid error in Excel cell when exporting to *.cvs + return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs case FILE_CONFLICT: case FILE_DIFFERENT_METADATA: - return wxT("\\/\\->"); + return L"conflict"; } - assert(false); - return wxEmptyString; + return std::wstring(); } -wxString zen::getDescription(SyncOperation op) +std::wstring zen::getSymbol(SyncOperation op) { switch (op) { case SO_CREATE_NEW_LEFT: - return _("Copy new file/folder to left"); + return L"create <-"; case SO_CREATE_NEW_RIGHT: - return _("Copy new file/folder to right"); + return L"create ->"; case SO_DELETE_LEFT: - return _("Delete left file/folder"); + return L"delete <-"; case SO_DELETE_RIGHT: - return _("Delete right file/folder"); - case SO_OVERWRITE_LEFT: - return _("Overwrite left file/folder with right one"); - case SO_OVERWRITE_RIGHT: - return _("Overwrite right file/folder with left one"); - case SO_DO_NOTHING: - return _("Do nothing"); - case SO_EQUAL: - return _("Both sides are equal"); - case SO_COPY_METADATA_TO_LEFT: - return _("Copy file attributes only to left"); - case SO_COPY_METADATA_TO_RIGHT: - return _("Copy file attributes only to right"); - case SO_UNRESOLVED_CONFLICT: //not used on GUI, but in .csv - return _("Conflict/file cannot be categorized"); - }; - - assert(false); - return wxEmptyString; -} - - -wxString zen::getSymbol(SyncOperation op) -{ - switch (op) - { - case SO_CREATE_NEW_LEFT: - return wxT("*-"); - case SO_CREATE_NEW_RIGHT: - return wxT("-*"); - case SO_DELETE_LEFT: - return wxT("D-"); - case SO_DELETE_RIGHT: - return wxT("-D"); + return L"delete ->"; + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + return L"move <-"; + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: + return L"move ->"; case SO_OVERWRITE_LEFT: case SO_COPY_METADATA_TO_LEFT: - return wxT("<-"); + return L"update <-"; case SO_OVERWRITE_RIGHT: case SO_COPY_METADATA_TO_RIGHT: - return wxT("->"); + return L"update ->"; case SO_DO_NOTHING: - return wxT(" -"); + return L" -"; case SO_EQUAL: - return wxT("'=="); //added quotation mark to avoid error in Excel cell when exporting to *.cvs + return L"'=="; //added quotation mark to avoid error in Excel cell when exporting to *.cvs case SO_UNRESOLVED_CONFLICT: - return wxT("\\/\\->"); + return L"conflict"; }; - assert(false); - return wxEmptyString; + return std::wstring(); } @@ -329,7 +273,7 @@ zen::Int64 resolve(size_t value, UnitTime unit, zen::Int64 defaultVal) zen::UInt64 resolve(size_t value, UnitSize unit, zen::UInt64 defaultVal) { - double out = value; + double out = 0; switch (unit) { case USIZE_NONE: @@ -337,10 +281,10 @@ zen::UInt64 resolve(size_t value, UnitSize unit, zen::UInt64 defaultVal) case USIZE_BYTE: return value; case USIZE_KB: - out *= 1024; + out = 1024.0 * value; break; case USIZE_MB: - out *= 1024 * 1024; + out = 1024 * 1024.0 * value; break; } return out >= to<double>(std::numeric_limits<zen::UInt64>::max()) ? //prevent overflow!!! diff --git a/structures.h b/structures.h index 47d34d0c..046b719e 100644 --- a/structures.h +++ b/structures.h @@ -7,15 +7,13 @@ #ifndef FREEFILESYNC_H_INCLUDED #define FREEFILESYNC_H_INCLUDED -#include <wx/string.h> #include <vector> +#include <memory> #include <zen/zstring.h> #include <zen/assert_static.h> -#include <memory> #include <zen/int64.h> - namespace zen { enum CompareVariant @@ -24,7 +22,7 @@ enum CompareVariant CMP_BY_CONTENT }; -wxString getVariantName(CompareVariant var); +std::wstring getVariantName(CompareVariant var); enum SymLinkHandling { @@ -89,8 +87,7 @@ CompareFilesResult convertToFilesResult(CompareSymlinkResult value) } -wxString getDescription(CompareFilesResult cmpRes); -wxString getSymbol(CompareFilesResult cmpRes); +std::wstring getSymbol(CompareFilesResult cmpRes); enum SyncOperation @@ -99,17 +96,24 @@ enum SyncOperation SO_CREATE_NEW_RIGHT, SO_DELETE_LEFT, SO_DELETE_RIGHT, + + SO_MOVE_LEFT_SOURCE, //SO_DELETE_LEFT - optimization! + SO_MOVE_LEFT_TARGET, //SO_CREATE_NEW_LEFT + + SO_MOVE_RIGHT_SOURCE, //SO_DELETE_RIGHT - optimization! + SO_MOVE_RIGHT_TARGET, //SO_CREATE_NEW_RIGHT + SO_OVERWRITE_LEFT, SO_OVERWRITE_RIGHT, SO_COPY_METADATA_TO_LEFT, //objects are already equal: transfer metadata only SO_COPY_METADATA_TO_RIGHT, // + SO_DO_NOTHING, //= both sides differ, but nothing will be synced SO_EQUAL, //= both sides are equal, so nothing will be synced SO_UNRESOLVED_CONFLICT }; -wxString getDescription(SyncOperation op); -wxString getSymbol(SyncOperation op); +std::wstring getSymbol (SyncOperation op); //method used for exporting .csv file only! struct DirectionSet @@ -171,7 +175,7 @@ bool operator==(const DirectionConfig& lhs, const DirectionConfig& rhs) //get sync directions: DON'T call for variant AUTOMATIC! DirectionSet extractDirections(const DirectionConfig& cfg); -wxString getVariantName(DirectionConfig::Variant var); +std::wstring getVariantName(DirectionConfig::Variant var); @@ -209,8 +213,8 @@ enum DeletionPolicy struct SyncConfig { SyncConfig(const DirectionConfig& directCfg, - const DeletionPolicy handleDel, - const wxString& customDelDir) : + const DeletionPolicy handleDel, + const Zstring& customDelDir) : directionCfg(directCfg), handleDeletion(handleDel), customDeletionDirectory(customDelDir) {} @@ -223,7 +227,7 @@ struct SyncConfig //misc options DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location - wxString customDeletionDirectory; + Zstring customDeletionDirectory; }; inline @@ -231,7 +235,7 @@ bool operator==(const SyncConfig& lhs, const SyncConfig& rhs) { return lhs.directionCfg == rhs.directionCfg && lhs.handleDeletion == rhs.handleDeletion && - (lhs.handleDeletion != MOVE_TO_CUSTOM_DIRECTORY || //only cmp custom deletion directory if required! + (lhs.handleDeletion != MOVE_TO_CUSTOM_DIRECTORY || //only compare deletion directory if required! lhs.customDeletionDirectory == rhs.customDeletionDirectory); } @@ -365,16 +369,14 @@ struct MainConfiguration MainConfiguration() : #ifdef FFS_WIN globalFilter(Zstr("*"), - Zstr("\ -\\System Volume Information\\\n\ -\\RECYCLED\\\n\ -\\RECYCLER\\\n\ -\\$Recycle.Bin\\")) {} + Zstr("\\System Volume Information\\\n") + Zstr("\\RECYCLED\\\n") + Zstr("\\RECYCLER\\\n") + Zstr("\\$Recycle.Bin\\")) {} #elif defined FFS_LINUX globalFilter(Zstr("*"), - Zstr("\ -/.Trash-*/\n\ -/.recycle/")) {} + Zstr("/.Trash-*/\n") + Zstr("/.recycle/")) {} #endif CompConfig cmpConfig; //global compare settings: may be overwritten by folder pair settings @@ -384,18 +386,18 @@ struct MainConfiguration FolderPairEnh firstPair; //there needs to be at least one pair! std::vector<FolderPairEnh> additionalPairs; - wxString getCompVariantName() const; - wxString getSyncVariantName() const; + std::wstring getCompVariantName() const; + std::wstring getSyncVariantName() const; }; inline bool operator==(const MainConfiguration& lhs, const MainConfiguration& rhs) { - return lhs.cmpConfig == rhs.cmpConfig && - lhs.globalFilter == rhs.globalFilter && - lhs.syncCfg == rhs.syncCfg && - lhs.firstPair == rhs.firstPair && + return lhs.cmpConfig == rhs.cmpConfig && + lhs.globalFilter == rhs.globalFilter && + lhs.syncCfg == rhs.syncCfg && + lhs.firstPair == rhs.firstPair && lhs.additionalPairs == rhs.additionalPairs; } diff --git a/synchronization.cpp b/synchronization.cpp index 66c7d262..8a5027be 100644 --- a/synchronization.cpp +++ b/synchronization.cpp @@ -8,7 +8,7 @@ #include <memory> #include <deque> #include <stdexcept> -#include <wx/msgdlg.h> +#include <wx/utils.h> #include <wx/log.h> #include <wx/file.h> #include <wx+/string_conv.h> @@ -32,36 +32,55 @@ using namespace zen; +namespace +{ +inline +int getCUD(const SyncStatistics& stat) +{ + return stat.getCreate() + + stat.getUpdate() + + stat.getDelete(); +} +} + void SyncStatistics::init() { - createLeft = 0; - createRight = 0; - overwriteLeft = 0; - overwriteRight = 0; - deleteLeft = 0; - deleteRight = 0; - conflict = 0; - rowsTotal = 0; + createLeft = 0; + createRight = 0; + updateLeft = 0; + updateRight = 0; + deleteLeft = 0; + deleteRight = 0; + conflict = 0; + rowsTotal = 0; } SyncStatistics::SyncStatistics(const FolderComparison& folderCmp) { init(); - std::for_each(begin(folderCmp), end(folderCmp), [&](const BaseDirMapping& baseMap) { getNumbersRecursively(baseMap); }); + std::for_each(begin(folderCmp), end(folderCmp), [&](const BaseDirMapping& baseMap) { recurse(baseMap); }); } SyncStatistics::SyncStatistics(const HierarchyObject& hierObj) { init(); - getNumbersRecursively(hierObj); + recurse(hierObj); +} + + +SyncStatistics::SyncStatistics(const FileMapping& fileObj) +{ + init(); + getFileNumbers(fileObj); + rowsTotal += 1; } inline -void SyncStatistics::getNumbersRecursively(const HierarchyObject& hierObj) +void SyncStatistics::recurse(const HierarchyObject& hierObj) { std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](const DirMapping& dirObj) { getDirNumbers(dirObj); }); @@ -101,13 +120,25 @@ void SyncStatistics::getFileNumbers(const FileMapping& fileObj) ++deleteRight; break; + case SO_MOVE_LEFT_TARGET: + ++updateLeft; + break; + + case SO_MOVE_RIGHT_TARGET: + ++updateRight; + break; + + case SO_MOVE_LEFT_SOURCE: //ignore + case SO_MOVE_RIGHT_SOURCE: // + break; + case SO_OVERWRITE_LEFT: - ++overwriteLeft; + ++updateLeft; dataToProcess += fileObj.getFileSize<RIGHT_SIDE>(); break; case SO_OVERWRITE_RIGHT: - ++overwriteRight; + ++updateRight; dataToProcess += fileObj.getFileSize<LEFT_SIDE>(); break; @@ -118,11 +149,11 @@ void SyncStatistics::getFileNumbers(const FileMapping& fileObj) break; case SO_COPY_METADATA_TO_LEFT: - ++overwriteLeft; + ++updateLeft; break; case SO_COPY_METADATA_TO_RIGHT: - ++overwriteRight; + ++updateRight; break; case SO_DO_NOTHING: @@ -155,12 +186,12 @@ void SyncStatistics::getLinkNumbers(const SymLinkMapping& linkObj) case SO_OVERWRITE_LEFT: case SO_COPY_METADATA_TO_LEFT: - ++overwriteLeft; + ++updateLeft; break; case SO_OVERWRITE_RIGHT: case SO_COPY_METADATA_TO_RIGHT: - ++overwriteRight; + ++updateRight; break; case SO_UNRESOLVED_CONFLICT: @@ -169,6 +200,11 @@ void SyncStatistics::getLinkNumbers(const SymLinkMapping& linkObj) firstConflicts.push_back(std::make_pair(linkObj.getObjRelativeName(), linkObj.getSyncOpConflict())); break; + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + assert(false); case SO_DO_NOTHING: case SO_EQUAL: break; @@ -209,20 +245,24 @@ void SyncStatistics::getDirNumbers(const DirMapping& dirObj) break; case SO_COPY_METADATA_TO_LEFT: - ++overwriteLeft; + ++updateLeft; break; case SO_COPY_METADATA_TO_RIGHT: - ++overwriteRight; + ++updateRight; break; + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + assert(false); case SO_DO_NOTHING: case SO_EQUAL: break; } - //recurse into sub-dirs - getNumbersRecursively(dirObj); + recurse(dirObj); } @@ -245,7 +285,7 @@ std::vector<zen::FolderPairSyncCfg> zen::extractSyncCfg(const MainConfiguration& output.push_back( FolderPairSyncCfg(syncCfg.directionCfg.var == DirectionConfig::AUTOMATIC, syncCfg.handleDeletion, - toZ(syncCfg.customDeletionDirectory))); + syncCfg.customDeletionDirectory)); } return output; @@ -257,7 +297,7 @@ namespace bool synchronizationNeeded(const SyncStatistics& statisticsTotal) { return statisticsTotal.getCreate() + - statisticsTotal.getOverwrite() + + statisticsTotal.getUpdate() + statisticsTotal.getDelete() + //conflicts (unless excluded) justify a sync! Also note: if this method returns false, no warning about unresolved conflicts were shown! statisticsTotal.getConflict() != 0; @@ -269,18 +309,18 @@ bool synchronizationNeeded(const SyncStatistics& statisticsTotal) bool significantDifferenceDetected(const SyncStatistics& folderPairStat) { //initial file copying shall not be detected as major difference - if (folderPairStat.getCreate<LEFT_SIDE>() == 0 && - folderPairStat.getOverwrite() == 0 && - folderPairStat.getDelete() == 0 && - folderPairStat.getConflict() == 0) return false; + if (folderPairStat.getCreate<LEFT_SIDE>() == 0 && + folderPairStat.getUpdate () == 0 && + folderPairStat.getDelete () == 0 && + folderPairStat.getConflict() == 0) return false; if (folderPairStat.getCreate<RIGHT_SIDE>() == 0 && - folderPairStat.getOverwrite() == 0 && - folderPairStat.getDelete() == 0 && - folderPairStat.getConflict() == 0) return false; + folderPairStat.getUpdate () == 0 && + folderPairStat.getDelete () == 0 && + folderPairStat.getConflict() == 0) return false; - const int changedRows = folderPairStat.getCreate() + - folderPairStat.getOverwrite() + - folderPairStat.getDelete() + + const int changedRows = folderPairStat.getCreate () + + folderPairStat.getUpdate () + + folderPairStat.getDelete () + folderPairStat.getConflict(); return changedRows >= 10 && changedRows > 0.5 * folderPairStat.getRowCount(); @@ -361,10 +401,10 @@ SyncProcess::SyncProcess(xmlAccess::OptionalDialogs& warnings, transactionalFileCopy_(transactionalFileCopy), m_warnings(warnings), procCallback(handler) - { -if (runWithBackgroundPriority) -procBackground.reset(new ScheduleForBackgroundProcessing); - } +{ + if (runWithBackgroundPriority) + procBackground.reset(new ScheduleForBackgroundProcessing); +} //-------------------------------------------------------------------------------------------------------------- namespace @@ -377,7 +417,7 @@ class DeletionHandling //e.g. generate name of alternate deletion directory (uni public: DeletionHandling(DeletionPolicy handleDel, const Zstring& custDelFolder, - const Zstring& baseDir, //with separator postfix + const Zstring& baseDirPf, //with separator postfix ProcessCallback& procCallback); ~DeletionHandling(); //always (try to) clean up, even if synchronization is aborted! @@ -387,9 +427,9 @@ public: void removeFile (const Zstring& relativeName) const; //throw FileError void removeFolder(const Zstring& relativeName) const; //throw FileError - const wxString& getTxtRemovingFile () const { return txtRemovingFile; } // - const wxString& getTxtRemovingSymLink() const { return txtRemovingSymlink; } //status text templates - const wxString& getTxtRemovingDir () const { return txtRemovingDirectory; } // + const std::wstring& getTxtRemovingFile () const { return txtRemovingFile; } // + const std::wstring& getTxtRemovingSymLink() const { return txtRemovingSymlink; } //status text templates + const std::wstring& getTxtRemovingDir () const { return txtRemovingDirectory; } // //evaluate whether a deletion will actually free space within a volume bool deletionFreesSpace() const; @@ -401,12 +441,12 @@ private: Zstring sessionDelDir; //target deletion folder for current folder pair (with timestamp, ends with path separator) - Zstring baseDir_; //with separator postfix + Zstring baseDirPf_; //with separator postfix //preloaded status texts: - wxString txtRemovingFile; - wxString txtRemovingSymlink; - wxString txtRemovingDirectory; + std::wstring txtRemovingFile; + std::wstring txtRemovingSymlink; + std::wstring txtRemovingDirectory; bool cleanedUp; }; @@ -414,41 +454,41 @@ private: DeletionHandling::DeletionHandling(DeletionPolicy handleDel, const Zstring& custDelFolder, - const Zstring& baseDir, //with separator postfix + const Zstring& baseDirPf, //with separator postfix ProcessCallback& procCallback) : deletionType(handleDel), procCallback_(&procCallback), - baseDir_(baseDir), + baseDirPf_(baseDirPf), cleanedUp(false) { #ifdef FFS_WIN - if (baseDir.empty() || - (deletionType == MOVE_TO_RECYCLE_BIN && recycleBinStatus(baseDir) != STATUS_REC_EXISTS)) + if (baseDirPf.empty() || + (deletionType == MOVE_TO_RECYCLE_BIN && recycleBinStatus(baseDirPf) != STATUS_REC_EXISTS)) deletionType = DELETE_PERMANENTLY; //Windows' ::SHFileOperation() will do this anyway, but we have a better and faster deletion routine (e.g. on networks) #endif switch (deletionType) { case DELETE_PERMANENTLY: - txtRemovingFile = replaceCpy(_("Deleting file %x" ), L"%x", L"\n\"%x\"", false); - txtRemovingDirectory = replaceCpy(_("Deleting folder %x" ), L"%x", L"\n\"%x\"", false); - txtRemovingSymlink = replaceCpy(_("Deleting symbolic link %x"), L"%x", L"\n\"%x\"", false); + txtRemovingFile = replaceCpy(_("Deleting file %x" ), L"%x", L"\"%x\"", false); + txtRemovingDirectory = replaceCpy(_("Deleting folder %x" ), L"%x", L"\"%x\"", false); + txtRemovingSymlink = replaceCpy(_("Deleting symbolic link %x"), L"%x", L"\"%x\"", false); break; case MOVE_TO_RECYCLE_BIN: - sessionDelDir = getSessionDeletionDir(baseDir_, Zstr("FFS ")); + sessionDelDir = getSessionDeletionDir(baseDirPf_, Zstr("FFS ")); - txtRemovingFile = replaceCpy(_("Moving file %x to recycle bin" ), L"%x", L"\n\"%x\"", false); - txtRemovingDirectory = replaceCpy(_("Moving folder %x to recycle bin" ), L"%x", L"\n\"%x\"", false); - txtRemovingSymlink = replaceCpy(_("Moving symbolic link %x to recycle bin"), L"%x", L"\n\"%x\"", false); + txtRemovingFile = replaceCpy(_("Moving file %x to recycle bin" ), L"%x", L"\"%x\"", false); + txtRemovingDirectory = replaceCpy(_("Moving folder %x to recycle bin" ), L"%x", L"\"%x\"", false); + txtRemovingSymlink = replaceCpy(_("Moving symbolic link %x to recycle bin"), L"%x", L"\"%x\"", false); break; case MOVE_TO_CUSTOM_DIRECTORY: sessionDelDir = getSessionDeletionDir(custDelFolder); - txtRemovingFile = replaceCpy(replaceCpy(_("Moving file %x to %y" ), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false); - txtRemovingDirectory = replaceCpy(replaceCpy(_("Moving folder %x to %y" ), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false); - txtRemovingSymlink = replaceCpy(replaceCpy(_("Moving symbolic link %x to %y"), L"%x", L"\n\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<wxString>(custDelFolder) + L"\"", false); + txtRemovingFile = replaceCpy(replaceCpy(_("Moving file %x to %y" ), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false); + txtRemovingDirectory = replaceCpy(replaceCpy(_("Moving folder %x to %y" ), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false); + txtRemovingSymlink = replaceCpy(replaceCpy(_("Moving symbolic link %x to %y"), L"%x", L"\"%x\"", false), L"%y", L"\"" + utf8CvrtTo<std::wstring>(custDelFolder) + L"\"", false); break; } } @@ -497,12 +537,12 @@ struct CallbackRemoveDirImpl : public CallbackRemoveDir virtual void notifyFileDeletion(const Zstring& filename) { - delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(filename))); + delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingFile(), L"%x", utf8CvrtTo<std::wstring>(filename))); } virtual void notifyDirDeletion(const Zstring& dirname) { - delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirname))); + delHandling_.procCallback_->reportStatus(replaceCpy(delHandling_.getTxtRemovingDir(), L"%x", utf8CvrtTo<std::wstring>(dirname))); } private: @@ -513,7 +553,7 @@ private: void DeletionHandling::removeFile(const Zstring& relativeName) const { - const Zstring fullName = baseDir_ + relativeName; + const Zstring fullName = baseDirPf_ + relativeName; switch (deletionType) { @@ -562,7 +602,7 @@ void DeletionHandling::removeFile(const Zstring& relativeName) const void DeletionHandling::removeFolder(const Zstring& relativeName) const { - const Zstring fullName = baseDir_ + relativeName; + const Zstring fullName = baseDirPf_ + relativeName; switch (deletionType) { @@ -621,7 +661,7 @@ bool DeletionHandling::deletionFreesSpace() const case MOVE_TO_RECYCLE_BIN: return false; //in general... (unless Recycle Bin is full) case MOVE_TO_CUSTOM_DIRECTORY: - switch (zen::onSameVolume(baseDir_, sessionDelDir)) + switch (zen::onSameVolume(baseDirPf_, sessionDelDir)) { case IS_SAME_YES: return false; @@ -642,20 +682,21 @@ namespace class DiskSpaceNeeded { public: - DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) : - freeSpaceDelLeft_(freeSpaceDelLeft), - freeSpaceDelRight_(freeSpaceDelRight) + static std::pair<Int64, Int64> calculate(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) { - processRecursively(baseObj); + DiskSpaceNeeded inst(baseObj, freeSpaceDelLeft, freeSpaceDelRight); + return std::make_pair(inst.spaceNeededLeft, inst.spaceNeededRight); } - std::pair<zen::Int64, zen::Int64> getSpaceTotal() const +private: + DiskSpaceNeeded(const BaseDirMapping& baseObj, bool freeSpaceDelLeft, bool freeSpaceDelRight) : + freeSpaceDelLeft_(freeSpaceDelLeft), + freeSpaceDelRight_(freeSpaceDelRight) { - return std::make_pair(spaceNeededLeft, spaceNeededRight); + recurse(baseObj); } -private: - void processRecursively(const HierarchyObject& hierObj) + void recurse(const HierarchyObject& hierObj) { //don't process directories @@ -664,33 +705,33 @@ private: switch (i->getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: - spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + spaceNeededLeft += to<Int64>(i->getFileSize<RIGHT_SIDE>()); break; case SO_CREATE_NEW_RIGHT: - spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + spaceNeededRight += to<Int64>(i->getFileSize<LEFT_SIDE>()); break; case SO_DELETE_LEFT: if (freeSpaceDelLeft_) - spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + spaceNeededLeft -= to<Int64>(i->getFileSize<LEFT_SIDE>()); break; case SO_DELETE_RIGHT: if (freeSpaceDelRight_) - spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + spaceNeededRight -= to<Int64>(i->getFileSize<RIGHT_SIDE>()); break; case SO_OVERWRITE_LEFT: if (freeSpaceDelLeft_) - spaceNeededLeft -= to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); - spaceNeededLeft += to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); + spaceNeededLeft -= to<Int64>(i->getFileSize<LEFT_SIDE>()); + spaceNeededLeft += to<Int64>(i->getFileSize<RIGHT_SIDE>()); break; case SO_OVERWRITE_RIGHT: if (freeSpaceDelRight_) - spaceNeededRight -= to<zen::Int64>(i->getFileSize<RIGHT_SIDE>()); - spaceNeededRight += to<zen::Int64>(i->getFileSize<LEFT_SIDE>()); + spaceNeededRight -= to<Int64>(i->getFileSize<RIGHT_SIDE>()); + spaceNeededRight += to<Int64>(i->getFileSize<LEFT_SIDE>()); break; case SO_DO_NOTHING: @@ -698,6 +739,10 @@ private: case SO_UNRESOLVED_CONFLICT: case SO_COPY_METADATA_TO_LEFT: case SO_COPY_METADATA_TO_RIGHT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: break; } @@ -705,78 +750,20 @@ private: //[...] //recurse into sub-dirs - std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](const HierarchyObject& subDir) { this->processRecursively(subDir); }); + std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](const HierarchyObject& subDir) { this->recurse(subDir); }); //for (auto& subDir : hierObj.refSubDirs()) - // processRecursively(subDir); + // recurse(subDir); } const bool freeSpaceDelLeft_; const bool freeSpaceDelRight_; - zen::Int64 spaceNeededLeft; - zen::Int64 spaceNeededRight; + Int64 spaceNeededLeft; + Int64 spaceNeededRight; }; } //---------------------------------------------------------------------------------------- -//test if current sync-line will result in deletion of files or -//big file is overwritten by smaller one -> used to avoid disc space bottlenecks (at least if permanent deletion is active) -inline -bool diskSpaceIsReduced(const FileMapping& fileObj) -{ - switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_DELETE_LEFT: - case SO_DELETE_RIGHT: - return true; - - case SO_OVERWRITE_LEFT: - return fileObj.getFileSize<LEFT_SIDE>() > fileObj.getFileSize<RIGHT_SIDE>(); - - case SO_OVERWRITE_RIGHT: - return fileObj.getFileSize<LEFT_SIDE>() < fileObj.getFileSize<RIGHT_SIDE>(); - - case SO_CREATE_NEW_LEFT: - case SO_CREATE_NEW_RIGHT: - case SO_DO_NOTHING: - case SO_EQUAL: - case SO_UNRESOLVED_CONFLICT: - case SO_COPY_METADATA_TO_LEFT: - case SO_COPY_METADATA_TO_RIGHT: - return false; - } - assert(false); - return false; //dummy -} - - -inline -bool diskSpaceIsReduced(const DirMapping& dirObj) -{ - switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_DELETE_LEFT: - case SO_DELETE_RIGHT: - return true; - - case SO_OVERWRITE_LEFT: - case SO_OVERWRITE_RIGHT: - assert(false); - case SO_CREATE_NEW_LEFT: - case SO_CREATE_NEW_RIGHT: - case SO_DO_NOTHING: - case SO_EQUAL: - case SO_UNRESOLVED_CONFLICT: - case SO_COPY_METADATA_TO_LEFT: - case SO_COPY_METADATA_TO_RIGHT: - return false; - } - assert(false); - return false; //dummy -} -//--------------------------------------------------------------------------------------------------------------- - - class zen::SynchronizeFolderPair { public: @@ -801,36 +788,58 @@ public: txtOverwritingFile (replaceCpy(_("Overwriting file %x" ), L"%x", L"\"%x\"", false)), txtOverwritingLink (replaceCpy(_("Overwriting symbolic link %x"), L"%x", L"\"%x\"", false)), txtVerifying (replaceCpy(_("Verifying file %x" ), L"%x", L"\"%x\"", false)), - txtWritingAttributes(replaceCpy(_("Updating attributes of %x" ), L"%x", L"\"%x\"", false)) {} + txtWritingAttributes(replaceCpy(_("Updating attributes of %x" ), L"%x", L"\"%x\"", false)), + txtMovingFile (replaceCpy(replaceCpy(_("Moving file %x to %y"), L"%x", L"\"%x\"", false), L"%y", L"\"%y\"", false)) {} void startSync(BaseDirMapping& baseMap) { - //loop through all files twice; reason: first delete files (or overwrite big ones with smaller ones), then copy rest - execute<FIRST_PASS >(baseMap); - execute<SECOND_PASS>(baseMap); + runZeroPass(baseMap); //first process file moves + runPass<PASS_ONE>(baseMap); //delete files (or overwrite big ones with smaller ones) + runPass<PASS_TWO>(baseMap); //copy rest } private: enum PassId { - FIRST_PASS, //delete files - SECOND_PASS //create, modify + PASS_ONE, //delete files + PASS_TWO, //create, modify + PASS_NEVER //skip }; + static PassId getPass(const FileMapping& fileObj); + static PassId getPass(const SymLinkMapping& linkObj); + static PassId getPass(const DirMapping& dirObj); + + template <SelectedSide side> + void prepare2StepMove(FileMapping& sourceObj, FileMapping& targetObj); //throw FileError + bool createParentDir(FileSystemObject& fsObj); //throw FileError + template <SelectedSide side> + void manageFileMove(FileMapping& sourceObj, FileMapping& targetObj); //throw FileError + + void runZeroPass(HierarchyObject& hierObj); template <PassId pass> - void execute(HierarchyObject& hierObj); + void runPass(HierarchyObject& hierObj); + + void synchronizeFile(FileMapping& fileObj) const; + template <SelectedSide side> void synchronizeFileInt(FileMapping& fileObj, SyncOperation syncOp) const; + + void synchronizeLink(SymLinkMapping& linkObj) const; + template <SelectedSide sideTrg> void synchronizeLinkInt(SymLinkMapping& linkObj, SyncOperation syncOp) const; + + void synchronizeFolder(DirMapping& dirObj) const; + template <SelectedSide sideTrg> void synchronizeFolderInt(DirMapping& dirObj, SyncOperation syncOp) const; - void synchronizeFile (FileMapping& fileObj) const; - void synchronizeLink (SymLinkMapping& linkObj) const; - void synchronizeFolder(DirMapping& dirObj) const; + void reportInfo (const std::wstring& rawText, const Zstring& objname) const { procCallback_.reportInfo (replaceCpy(rawText, L"%x", utf8CvrtTo<std::wstring>(objname))); }; + void reportStatus(const std::wstring& rawText, const Zstring& objname) const { procCallback_.reportStatus(replaceCpy(rawText, L"%x", utf8CvrtTo<std::wstring>(objname))); }; //more low level helper - template <zen::SelectedSide side> - void deleteSymlink(const SymLinkMapping& linkObj) const; template <SelectedSide side, class DelTargetCommand> - void copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileDescriptor& sourceAttr) const; + void copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileAttrib& newAttr) const; void verifyFileCopy(const Zstring& source, const Zstring& target) const; + template <SelectedSide side> + const DeletionHandling& getDelHandling() const; + ProcessCallback& procCallback_; #ifdef FFS_WIN shadow::ShadowCopy* shadowCopyHandler_; //optional! @@ -843,198 +852,556 @@ private: const bool transactionalFileCopy; //preload status texts - const wxString txtCreatingFile; - const wxString txtCreatingLink; - const wxString txtCreatingFolder; - const wxString txtOverwritingFile; - const wxString txtOverwritingLink; - const wxString txtVerifying; - const wxString txtWritingAttributes; + const std::wstring txtCreatingFile; + const std::wstring txtCreatingLink; + const std::wstring txtCreatingFolder; + const std::wstring txtOverwritingFile; + const std::wstring txtOverwritingLink; + const std::wstring txtVerifying; + const std::wstring txtWritingAttributes; + const std::wstring txtMovingFile; }; +//--------------------------------------------------------------------------------------------------------------- +namespace zen +{ +template <> inline +const DeletionHandling& SynchronizeFolderPair::getDelHandling<LEFT_SIDE>() const { return delHandlingLeft_; } + +template <> inline +const DeletionHandling& SynchronizeFolderPair::getDelHandling<RIGHT_SIDE>() const { return delHandlingRight_; } +} + + +/* +__________________________ +|Move algorithm, 0th pass| +-------------------------- +1. loop over hierarchy and find "move source" + +2. check whether parent directory of "move source" is going to be deleted or location of "move source" may lead to name clash with other dir/symlink + -> no: delay move until 2nd pass + +3. create move target's parent directory recursively + execute move + do we have name clash? + -> prepare a 2-step move operation: 1. move source to root and update "move target" accordingly 2. delay move until 2nd pass + +4. If any of the operations above did not succeed (even after retry), update statistics and revert to "copy + delete" + Note: first pass may delete "move source"!!! + +__________________ +|killer-scenarios| +------------------ +propagate the following move sequences: +I) a -> a/a caveat sync'ing parent directory first leads to circular dependency! + +II) a/a -> a caveat: fixing name clash will remove source! + +III) c -> d caveat: move-sequence needs to be processed in correct order! + b -> c/b + a -> b/a +*/ + +namespace +{ +template <class Mapping> inline +bool haveNameClash(const Zstring& shortname, Mapping& m) +{ + return std::find_if(m.begin(), m.end(), + [&](const typename Mapping::value_type& obj) { return EqualFilename()(obj.getObjShortName(), shortname); }) != m.end(); +} + + +Zstring findUniqueTempName(const Zstring& filename) +{ + Zstring output = filename + zen::TEMP_FILE_ENDING; + + //ensure uniqueness + for (int i = 1; somethingExists(output); ++i) + output = filename + Zchar('_') + toString<Zstring>(i) + zen::TEMP_FILE_ENDING; + + return output; +} +} + + +template <SelectedSide side> +void SynchronizeFolderPair::prepare2StepMove(FileMapping& sourceObj, + FileMapping& targetObj) //throw FileError +{ + const Zstring& source = sourceObj.getFullName<side>(); + const Zstring& tmpTarget = findUniqueTempName(sourceObj.getBaseDirPf<side>() + sourceObj.getShortName<side>()); + //this could still lead to a name-clash in obscure cases, if some file ex. on the other side with + //the very same (.ffs_tmp) name and is copied before the second step of the move is executed + //good news: even in this pathologic case, this may only prevent the copy of the other file, but not the move + + reportInfo(replaceCpy(txtMovingFile, L"%y", utf8CvrtTo<std::wstring>(tmpTarget)), source); + + renameFile(source, tmpTarget); //throw FileError; + + //update file hierarchy + const FileDescriptor descrSource(sourceObj.getLastWriteTime<side>(), + sourceObj.getFileSize <side>(), + sourceObj.getFileId <side>()); + + sourceObj.removeObject<side>(); + + FileMapping& tempFile = sourceObj.root().addSubFile<side>(afterLast(tmpTarget, FILE_NAME_SEPARATOR), descrSource); + + //prepare move in second pass + tempFile.setSyncDir(side == LEFT_SIDE ? SYNC_DIR_LEFT : SYNC_DIR_RIGHT); + + targetObj.setMoveRef(tempFile .getId()); + tempFile .setMoveRef(targetObj.getId()); + + //NO statistics update! + procCallback_.requestUiRefresh(); //may throw +} + + +bool SynchronizeFolderPair::createParentDir(FileSystemObject& fsObj) //throw FileError, "false" on name clash +{ + if (DirMapping* parentDir = dynamic_cast<DirMapping*>(&fsObj.parent())) + { + if (!createParentDir(*parentDir)) + return false; + + //detect (and try to resolve) file type conflicts: 1. symlinks 2. files + const Zstring& shortname = parentDir->getObjShortName(); + if (haveNameClash(shortname, parentDir->parent().refSubLinks()) || + haveNameClash(shortname, parentDir->parent().refSubFiles())) + return false; + + //in this context "parentDir" cannot be scheduled for deletion since it contains a "move target"! + //note: if parentDir were deleted, we'd end up destroying "fsObj"! + assert(parentDir->getSyncOperation() != SO_DELETE_LEFT && + parentDir->getSyncOperation() != SO_DELETE_RIGHT); + + synchronizeFolder(*parentDir); //throw FileError + } + return true; +} + + +template <SelectedSide side> +void SynchronizeFolderPair::manageFileMove(FileMapping& sourceObj, + FileMapping& targetObj) //throw FileError +{ + assert((sourceObj.getSyncOperation() == SO_MOVE_LEFT_SOURCE && targetObj.getSyncOperation() == SO_MOVE_LEFT_TARGET && side == LEFT_SIDE) || + (sourceObj.getSyncOperation() == SO_MOVE_RIGHT_SOURCE && targetObj.getSyncOperation() == SO_MOVE_RIGHT_TARGET && side == RIGHT_SIDE)); + + const bool sourceWillBeDeleted = [&]() -> bool + { + if (DirMapping* parentDir = dynamic_cast<DirMapping*>(&sourceObj.parent())) + { + switch (parentDir->getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + return true; //we need to do something about it + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + case SO_OVERWRITE_LEFT: + case SO_OVERWRITE_RIGHT: + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + break; + } + } + return false; + }(); + + auto haveNameClash = [](const FileMapping& fileObj) + { + return ::haveNameClash(fileObj.getObjShortName(), fileObj.parent().refSubLinks()) || + ::haveNameClash(fileObj.getObjShortName(), fileObj.parent().refSubDirs()); + }; + + if (sourceWillBeDeleted || haveNameClash(sourceObj)) + { + //prepare for move now: - revert to 2-step move on name clashes + if (haveNameClash(targetObj) || + !createParentDir(targetObj)) //throw FileError + return prepare2StepMove<side>(sourceObj, targetObj); //throw FileError + + //finally start move! this should work now: + synchronizeFile(sourceObj); //throw FileError + } + //else: sourceObj will not be deleted, and is not standing in the way => delay to second pass + //note: this case may include "move sources" from two-step sub-routine! +} + + +void SynchronizeFolderPair::runZeroPass(HierarchyObject& hierObj) +{ + //search for file move-operations + + for (auto iter = hierObj.refSubFiles().begin(); iter != hierObj.refSubFiles().end(); ++iter) //VS 2010 crashes if we use for_each + lambda here... + { + FileMapping& fileObj = *iter; + + const SyncOperation syncOp = fileObj.getSyncOperation(); + switch (syncOp) //evaluate comparison result and sync direction + { + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + { + FileMapping* sourceObj = &fileObj; + if (FileMapping* targetObj = dynamic_cast<FileMapping*>(FileSystemObject::retrieve(fileObj.getMoveRef()))) + { + if (!tryReportingError(procCallback_, [&] { return syncOp == SO_MOVE_LEFT_SOURCE ? this->manageFileMove<LEFT_SIDE>(*sourceObj, *targetObj) : this->manageFileMove<RIGHT_SIDE>(*sourceObj, *targetObj); })) + { + //move operation has failed! We cannot allow to continue and have move source's parent directory deleted, messing up statistics! + // => revert to ordinary "copy + delete" + + auto getStat = [&]() -> std::pair<int, Int64> + { + SyncStatistics statSrc(*sourceObj); + SyncStatistics statTrg(*targetObj); + + return std::make_pair(getCUD(statSrc) + getCUD(statTrg), + to<Int64>(statSrc.getDataToProcess() + statTrg.getDataToProcess())); + }; + + const auto statBefore = getStat(); + sourceObj->setMoveRef(NULL); + targetObj->setMoveRef(NULL); + const auto statAfter = getStat(); + //fix statistics to match "copy + delete" + procCallback_.updateProcessedData(statBefore.first - statAfter.first, statBefore.second - statAfter.second); + } + } + } + break; + case SO_MOVE_LEFT_TARGET: //it's enough to try each move-pair *once* + case SO_MOVE_RIGHT_TARGET: // + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + case SO_OVERWRITE_LEFT: + case SO_OVERWRITE_RIGHT: + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + break; + } + } + + std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), + [&](DirMapping& dirObj) { this->runZeroPass(dirObj); /*recurse */ }); +} +//--------------------------------------------------------------------------------------------------------------- + + +//1st, 2nd pass requirements: +// - avoid disk space shortage: 1. delete files, 2. overwrite big with small files first +// - support change in type: overwrite file by directory, symlink by file, ect. + +inline +SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const FileMapping& fileObj) +{ + switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + return PASS_ONE; + + case SO_OVERWRITE_LEFT: + return fileObj.getFileSize<LEFT_SIDE>() > fileObj.getFileSize<RIGHT_SIDE>() ? PASS_ONE : PASS_TWO; + + case SO_OVERWRITE_RIGHT: + return fileObj.getFileSize<LEFT_SIDE>() < fileObj.getFileSize<RIGHT_SIDE>() ? PASS_ONE : PASS_TWO; + + case SO_MOVE_LEFT_SOURCE: // + case SO_MOVE_RIGHT_SOURCE: // [!] + return PASS_NEVER; + case SO_MOVE_LEFT_TARGET: // + case SO_MOVE_RIGHT_TARGET: //to be processed in second pass, after "move target" parent directory was created! + return PASS_TWO; + + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + return PASS_TWO; + } + assert(false); + return PASS_TWO; //dummy +} + + +inline +SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const SymLinkMapping& linkObj) +{ + switch (linkObj.getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + return PASS_ONE; //make sure to delete symlinks in first pass, and equally named file or dir in second pass: usecase "overwrite symlink with regular file"! + + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + assert(false); + case SO_OVERWRITE_LEFT: + case SO_OVERWRITE_RIGHT: + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + return PASS_TWO; + } + assert(false); + return PASS_TWO; //dummy +} + + +inline +SynchronizeFolderPair::PassId SynchronizeFolderPair::getPass(const DirMapping& dirObj) +{ + switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction + { + case SO_DELETE_LEFT: + case SO_DELETE_RIGHT: + return PASS_ONE; + + case SO_OVERWRITE_LEFT: + case SO_OVERWRITE_RIGHT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + assert(false); + case SO_CREATE_NEW_LEFT: + case SO_CREATE_NEW_RIGHT: + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + case SO_COPY_METADATA_TO_LEFT: + case SO_COPY_METADATA_TO_RIGHT: + return PASS_TWO; + } + assert(false); + return PASS_TWO; //dummy +} template <SynchronizeFolderPair::PassId pass> -void SynchronizeFolderPair::execute(HierarchyObject& hierObj) +void SynchronizeFolderPair::runPass(HierarchyObject& hierObj) { //synchronize files: std::for_each(hierObj.refSubFiles().begin(), hierObj.refSubFiles().end(), [&](FileMapping& fileObj) { - const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(fileObj); //to be deleted files on first pass, rest on second! - if (letsDoThis) - tryReportingError(procCallback_, [&]() { synchronizeFile(fileObj); }); + if (pass == getPass(fileObj)) + tryReportingError(procCallback_, [&] { synchronizeFile(fileObj); }); }); - //synchronize symbolic links: (process in second step only) - if (pass == SECOND_PASS) - std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), - [&](SymLinkMapping& linkObj) { tryReportingError(procCallback_, [&]() { synchronizeLink(linkObj); }); }); + //synchronize symbolic links: + std::for_each(hierObj.refSubLinks().begin(), hierObj.refSubLinks().end(), + [&](SymLinkMapping& linkObj) + { + if (pass == getPass(linkObj)) + tryReportingError(procCallback_, [&] { synchronizeLink(linkObj); }); + }); //synchronize folders: std::for_each(hierObj.refSubDirs().begin(), hierObj.refSubDirs().end(), [&](DirMapping& dirObj) { - const bool letsDoThis = (pass == FIRST_PASS) == diskSpaceIsReduced(dirObj); //to be deleted dirs on first pass, rest on second! - if (letsDoThis) //if we created all folders on first pass it would look strange for initial mirror sync when all folders are created at once - tryReportingError(procCallback_, [&]() { synchronizeFolder(dirObj); }); + if (pass == getPass(dirObj)) + tryReportingError(procCallback_, [&] { synchronizeFolder(dirObj); }); - //recursion! - this->execute<pass>(dirObj); + this->runPass<pass>(dirObj); //recurse }); } +//--------------------------------------------------------------------------------------------------------------- -void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const +namespace { - wxString logText; - Zstring target; - - switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction +inline +bool getTargetDir(SyncOperation syncOp, SelectedSide* side) +{ + switch (syncOp) { case SO_CREATE_NEW_LEFT: - target = fileObj.getBaseDirPf<LEFT_SIDE>() + fileObj.getRelativeName<RIGHT_SIDE>(); //can't use "getFullName" as target is not yet existing + case SO_DELETE_LEFT: + case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + *side = LEFT_SIDE; + return true; - logText = txtCreatingFile; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + case SO_CREATE_NEW_RIGHT: + case SO_DELETE_RIGHT: + case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: + *side = RIGHT_SIDE; + return true; - try - { - FileDescriptor sourceAttr; - copyFileUpdatingTo<LEFT_SIDE>(fileObj, - []() {}, //no target to delete - sourceAttr); + case SO_DO_NOTHING: + case SO_EQUAL: + case SO_UNRESOLVED_CONFLICT: + break; //nothing to do + } + return false; +} +} - fileObj.copyTo<LEFT_SIDE>(&sourceAttr); //update FileMapping - } - catch (FileError&) - { - if (fileExists(fileObj.getFullName<RIGHT_SIDE>())) - throw; - //source deleted meanwhile... - procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<RIGHT_SIDE>())); - fileObj.removeObject<RIGHT_SIDE>(); - } - break; +inline +void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const +{ + const SyncOperation syncOp = fileObj.getSyncOperation(); + + SelectedSide sideTrg = LEFT_SIDE; + + if (getTargetDir(syncOp, &sideTrg)) + { + if (sideTrg == LEFT_SIDE) + synchronizeFileInt<LEFT_SIDE>(fileObj, syncOp); + else + synchronizeFileInt<RIGHT_SIDE>(fileObj, syncOp); + } +} + + +template <SelectedSide sideTrg> +void SynchronizeFolderPair::synchronizeFileInt(FileMapping& fileObj, SyncOperation syncOp) const +{ + static const SelectedSide sideSrc = OtherSide<sideTrg>::result; + + switch (syncOp) + { + case SO_CREATE_NEW_LEFT: case SO_CREATE_NEW_RIGHT: - target = fileObj.getBaseDirPf<RIGHT_SIDE>() + fileObj.getRelativeName<LEFT_SIDE>(); + { + const Zstring& target = fileObj.getBaseDirPf<sideTrg>() + fileObj.getRelativeName<sideSrc>(); //can't use "getFullName" as target is not yet existing - logText = txtCreatingFile; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + reportInfo(txtCreatingFile, target); try { - FileDescriptor sourceAttr; - copyFileUpdatingTo<RIGHT_SIDE>(fileObj, - []() {}, //no target to delete - sourceAttr); + FileAttrib newAttr; + copyFileUpdatingTo<sideTrg>(fileObj, [] {}, /*no target to delete*/ newAttr); - fileObj.copyTo<RIGHT_SIDE>(&sourceAttr); //update FileMapping + const FileDescriptor descrSource(newAttr.modificationTime, newAttr.fileSize, newAttr.sourceFileId); + const FileDescriptor descrTarget(newAttr.modificationTime, newAttr.fileSize, newAttr.targetFileId); + fileObj.syncTo<sideTrg>(descrTarget, &descrSource); //update FileMapping } catch (FileError&) { - if (fileExists(fileObj.getFullName<LEFT_SIDE>())) + if (fileExists(fileObj.getFullName<sideSrc>())) throw; //source deleted meanwhile... - procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<LEFT_SIDE>())); - fileObj.removeObject<LEFT_SIDE>(); + procCallback_.updateProcessedData(0, to<zen::Int64>(fileObj.getFileSize<sideSrc>())); + fileObj.removeObject<sideSrc>(); } - break; + } + break; case SO_DELETE_LEFT: - logText = replaceCpy(delHandlingLeft_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); + case SO_DELETE_RIGHT: + reportInfo(getDelHandling<sideTrg>().getTxtRemovingFile(), fileObj.getFullName<sideTrg>()); - delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw FileError - fileObj.removeObject<LEFT_SIDE>(); //update FileMapping + getDelHandling<sideTrg>().removeFile(fileObj.getObjRelativeName()); //throw FileError + fileObj.removeObject<sideTrg>(); //update FileMapping break; - case SO_DELETE_RIGHT: - logText = replaceCpy(delHandlingRight_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_RIGHT_TARGET: + if (FileMapping* targetObj = dynamic_cast<FileMapping*>(FileSystemObject::retrieve(fileObj.getMoveRef()))) + { + FileMapping* sourceObj = &fileObj; - delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw FileError - fileObj.removeObject<RIGHT_SIDE>(); //update FileMapping - break; + if (syncOp != SO_MOVE_LEFT_SOURCE && syncOp != SO_MOVE_RIGHT_SOURCE) + std::swap(sourceObj, targetObj); - case SO_OVERWRITE_LEFT: - { - target = fileObj.getBaseDirPf<LEFT_SIDE>() + fileObj.getRelativeName<RIGHT_SIDE>(); //respect differences in case of source object + assert((sourceObj->getSyncOperation() == SO_MOVE_LEFT_SOURCE && targetObj->getSyncOperation() == SO_MOVE_LEFT_TARGET && sideTrg == LEFT_SIDE) || + (sourceObj->getSyncOperation() == SO_MOVE_RIGHT_SOURCE && targetObj->getSyncOperation() == SO_MOVE_RIGHT_TARGET && sideTrg == RIGHT_SIDE)); - logText = txtOverwritingFile; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + const Zstring& source = sourceObj->getFullName<sideTrg>(); + const Zstring& target = targetObj->getBaseDirPf<sideTrg>() + targetObj->getRelativeName<sideSrc>(); - FileDescriptor sourceAttr; - copyFileUpdatingTo<LEFT_SIDE>(fileObj, - [&]() //delete target at appropriate time - { - procCallback_.reportStatus(replaceCpy(delHandlingLeft_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>()))); + reportInfo(replaceCpy(txtMovingFile, L"%y", utf8CvrtTo<std::wstring>(target)), source); - delHandlingLeft_.removeFile(fileObj.getObjRelativeName()); //throw FileError - fileObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) + renameFile(source, target); //throw FileError; - procCallback_.reportStatus(logText); //restore status text copy file - }, sourceAttr); + const FileDescriptor descrTarget(sourceObj->getLastWriteTime<sideTrg>(), + sourceObj->getFileSize <sideTrg>(), + sourceObj->getFileId <sideTrg>()); - fileObj.copyTo<LEFT_SIDE>(&sourceAttr); //update FileMapping - } - break; + sourceObj->removeObject<sideTrg>(); // + targetObj->syncTo<sideTrg>(descrTarget); //update FileMapping + } + break; + case SO_OVERWRITE_LEFT: case SO_OVERWRITE_RIGHT: { - target = fileObj.getBaseDirPf<RIGHT_SIDE>() + fileObj.getRelativeName<LEFT_SIDE>(); //respect differences in case of source object + const Zstring& target = fileObj.getBaseDirPf<sideTrg>() + fileObj.getRelativeName<sideSrc>(); //respect differences in case of source object - logText = txtOverwritingFile; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + reportInfo(txtOverwritingFile, target); - FileDescriptor sourceAttr; - copyFileUpdatingTo<RIGHT_SIDE>(fileObj, - [&]() //delete target at appropriate time + FileAttrib newAttr; + copyFileUpdatingTo<sideTrg>(fileObj, + [&] //delete target at appropriate time { - procCallback_.reportStatus(replaceCpy(delHandlingRight_.getTxtRemovingFile(), L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>()))); + reportStatus(this->getDelHandling<sideTrg>().getTxtRemovingFile(), fileObj.getFullName<sideTrg>()); - delHandlingRight_.removeFile(fileObj.getObjRelativeName()); //throw FileError - fileObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) + this->getDelHandling<sideTrg>().removeFile(fileObj.getObjRelativeName()); //throw FileError + fileObj.removeObject<sideTrg>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) - procCallback_.reportStatus(logText); //restore status text copy file - }, sourceAttr); + reportStatus(txtOverwritingFile, target); //restore status text copy file + }, newAttr); - fileObj.copyTo<RIGHT_SIDE>(&sourceAttr); //update FileMapping + const FileDescriptor descrSource(newAttr.modificationTime, newAttr.fileSize, newAttr.sourceFileId); + const FileDescriptor descrTarget(newAttr.modificationTime, newAttr.fileSize, newAttr.targetFileId); + fileObj.syncTo<sideTrg>(descrTarget, &descrSource); //update FileMapping } break; case SO_COPY_METADATA_TO_LEFT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); - - if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(fileObj.getFullName<LEFT_SIDE>(), - beforeLast(fileObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<RIGHT_SIDE>()); //throw FileError; - - if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision - setFileTime(fileObj.getFullName<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), SYMLINK_FOLLOW); //throw FileError - //do NOT read *current* source file time, but use buffered value which corresponds to time of comparison! - - fileObj.copyTo<LEFT_SIDE>(NULL); //-> both sides *should* be completely equal now... - break; - case SO_COPY_METADATA_TO_RIGHT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(fileObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + { + reportInfo(txtWritingAttributes, fileObj.getFullName<sideTrg>()); - if (fileObj.getShortName<LEFT_SIDE>() != fileObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(fileObj.getFullName<RIGHT_SIDE>(), - beforeLast(fileObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<LEFT_SIDE>()); //throw FileError; + if (fileObj.getShortName<sideTrg>() != fileObj.getShortName<sideSrc>()) //adapt difference in case (windows only) + renameFile(fileObj.getFullName<sideTrg>(), + beforeLast(fileObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + fileObj.getShortName<sideSrc>()); //throw FileError; - if (!sameFileTime(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision - setFileTime(fileObj.getFullName<RIGHT_SIDE>(), fileObj.getLastWriteTime<LEFT_SIDE>(), SYMLINK_FOLLOW); //throw FileError + if (!sameFileTime(fileObj.getLastWriteTime<sideTrg>(), fileObj.getLastWriteTime<sideSrc>(), 2)) //respect 2 second FAT/FAT32 precision + setFileTime(fileObj.getFullName<sideTrg>(), fileObj.getLastWriteTime<sideSrc>(), SYMLINK_FOLLOW); //throw FileError + //do NOT read *current* source file time, but use buffered value which corresponds to time of comparison! - fileObj.copyTo<RIGHT_SIDE>(NULL); //-> both sides *should* be completely equal now... - break; + const FileDescriptor descrTarget(fileObj.getLastWriteTime<sideSrc>(), + fileObj.getFileSize <sideTrg >(), + fileObj.getFileId <sideTrg >()); + fileObj.syncTo<sideTrg>(descrTarget); //-> both sides *should* be completely equal now... + } + break; case SO_DO_NOTHING: case SO_EQUAL: @@ -1049,137 +1416,112 @@ void SynchronizeFolderPair::synchronizeFile(FileMapping& fileObj) const } +inline void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const { - wxString logText; - Zstring target; + const SyncOperation syncOp = linkObj.getSyncOperation(); - switch (linkObj.getSyncOperation()) //evaluate comparison result and sync direction + SelectedSide sideTrg = LEFT_SIDE; + + if (getTargetDir(syncOp, &sideTrg)) { - case SO_CREATE_NEW_LEFT: - target = linkObj.getBaseDirPf<LEFT_SIDE>() + linkObj.getRelativeName<RIGHT_SIDE>(); + if (sideTrg == LEFT_SIDE) + synchronizeLinkInt<LEFT_SIDE>(linkObj, syncOp); + else + synchronizeLinkInt<RIGHT_SIDE>(linkObj, syncOp); + } +} - logText = txtCreatingLink; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); - try - { - zen::copySymlink(linkObj.getFullName<RIGHT_SIDE>(), target, copyFilePermissions); //throw FileError +template <SelectedSide sideTrg> +void SynchronizeFolderPair::synchronizeLinkInt(SymLinkMapping& linkObj, SyncOperation syncOp) const +{ + static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - linkObj.copyTo<LEFT_SIDE>(); //update SymLinkMapping - } - catch (FileError&) - { - if (fileExists(linkObj.getFullName<RIGHT_SIDE>())) - throw; - //source deleted meanwhile... - linkObj.removeObject<RIGHT_SIDE>(); - } - break; + auto deleteSymlink = [&] + { + switch (linkObj.getLinkType<sideTrg>()) + { + case LinkDescriptor::TYPE_DIR: + this->getDelHandling<sideTrg>().removeFolder(linkObj.getObjRelativeName()); //throw FileError + break; + + case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link + this->getDelHandling<sideTrg>().removeFile(linkObj.getObjRelativeName()); //throw FileError + break; + } + }; + switch (syncOp) + { + case SO_CREATE_NEW_LEFT: case SO_CREATE_NEW_RIGHT: - target = linkObj.getBaseDirPf<RIGHT_SIDE>() + linkObj.getRelativeName<LEFT_SIDE>(); + { + const Zstring& target = linkObj.getBaseDirPf<sideTrg>() + linkObj.getRelativeName<sideSrc>(); - logText = txtCreatingLink; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + reportInfo(txtCreatingLink, target); try { - zen::copySymlink(linkObj.getFullName<LEFT_SIDE>(), target, copyFilePermissions); //throw FileError + zen::copySymlink(linkObj.getFullName<sideSrc>(), target, copyFilePermissions); //throw FileError - linkObj.copyTo<RIGHT_SIDE>(); //update SymLinkMapping + linkObj.copyTo<sideTrg>(); //update SymLinkMapping } catch (FileError&) { - if (fileExists(linkObj.getFullName<LEFT_SIDE>())) + if (fileExists(linkObj.getFullName<sideSrc>())) throw; //source deleted meanwhile... - linkObj.removeObject<LEFT_SIDE>(); + linkObj.removeObject<sideSrc>(); } - break; + } + break; case SO_DELETE_LEFT: - logText = replaceCpy(delHandlingLeft_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); - - deleteSymlink<LEFT_SIDE>(linkObj); //throw FileError - - linkObj.removeObject<LEFT_SIDE>(); //update SymLinkMapping - break; - case SO_DELETE_RIGHT: - logText = replaceCpy(delHandlingRight_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + reportInfo(getDelHandling<sideTrg>().getTxtRemovingSymLink(), linkObj.getFullName<sideTrg>()); - deleteSymlink<RIGHT_SIDE>(linkObj); //throw FileError + deleteSymlink(); //throw FileError - linkObj.removeObject<RIGHT_SIDE>(); //update SymLinkMapping + linkObj.removeObject<sideTrg>(); //update SymLinkMapping break; case SO_OVERWRITE_LEFT: - target = linkObj.getBaseDirPf<LEFT_SIDE>() + linkObj.getRelativeName<RIGHT_SIDE>(); //respect differences in case of source object - - logText = txtOverwritingLink; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); - - procCallback_.reportStatus(replaceCpy(delHandlingLeft_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>()))); - deleteSymlink<LEFT_SIDE>(linkObj); //throw FileError - linkObj.removeObject<LEFT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) - - procCallback_.reportStatus(logText); //restore status text - zen::copySymlink(linkObj.getFullName<RIGHT_SIDE>(), target, copyFilePermissions); //throw FileError - - linkObj.copyTo<LEFT_SIDE>(); //update SymLinkMapping - break; - case SO_OVERWRITE_RIGHT: - target = linkObj.getBaseDirPf<RIGHT_SIDE>() + linkObj.getRelativeName<LEFT_SIDE>(); //respect differences in case of source object - - logText = txtOverwritingLink; - replace(logText, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + { + const Zstring& target = linkObj.getBaseDirPf<sideTrg>() + linkObj.getRelativeName<sideSrc>(); //respect differences in case of source object - procCallback_.reportStatus(replaceCpy(delHandlingRight_.getTxtRemovingSymLink(), L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>()))); - deleteSymlink<RIGHT_SIDE>(linkObj); //throw FileError - linkObj.removeObject<RIGHT_SIDE>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) + reportInfo(txtOverwritingLink, target); - procCallback_.reportStatus(logText); //restore status text - zen::copySymlink(linkObj.getFullName<LEFT_SIDE>(), target, copyFilePermissions); //throw FileError + reportStatus(getDelHandling<sideTrg>().getTxtRemovingSymLink(), linkObj.getFullName<sideTrg>()); + deleteSymlink(); //throw FileError + linkObj.removeObject<sideTrg>(); //remove file from FileMapping, to keep in sync (if subsequent copying fails!!) - linkObj.copyTo<RIGHT_SIDE>(); //update SymLinkMapping - break; + reportStatus(txtOverwritingLink, target); //restore status text + zen::copySymlink(linkObj.getFullName<sideSrc>(), target, copyFilePermissions); //throw FileError + linkObj.copyTo<sideTrg>(); //update SymLinkMapping + } + break; case SO_COPY_METADATA_TO_LEFT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); - - if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(linkObj.getFullName<LEFT_SIDE>(), - beforeLast(linkObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<RIGHT_SIDE>()); //throw FileError; - - if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision - setFileTime(linkObj.getFullName<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), SYMLINK_DIRECT); //throw FileError - - linkObj.copyTo<LEFT_SIDE>(); //-> both sides *should* be completely equal now... - break; - case SO_COPY_METADATA_TO_RIGHT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(linkObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + reportInfo(txtWritingAttributes, linkObj.getFullName<sideTrg>()); - if (linkObj.getShortName<LEFT_SIDE>() != linkObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(linkObj.getFullName<RIGHT_SIDE>(), - beforeLast(linkObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<LEFT_SIDE>()); //throw FileError; + if (linkObj.getShortName<sideTrg>() != linkObj.getShortName<sideSrc>()) //adapt difference in case (windows only) + renameFile(linkObj.getFullName<sideTrg>(), + beforeLast(linkObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + linkObj.getShortName<sideSrc>()); //throw FileError; - if (!sameFileTime(linkObj.getLastWriteTime<LEFT_SIDE>(), linkObj.getLastWriteTime<RIGHT_SIDE>(), 2)) //respect 2 second FAT/FAT32 precision - setFileTime(linkObj.getFullName<RIGHT_SIDE>(), linkObj.getLastWriteTime<LEFT_SIDE>(), SYMLINK_DIRECT); //throw FileError + if (!sameFileTime(linkObj.getLastWriteTime<sideTrg>(), linkObj.getLastWriteTime<sideSrc>(), 2)) //respect 2 second FAT/FAT32 precision + setFileTime(linkObj.getFullName<sideTrg>(), linkObj.getLastWriteTime<sideSrc>(), SYMLINK_DIRECT); //throw FileError - linkObj.copyTo<RIGHT_SIDE>(); //-> both sides *should* be completely equal now... + linkObj.copyTo<sideTrg>(); //-> both sides *should* be completely equal now... break; + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: + assert(false); case SO_DO_NOTHING: case SO_EQUAL: case SO_UNRESOLVED_CONFLICT: @@ -1193,126 +1535,89 @@ void SynchronizeFolderPair::synchronizeLink(SymLinkMapping& linkObj) const } +inline void SynchronizeFolderPair::synchronizeFolder(DirMapping& dirObj) const { - wxString logText; - Zstring target; + const SyncOperation syncOp = dirObj.getSyncOperation(); - //synchronize folders: - switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction - { - case SO_CREATE_NEW_LEFT: - //some check to catch the error that directory on source has been deleted externally after "compare"... - if (!dirExists(dirObj.getFullName<RIGHT_SIDE>())) - { - // throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<RIGHT_SIDE>() + "\""); - const SyncStatistics subObjects(dirObj); //DON'T forget to notify about implicitly deleted objects! - procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); + SelectedSide sideTrg = LEFT_SIDE; - dirObj.refSubFiles().clear(); //...then remove sub-objects - dirObj.refSubLinks().clear(); // - dirObj.refSubDirs ().clear(); // - dirObj.removeObject<RIGHT_SIDE>(); - } - else - { - target = dirObj.getBaseDirPf<LEFT_SIDE>() + dirObj.getRelativeName<RIGHT_SIDE>(); + if (getTargetDir(syncOp, &sideTrg)) + { + if (sideTrg == LEFT_SIDE) + synchronizeFolderInt<LEFT_SIDE>(dirObj, syncOp); + else + synchronizeFolderInt<RIGHT_SIDE>(dirObj, syncOp); + } +} - logText = replaceCpy(txtCreatingFolder, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); - createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), copyFilePermissions); //no symlink copying! - dirObj.copyTo<LEFT_SIDE>(); //update DirMapping - } - break; +template <SelectedSide sideTrg> +void SynchronizeFolderPair::synchronizeFolderInt(DirMapping& dirObj, SyncOperation syncOp) const +{ + static const SelectedSide sideSrc = OtherSide<sideTrg>::result; + switch (syncOp) + { + case SO_CREATE_NEW_LEFT: case SO_CREATE_NEW_RIGHT: - //some check to catch the error that directory on source has been deleted externally after "compare"... - if (!dirExists(dirObj.getFullName<LEFT_SIDE>())) + if (dirExists(dirObj.getFullName<sideSrc>())) { - //throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<LEFT_SIDE>() + "\""); - const SyncStatistics subObjects(dirObj); //DON'T forget to notify about implicitly deleted objects! - procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); + const Zstring& target = dirObj.getBaseDirPf<sideTrg>() + dirObj.getRelativeName<sideSrc>(); - dirObj.refSubFiles().clear(); //...then remove sub-objects - dirObj.refSubLinks().clear(); // - dirObj.refSubDirs ().clear(); // - dirObj.removeObject<LEFT_SIDE>(); + reportInfo(txtCreatingFolder, target); + createDirectory(target, dirObj.getFullName<sideSrc>(), copyFilePermissions); //no symlink copying! + dirObj.copyTo<sideTrg>(); //update DirMapping } - else + else //source directory has been deleted externally after "compare"... { - target = dirObj.getBaseDirPf<RIGHT_SIDE>() + dirObj.getRelativeName<LEFT_SIDE>(); - - logText = replaceCpy(txtCreatingFolder, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + // throw FileError(_ ("Source directory does not exist anymore:") + "\n\"" + dirObj.getFullName<sideSrc>() + "\""); + const SyncStatistics subStats(dirObj); //DON'T forget to notify about implicitly deleted objects! + procCallback_.updateProcessedData(getCUD(subStats), to<zen::Int64>(subStats.getDataToProcess())); - createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), copyFilePermissions); //no symlink copying! - dirObj.copyTo<RIGHT_SIDE>(); //update DirMapping + dirObj.refSubFiles().clear(); //...then remove sub-objects + dirObj.refSubLinks().clear(); // + dirObj.refSubDirs ().clear(); // + dirObj.removeObject<sideSrc>(); } break; case SO_COPY_METADATA_TO_LEFT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); - - if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(dirObj.getFullName<LEFT_SIDE>(), - beforeLast(dirObj.getFullName<LEFT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<RIGHT_SIDE>()); //throw FileError; - //copyFileTimes(dirObj.getFullName<RIGHT_SIDE>(), dirObj.getFullName<LEFT_SIDE>(), true); //throw FileError -> is executed after sub-objects have finished synchronization - - dirObj.copyTo<LEFT_SIDE>(); //-> both sides *should* be completely equal now... - break; - case SO_COPY_METADATA_TO_RIGHT: - logText = replaceCpy(txtWritingAttributes, L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + reportInfo(txtWritingAttributes, dirObj.getFullName<sideTrg>()); - if (dirObj.getShortName<LEFT_SIDE>() != dirObj.getShortName<RIGHT_SIDE>()) //adapt difference in case (windows only) - renameFile(dirObj.getFullName<RIGHT_SIDE>(), - beforeLast(dirObj.getFullName<RIGHT_SIDE>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<LEFT_SIDE>()); //throw FileError; - //copyFileTimes(dirObj.getFullName<LEFT_SIDE>(), dirObj.getFullName<RIGHT_SIDE>(), true); //throw FileError -> is executed after sub-objects have finished synchronization + if (dirObj.getShortName<sideTrg>() != dirObj.getShortName<sideSrc>()) //adapt difference in case (windows only) + renameFile(dirObj.getFullName<sideTrg>(), + beforeLast(dirObj.getFullName<sideTrg>(), FILE_NAME_SEPARATOR) + FILE_NAME_SEPARATOR + dirObj.getShortName<sideSrc>()); //throw FileError; + //copyFileTimes -> useless at this time: modification time changes with each child-object creation/deletion - dirObj.copyTo<RIGHT_SIDE>(); //-> both sides *should* be completely equal now... + dirObj.copyTo<sideTrg>(); //-> both sides *should* be completely equal now... break; case SO_DELETE_LEFT: - //status information - logText = replaceCpy(delHandlingLeft_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<LEFT_SIDE>())); - procCallback_.reportInfo(logText); + case SO_DELETE_RIGHT: + { + reportInfo(getDelHandling<sideTrg>().getTxtRemovingDir(), dirObj.getFullName<sideTrg>()); - delHandlingLeft_.removeFolder(dirObj.getObjRelativeName()); //throw FileError - { - //progress indicator update: DON'T forget to notify about implicitly deleted objects! - const SyncStatistics subObjects(dirObj); - //...then remove everything - dirObj.refSubFiles().clear(); - dirObj.refSubLinks().clear(); - dirObj.refSubDirs ().clear(); - procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); - } - dirObj.removeObject<LEFT_SIDE>(); //update DirMapping - break; + getDelHandling<sideTrg>().removeFolder(dirObj.getObjRelativeName()); //throw FileError - case SO_DELETE_RIGHT: - //status information - logText = replaceCpy(delHandlingRight_.getTxtRemovingDir(), L"%x", utf8CvrtTo<wxString>(dirObj.getFullName<RIGHT_SIDE>())); - procCallback_.reportInfo(logText); + //progress indicator update: DON'T forget to notify about implicitly deleted objects! + const SyncStatistics subStats(dirObj); + dirObj.refSubFiles().clear(); //...then remove everything + dirObj.refSubLinks().clear(); + dirObj.refSubDirs ().clear(); + procCallback_.updateProcessedData(getCUD(subStats), to<zen::Int64>(subStats.getDataToProcess())); - delHandlingRight_.removeFolder(dirObj.getObjRelativeName()); //throw FileError - { - //progress indicator update: DON'T forget to notify about implicitly deleted objects! - const SyncStatistics subObjects(dirObj); - //...then remove everything - dirObj.refSubFiles().clear(); - dirObj.refSubLinks().clear(); - dirObj.refSubDirs ().clear(); - procCallback_.updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), to<zen::Int64>(subObjects.getDataToProcess())); - } - dirObj.removeObject<RIGHT_SIDE>(); //update DirMapping - break; + dirObj.removeObject<sideTrg>(); //update DirMapping + } + break; case SO_OVERWRITE_RIGHT: case SO_OVERWRITE_LEFT: + case SO_MOVE_LEFT_SOURCE: + case SO_MOVE_RIGHT_SOURCE: + case SO_MOVE_LEFT_TARGET: + case SO_MOVE_RIGHT_TARGET: assert(false); case SO_UNRESOLVED_CONFLICT: case SO_DO_NOTHING: @@ -1336,31 +1641,27 @@ void makeSameLength(std::wstring& first, std::wstring& second) second.resize(maxPref, L' '); } + +/* struct LessDependentDirectory : public std::binary_function<Zstring, Zstring, bool> { +-> a *very* bad idea: this is NOT a strict weak ordering! No transitivity of equivalence! + bool operator()(const Zstring& lhs, const Zstring& rhs) const { return LessFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); } }; - -struct EqualDependentDirectory : public std::binary_function<Zstring, Zstring, bool> -{ - bool operator()(const Zstring& lhs, const Zstring& rhs) const - { - return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), - Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); - } -}; +*/ } void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCfg>& syncConfig, FolderComparison& folderCmp) { - //prevent shutdown while synchronization is in progress - DisableStandby dummy; - (void)dummy; + //prevent shutdown while synchronization is in progress + PreventStandby dummy; + (void)dummy; #ifdef NDEBUG wxLogNull noWxLogs; //prevent wxWidgets logging @@ -1371,12 +1672,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf if (syncConfig.size() != folderCmp.size()) throw std::logic_error("Programming Error: Contract violation!"); - //inform about the total amount of data that will be processed from now on const SyncStatistics statisticsTotal(folderCmp); //keep at beginning so that all gui elements are initialized properly - procCallback.initNewProcess(statisticsTotal.getCreate() + statisticsTotal.getOverwrite() + statisticsTotal.getDelete(), + procCallback.initNewProcess(getCUD(statisticsTotal), to<zen::Int64>(statisticsTotal.getDataToProcess()), ProcessCallback::PROCESS_SYNCHRONIZING); @@ -1404,12 +1704,34 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //-------------------some basic checks:------------------------------------------ + auto dependentDir = [](const Zstring& lhs, const Zstring& rhs) //note: this is NOT an equivalence relation! + { + return EqualFilename()(Zstring(lhs.c_str(), std::min(lhs.length(), rhs.length())), + Zstring(rhs.c_str(), std::min(lhs.length(), rhs.length()))); + }; //aggregate information - typedef std::set<Zstring, LessDependentDirectory> DirReadSet; //count (at least one) read access - typedef std::map<Zstring, size_t, LessDependentDirectory> DirWriteMap; //count (read+)write accesses - DirReadSet dirReadCount; - DirWriteMap dirWriteCount; + std::map<Zstring, std::pair<size_t, size_t>> dirReadWriteCount; //count read/write accesses + auto incReadCount = [&](const Zstring& baseDir) + { + dirReadWriteCount[baseDir]; //create entry + for (auto iter = dirReadWriteCount.begin(); iter != dirReadWriteCount.end(); ++iter) + { + auto& countRef = iter->second; + if (dependentDir(baseDir, iter->first)) + ++countRef.first; + } + }; + auto incWriteCount = [&](const Zstring& baseDir) + { + dirReadWriteCount[baseDir]; //create entry + for (auto iter = dirReadWriteCount.begin(); iter != dirReadWriteCount.end(); ++iter) + { + auto& countRef = iter->second; + if (dependentDir(baseDir, iter->first)) + ++countRef.second; + } + }; typedef std::vector<std::pair<Zstring, Zstring> > DirPairList; DirPairList significantDiff; @@ -1417,8 +1739,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf typedef std::vector<std::pair<Zstring, std::pair<zen::Int64, zen::Int64> > > DirSpaceRequAvailList; //dirname / space required / space available DirSpaceRequAvailList diskSpaceMissing; - typedef std::set<Zstring, LessDependentDirectory> DirRecyclerMissing; - DirRecyclerMissing recyclMissing; + std::set<Zstring> recyclMissing; //start checking folder pairs for (auto j = begin(folderCmp); j != end(folderCmp); ++j) @@ -1435,13 +1756,13 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf const SyncStatistics folderPairStat(*j); //aggregate basic information - const bool writeLeft = folderPairStat.getCreate <LEFT_SIDE>() + - folderPairStat.getOverwrite<LEFT_SIDE>() + - folderPairStat.getDelete <LEFT_SIDE>() > 0; + const bool writeLeft = folderPairStat.getCreate<LEFT_SIDE>() + + folderPairStat.getUpdate<LEFT_SIDE>() + + folderPairStat.getDelete<LEFT_SIDE>() > 0; - const bool writeRight = folderPairStat.getCreate <RIGHT_SIDE>() + - folderPairStat.getOverwrite<RIGHT_SIDE>() + - folderPairStat.getDelete <RIGHT_SIDE>() > 0; + const bool writeRight = folderPairStat.getCreate<RIGHT_SIDE>() + + folderPairStat.getUpdate<RIGHT_SIDE>() + + folderPairStat.getDelete<RIGHT_SIDE>() > 0; //skip folder pair if there is nothing to do (except for automatic mode, where data base needs to be written even in this case) if (!writeLeft && !writeRight && @@ -1453,7 +1774,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check empty input fields: basically this only makes sense if empty field is not target (and not automatic mode: because of db file creation) - if ((j->getBaseDirPf<LEFT_SIDE>(). empty() && (writeLeft || folderPairCfg.inAutomaticMode)) || + if ((j->getBaseDirPf<LEFT_SIDE >().empty() && (writeLeft || folderPairCfg.inAutomaticMode)) || (j->getBaseDirPf<RIGHT_SIDE>().empty() && (writeRight || folderPairCfg.inAutomaticMode))) { procCallback.reportFatalError(_("Target directory name must not be empty!")); @@ -1462,30 +1783,32 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf } //aggregate information of folders used by multiple pairs in read/write access - if (!EqualDependentDirectory()(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general + if (!dependentDir(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())) //true in general { - if (writeLeft) + if (writeLeft && writeRight) + { + incWriteCount(j->getBaseDirPf<LEFT_SIDE >()); + incWriteCount(j->getBaseDirPf<RIGHT_SIDE>()); + } + else if (writeLeft) { - ++dirWriteCount[j->getBaseDirPf<LEFT_SIDE>()]; - if (writeRight) - ++dirWriteCount[j->getBaseDirPf<RIGHT_SIDE>()]; - else - dirReadCount.insert(j->getBaseDirPf<RIGHT_SIDE>()); + incWriteCount(j->getBaseDirPf<LEFT_SIDE>()); + incReadCount (j->getBaseDirPf<RIGHT_SIDE>()); } else if (writeRight) { - dirReadCount.insert(j->getBaseDirPf<LEFT_SIDE>()); - ++dirWriteCount[j->getBaseDirPf<RIGHT_SIDE>()]; + incReadCount (j->getBaseDirPf<LEFT_SIDE>()); + incWriteCount(j->getBaseDirPf<RIGHT_SIDE>()); } } else //if folder pair contains two dependent folders, a warning was already issued after comparison; in this context treat as one write access at most { if (writeLeft || writeRight) - ++dirWriteCount[j->getBaseDirPf<LEFT_SIDE>()]; + incWriteCount(j->getBaseDirPf<LEFT_SIDE>()); } - if (folderPairStat.getOverwrite() + folderPairStat.getDelete() > 0) + if (folderPairStat.getUpdate() + folderPairStat.getDelete() > 0) { if (folderPairCfg.handleDeletion == zen::MOVE_TO_CUSTOM_DIRECTORY) { @@ -1500,7 +1823,9 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf } //avoid data loss when source directory doesn't (temporarily?) exist anymore AND user chose to ignore errors (else we wouldn't arrive here) - if (folderPairStat.getCreate() + folderPairStat.getOverwrite() + folderPairStat.getConflict() == 0 && + if (folderPairStat.getCreate() + + folderPairStat.getUpdate() + + folderPairStat.getConflict() == 0 && folderPairStat.getDelete() > 0) //deletions only... (respect filtered items!) { Zstring missingSrcDir; @@ -1522,9 +1847,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf significantDiff.push_back(std::make_pair(j->getBaseDirPf<LEFT_SIDE>(), j->getBaseDirPf<RIGHT_SIDE>())); //check for sufficient free diskspace in left directory - const std::pair<zen::Int64, zen::Int64> spaceNeeded = DiskSpaceNeeded(*j, - delHandlerFp.first.deletionFreesSpace(), - delHandlerFp.second.deletionFreesSpace()).getSpaceTotal(); + const std::pair<Int64, Int64> spaceNeeded = DiskSpaceNeeded::calculate(*j, delHandlerFp.first.deletionFreesSpace(), + delHandlerFp.second.deletionFreesSpace()); wxLongLong freeDiskSpaceLeft; if (wxGetDiskSpace(toWx(j->getBaseDirPf<LEFT_SIDE>()), NULL, &freeDiskSpaceLeft)) { @@ -1546,14 +1870,14 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf #ifdef FFS_WIN if (folderPairCfg.handleDeletion == MOVE_TO_RECYCLE_BIN) { - if (folderPairStat.getOverwrite<LEFT_SIDE>() + - folderPairStat.getDelete <LEFT_SIDE>() > 0 && + if (folderPairStat.getUpdate<LEFT_SIDE>() + + folderPairStat.getDelete<LEFT_SIDE>() > 0 && recycleBinStatus(j->getBaseDirPf<LEFT_SIDE>()) != STATUS_REC_EXISTS) recyclMissing.insert(j->getBaseDirPf<LEFT_SIDE>()); - if (folderPairStat.getOverwrite<RIGHT_SIDE>() + - folderPairStat.getDelete <RIGHT_SIDE>() > 0 && + if (folderPairStat.getUpdate<RIGHT_SIDE>() + + folderPairStat.getDelete<RIGHT_SIDE>() > 0 && recycleBinStatus(j->getBaseDirPf<RIGHT_SIDE>()) != STATUS_REC_EXISTS) recyclMissing.insert(j->getBaseDirPf<RIGHT_SIDE>()); @@ -1565,20 +1889,20 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf if (statisticsTotal.getConflict() > 0) { //show the first few conflicts in warning message also: - wxString warningMessage = wxString(_("Unresolved conflicts existing!")) + - wxT(" (") + toStringSep(statisticsTotal.getConflict()) + wxT(")\n\n"); + std::wstring warningMessage = _("Unresolved conflicts existing!") + + L" (" + toStringSep(statisticsTotal.getConflict()) + L")\n\n"; const SyncStatistics::ConflictTexts& firstConflicts = statisticsTotal.getFirstConflicts(); //get first few sync conflicts for (SyncStatistics::ConflictTexts::const_iterator i = firstConflicts.begin(); i != firstConflicts.end(); ++i) { - wxString conflictDescription = i->second; + std::wstring conflictDescription = i->second; //conflictDescription.Replace(wxT("\n"), wxT(" ")); //remove line-breaks warningMessage += std::wstring(L"\"") + i->first + L"\": " + conflictDescription + L"\n\n"; } if (statisticsTotal.getConflict() > static_cast<int>(firstConflicts.size())) - warningMessage += wxT("[...]\n\n"); + warningMessage += L"[...]\n\n"; warningMessage += _("You can ignore conflicts and continue synchronization."); @@ -1589,13 +1913,14 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check if more than 50% of total number of files/dirs are to be created/overwritten/deleted if (!significantDiff.empty()) { - wxString warningMessage = _("Significant difference detected:"); + std::wstring warningMessage = _("Significant difference detected:"); for (DirPairList::const_iterator i = significantDiff.begin(); i != significantDiff.end(); ++i) warningMessage += std::wstring(L"\n\n") + i->first + L" <-> " + L"\n" + i->second; - warningMessage += wxString(L"\n\n") + _("More than 50% of the total number of files will be copied or deleted!"); + warningMessage += L"\n\n"; + warningMessage += _("More than 50% of the total number of files will be copied or deleted!"); procCallback.reportWarning(warningMessage, m_warnings.warningSignificantDifference); } @@ -1604,13 +1929,13 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check for sufficient free diskspace if (!diskSpaceMissing.empty()) { - wxString warningMessage = _("Not enough free disk space available in:"); + std::wstring warningMessage = _("Not enough free disk space available in:"); for (auto i = diskSpaceMissing.begin(); i != diskSpaceMissing.end(); ++i) warningMessage += std::wstring(L"\n\n") + L"\"" + i->first + L"\"\n" + - _("Free disk space required:") + wxT(" ") + filesizeToShortString(to<UInt64>(i->second.first)) + L"\n" + - _("Free disk space available:") + wxT(" ") + filesizeToShortString(to<UInt64>(i->second.second)); + _("Free disk space required:") + L" " + filesizeToShortString(to<UInt64>(i->second.first)) + L"\n" + + _("Free disk space available:") + L" " + filesizeToShortString(to<UInt64>(i->second.second)); procCallback.reportWarning(warningMessage, m_warnings.warningNotEnoughDiskSpace); } @@ -1620,11 +1945,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf #ifdef FFS_WIN if (!recyclMissing.empty()) { - wxString warningMessage = _("Recycle Bin is not available for the following paths! Files will be deleted permanently instead:"); + std::wstring warningMessage = _("Recycle Bin is not available for the following paths! Files will be deleted permanently instead:"); warningMessage += L"\n"; std::for_each(recyclMissing.begin(), recyclMissing.end(), - [&](const Zstring& path) { warningMessage += L"\n" + toWx(path); }); + [&](const Zstring& path) { warningMessage += L"\n" + utf8CvrtTo<std::wstring>(path); }); procCallback.reportWarning(warningMessage, m_warnings.warningRecyclerMissing); } @@ -1632,15 +1957,18 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check if folders are used by multiple pairs in read/write access std::vector<Zstring> conflictDirs; - for (DirWriteMap::const_iterator i = dirWriteCount.begin(); i != dirWriteCount.end(); ++i) - if (i->second >= 2 || //multiple write accesses - (i->second == 1 && dirReadCount.find(i->first) != dirReadCount.end())) //read/write access - conflictDirs.push_back(i->first); + for (auto iter = dirReadWriteCount.cbegin(); iter != dirReadWriteCount.cend(); ++iter) + { + const auto& countRef = iter->second; + if (countRef.second >= 2 || //multiple write accesses + (countRef.second == 1 && countRef.first >= 1)) //read/write access + conflictDirs.push_back(iter->first); + } if (!conflictDirs.empty()) { - wxString warningMessage = wxString(_("A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!")) + wxT("\n"); - for (std::vector<Zstring>::const_iterator i = conflictDirs.begin(); i != conflictDirs.end(); ++i) + std::wstring warningMessage = _("A directory will be modified which is part of multiple folder pairs! Please review synchronization settings!") + L"\n"; + for (auto i = conflictDirs.begin(); i != conflictDirs.end(); ++i) warningMessage += std::wstring(L"\n") + L"\"" + *i + L"\""; procCallback.reportWarning(warningMessage, m_warnings.warningMultiFolderWriteAccess); @@ -1677,8 +2005,8 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf makeSameLength(left, right); const std::wstring statusTxt = _("Processing folder pair:") + L" \n" + - L"\t" + left + L"\"" + j->getBaseDirPf<LEFT_SIDE>() + L"\"" + L" \n" + - L"\t" + right + L"\"" + j->getBaseDirPf<RIGHT_SIDE>() + L"\""; + L" " + left + L"\"" + j->getBaseDirPf<LEFT_SIDE>() + L"\"" + L" \n" + + L" " + right + L"\"" + j->getBaseDirPf<RIGHT_SIDE>() + L"\""; procCallback.reportInfo(statusTxt); //------------------------------------------------------------------------------------------ @@ -1725,7 +2053,6 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf if (folderPairCfg.inAutomaticMode) { procCallback.reportStatus(_("Generating database...")); - procCallback.forceUiRefresh(); tryReportingError(procCallback, [&]() { zen::saveToDisk(*j); }); //throw FileError guardUpdateDb.dismiss(); @@ -1737,7 +2064,7 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf } catch (const std::exception& e) { - procCallback.reportFatalError(wxString::FromUTF8(e.what())); + procCallback.reportFatalError(utf8CvrtTo<std::wstring>(e.what())); } } @@ -1768,7 +2095,7 @@ public: } private: - UInt64& bytesReported_; + UInt64& bytesReported_; ProcessCallback& statusHandler_; DelTargetCommand cmd_; }; @@ -1776,13 +2103,13 @@ private: //copy file while refreshing UI template <SelectedSide side, class DelTargetCommand> -void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileDescriptor& sourceAttr) const +void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const DelTargetCommand& cmd, FileAttrib& newAttr) const { const UInt64 totalBytesToCpy = fileObj.getFileSize<OtherSide<side>::result>(); Zstring source = fileObj.getFullName<OtherSide<side>::result>(); const Zstring& target = fileObj.getBaseDirPf<side>() + fileObj.getRelativeName<OtherSide<side>::result>(); - auto copyOperation = [&]() + auto copyOperation = [&] { //start of (possibly) long-running copy process: ensure status updates are performed regularly UInt64 bytesReported; @@ -1790,16 +2117,13 @@ void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const zen::ScopeGuard guardStatistics = zen::makeGuard([&]() { procCallback_.updateProcessedData(0, -1 * to<Int64>(bytesReported)); }); WhileCopying<DelTargetCommand> callback(bytesReported, procCallback_, cmd); - FileAttrib fileAttr; zen::copyFile(source, //type File implicitly means symlinks need to be dereferenced! - target, - copyFilePermissions, - transactionalFileCopy, - &callback, - &fileAttr); //throw FileError, ErrorFileLocked - - sourceAttr = FileDescriptor(fileAttr.modificationTime, fileAttr.fileSize); + target, + copyFilePermissions, + transactionalFileCopy, + &callback, + &newAttr); //throw FileError, ErrorFileLocked //inform about the (remaining) processed amount of data procCallback_.updateProcessedData(0, to<Int64>(totalBytesToCpy) - to<Int64>(bytesReported)); @@ -1851,24 +2175,6 @@ void SynchronizeFolderPair::copyFileUpdatingTo(const FileMapping& fileObj, const } -template <zen::SelectedSide side> -void SynchronizeFolderPair::deleteSymlink(const SymLinkMapping& linkObj) const -{ - const DeletionHandling& delHandling = side == LEFT_SIDE ? delHandlingLeft_ : delHandlingRight_; - - switch (linkObj.getLinkType<side>()) - { - case LinkDescriptor::TYPE_DIR: - delHandling.removeFolder(linkObj.getObjRelativeName()); //throw FileError - break; - - case LinkDescriptor::TYPE_FILE: //Windows: true file symlink; Linux: file-link or broken link - delHandling.removeFile(linkObj.getObjRelativeName()); //throw FileError - break; - } -} - - //--------------------- data verification ------------------------- //callback functionality for status updates while verifying @@ -1936,8 +2242,7 @@ private: void SynchronizeFolderPair::verifyFileCopy(const Zstring& source, const Zstring& target) const { - wxString logText = replaceCpy(txtVerifying, L"%x", utf8CvrtTo<wxString>(target)); - procCallback_.reportInfo(logText); + procCallback_.reportInfo(replaceCpy(txtVerifying, L"%x", utf8CvrtTo<std::wstring>(target))); VerifyStatusUpdater callback(procCallback_); diff --git a/synchronization.h b/synchronization.h index 4e11d5a9..6cf32de5 100644 --- a/synchronization.h +++ b/synchronization.h @@ -21,19 +21,20 @@ class SyncStatistics public: SyncStatistics(const HierarchyObject& hierObj); SyncStatistics(const FolderComparison& folderCmp); + SyncStatistics(const FileMapping& fileObj); int getCreate() const; template <SelectedSide side> int getCreate() const; - int getOverwrite() const; - template <SelectedSide side> int getOverwrite() const; + int getUpdate() const; + template <SelectedSide side> int getUpdate() const; int getDelete() const; template <SelectedSide side> int getDelete() const; int getConflict() const { return conflict; } - typedef std::vector<std::pair<Zstring, wxString> > ConflictTexts; // Pair(filename/conflict text) + typedef std::vector<std::pair<Zstring, std::wstring> > ConflictTexts; // Pair(filename/conflict text) const ConflictTexts& getFirstConflicts() const { return firstConflicts; } zen::UInt64 getDataToProcess() const { return dataToProcess; } @@ -42,15 +43,15 @@ public: private: void init(); - void getNumbersRecursively(const HierarchyObject& hierObj); + void recurse(const HierarchyObject& hierObj); void getFileNumbers(const FileMapping& fileObj); void getLinkNumbers(const SymLinkMapping& linkObj); void getDirNumbers(const DirMapping& dirObj); - int createLeft, createRight; - int overwriteLeft, overwriteRight; - int deleteLeft, deleteRight; + int createLeft, createRight; + int updateLeft, updateRight; + int deleteLeft, deleteRight; int conflict; ConflictTexts firstConflicts; //save the first few conflict texts to display as a warning message zen::UInt64 dataToProcess; @@ -103,7 +104,7 @@ private: xmlAccess::OptionalDialogs& m_warnings; ProcessCallback& procCallback; -std::unique_ptr<ScheduleForBackgroundProcessing> procBackground; + std::unique_ptr<ScheduleForBackgroundProcessing> procBackground; }; @@ -131,16 +132,14 @@ std::unique_ptr<ScheduleForBackgroundProcessing> procBackground; -// inline implementation -template <> -inline +// ----------- implementation ---------------- +template <> inline int SyncStatistics::getCreate<LEFT_SIDE>() const { return createLeft; } -template <> -inline +template <> inline int SyncStatistics::getCreate<RIGHT_SIDE>() const { return createRight; @@ -152,36 +151,32 @@ int SyncStatistics::getCreate() const return getCreate<LEFT_SIDE>() + getCreate<RIGHT_SIDE>(); } -template <> -inline -int SyncStatistics::getOverwrite<LEFT_SIDE>() const +template <> inline +int SyncStatistics::getUpdate<LEFT_SIDE>() const { - return overwriteLeft; + return updateLeft; } -template <> -inline -int SyncStatistics::getOverwrite<RIGHT_SIDE>() const +template <> inline +int SyncStatistics::getUpdate<RIGHT_SIDE>() const { - return overwriteRight; + return updateRight; } inline -int SyncStatistics::getOverwrite() const +int SyncStatistics::getUpdate() const { - return getOverwrite<LEFT_SIDE>() + getOverwrite<RIGHT_SIDE>(); + return getUpdate<LEFT_SIDE>() + getUpdate<RIGHT_SIDE>(); } -template <> -inline +template <> inline int SyncStatistics::getDelete<LEFT_SIDE>() const { return deleteLeft; } -template <> -inline +template <> inline int SyncStatistics::getDelete<RIGHT_SIDE>() const { return deleteRight; diff --git a/ui/batch_status_handler.cpp b/ui/batch_status_handler.cpp index 93237c70..1a710eee 100644 --- a/ui/batch_status_handler.cpp +++ b/ui/batch_status_handler.cpp @@ -278,14 +278,14 @@ void BatchStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 da } -void BatchStatusHandler::reportStatus(const wxString& text) +void BatchStatusHandler::reportStatus(const std::wstring& text) { syncStatusFrame.setStatusText_NoUpdate(text); requestUiRefresh(); //throw AbortThisProcess } -void BatchStatusHandler::reportInfo(const wxString& text) +void BatchStatusHandler::reportInfo(const std::wstring& text) { errorLog.logMsg(text, TYPE_INFO); @@ -294,7 +294,7 @@ void BatchStatusHandler::reportInfo(const wxString& text) } -void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive) +void BatchStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) { errorLog.logMsg(warningMessage, TYPE_WARNING); @@ -339,7 +339,7 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war } -ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& errorMessage) { switch (handleError_) { @@ -384,7 +384,7 @@ ProcessCallback::Response BatchStatusHandler::reportError(const wxString& errorM } -void BatchStatusHandler::reportFatalError(const wxString& errorMessage) +void BatchStatusHandler::reportFatalError(const std::wstring& errorMessage) { if (handleError_ == xmlAccess::ON_ERROR_POPUP) exitWhenFinished = false; //log fatal error and show it on status dialog diff --git a/ui/batch_status_handler.h b/ui/batch_status_handler.h index 548447f6..998f2bc8 100644 --- a/ui/batch_status_handler.h +++ b/ui/batch_status_handler.h @@ -34,13 +34,13 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportStatus(const wxString& text); - virtual void reportInfo(const wxString& text); + virtual void reportStatus(const std::wstring& text); + virtual void reportInfo(const std::wstring& text); virtual void forceUiRefresh(); - virtual void reportWarning(const wxString& warningMessage, bool& warningActive); - virtual Response reportError(const wxString& errorMessage); - virtual void reportFatalError(const wxString& errorMessage); + virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); + virtual Response reportError(const std::wstring& errorMessage); + virtual void reportFatalError(const std::wstring& errorMessage); private: virtual void abortThisProcess(); diff --git a/ui/grid_view.cpp b/ui/grid_view.cpp index bd2bf4f4..0120764f 100644 --- a/ui/grid_view.cpp +++ b/ui/grid_view.cpp @@ -181,18 +181,22 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: + case SO_MOVE_LEFT_TARGET: output.existsSyncCreateLeft = true; if (!syncCreateLeftActive) continue; break; case SO_CREATE_NEW_RIGHT: + case SO_MOVE_RIGHT_TARGET: output.existsSyncCreateRight = true; if (!syncCreateRightActive) continue; break; case SO_DELETE_LEFT: + case SO_MOVE_LEFT_SOURCE: output.existsSyncDeleteLeft = true; if (!syncDeleteLeftActive) continue; break; case SO_DELETE_RIGHT: + case SO_MOVE_RIGHT_SOURCE: output.existsSyncDeleteRight = true; if (!syncDeleteRightActive) continue; break; diff --git a/ui/gui_generated.cpp b/ui/gui_generated.cpp index 3704d666..2b3761c5 100644 --- a/ui/gui_generated.cpp +++ b/ui/gui_generated.cpp @@ -942,6 +942,167 @@ FolderPairGenerated::~FolderPairGenerated() { } +CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) +{ + wxBoxSizer* bSizer40; + bSizer40 = new wxBoxSizer( wxVERTICAL ); + + + bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer48; + bSizer48 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText30->Wrap( -1 ); + m_staticText30->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) ); + + bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); + m_textCtrlStatus->SetBackgroundColour( wxColour( 208, 208, 208 ) ); + + bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer40->Add( bSizer48, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); + bSizer40->Add( m_gauge2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + bSizer42 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer157; + bSizer157 = new wxBoxSizer( wxVERTICAL ); + + bSizerFilesFound = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText321 = new wxStaticText( this, wxID_ANY, _("Items found:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText321->Wrap( -1 ); + m_staticText321->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); + + bSizerFilesFound->Add( m_staticText321, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextScanned->Wrap( -1 ); + m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizerFilesFound->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); + + bSizer157->Add( bSizerFilesFound, 0, 0, 5 ); + + bSizerFilesRemaining = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText46 = new wxStaticText( this, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText46->Wrap( -1 ); + m_staticText46->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); + + bSizerFilesRemaining->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 ); + + wxBoxSizer* bSizer154; + bSizer154 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFilesRemaining->Wrap( -1 ); + m_staticTextFilesRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 ); + + m_staticText117 = new wxStaticText( this, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText117->Wrap( -1 ); + m_staticText117->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); + + bSizer154->Add( m_staticText117, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDataRemaining->Wrap( -1 ); + m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); + + bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 ); + + m_staticText118 = new wxStaticText( this, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText118->Wrap( -1 ); + m_staticText118->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); + + bSizer154->Add( m_staticText118, 0, wxALIGN_BOTTOM, 5 ); + + bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); + + bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 ); + + bSizer42->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + sSizerSpeed = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText104->Wrap( -1 ); + m_staticText104->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); + + sSizerSpeed->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSpeed->Wrap( -1 ); + m_staticTextSpeed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer42->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL ); + + m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeRemFixed->Wrap( -1 ); + m_staticTextTimeRemFixed->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); + + sSizerTimeRemaining->Add( m_staticTextTimeRemFixed, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextRemTime = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextRemTime->Wrap( -1 ); + m_staticTextRemTime->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer42->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticText* m_staticText37; + m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText37->Wrap( -1 ); + m_staticText37->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); + + sSizerTimeElapsed->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer42->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + + bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); + + this->SetSizer( bSizer40 ); + this->Layout(); + bSizer40->Fit( this ); +} + +CompareStatusGenerated::~CompareStatusGenerated() +{ +} + BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { this->SetSizeHints( wxSize( 560,320 ), wxDefaultSize ); @@ -1464,167 +1625,6 @@ BatchFolderPairGenerated::~BatchFolderPairGenerated() { } -CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ - wxBoxSizer* bSizer40; - bSizer40 = new wxBoxSizer( wxVERTICAL ); - - - bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer48; - bSizer48 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText30->Wrap( -1 ); - m_staticText30->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) ); - - bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); - m_textCtrlStatus->SetBackgroundColour( wxColour( 208, 208, 208 ) ); - - bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer40->Add( bSizer48, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); - bSizer40->Add( m_gauge2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer157; - bSizer157 = new wxBoxSizer( wxVERTICAL ); - - bSizerFilesFound = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText321 = new wxStaticText( this, wxID_ANY, _("Items found:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText321->Wrap( -1 ); - m_staticText321->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); - - bSizerFilesFound->Add( m_staticText321, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextScanned->Wrap( -1 ); - m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizerFilesFound->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - bSizer157->Add( bSizerFilesFound, 0, 0, 5 ); - - bSizerFilesRemaining = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText46 = new wxStaticText( this, wxID_ANY, _("Items remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText46->Wrap( -1 ); - m_staticText46->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); - - bSizerFilesRemaining->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 ); - - wxBoxSizer* bSizer154; - bSizer154 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFilesRemaining->Wrap( -1 ); - m_staticTextFilesRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer154->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 ); - - m_staticText117 = new wxStaticText( this, wxID_ANY, _("("), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText117->Wrap( -1 ); - m_staticText117->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); - - bSizer154->Add( m_staticText117, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataRemaining->Wrap( -1 ); - m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); - - bSizer154->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 ); - - m_staticText118 = new wxStaticText( this, wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText118->Wrap( -1 ); - m_staticText118->SetFont( wxFont( 9, 74, 90, 90, false, wxT("Arial") ) ); - - bSizer154->Add( m_staticText118, 0, wxALIGN_BOTTOM, 5 ); - - bSizerFilesRemaining->Add( bSizer154, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - bSizer157->Add( bSizerFilesRemaining, 0, 0, 5 ); - - bSizer42->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - sSizerSpeed = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText104->Wrap( -1 ); - m_staticText104->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); - - sSizerSpeed->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSpeed->Wrap( -1 ); - m_staticTextSpeed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - sSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer42->Add( sSizerSpeed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - sSizerTimeRemaining = new wxBoxSizer( wxHORIZONTAL ); - - m_staticTextTimeRemFixed = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemFixed->Wrap( -1 ); - m_staticTextTimeRemFixed->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); - - sSizerTimeRemaining->Add( m_staticTextTimeRemFixed, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextRemTime = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextRemTime->Wrap( -1 ); - m_staticTextRemTime->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - sSizerTimeRemaining->Add( m_staticTextRemTime, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer42->Add( sSizerTimeRemaining, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - sSizerTimeElapsed = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticText* m_staticText37; - m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText37->Wrap( -1 ); - m_staticText37->SetFont( wxFont( 10, 70, 90, 90, false, wxEmptyString ) ); - - sSizerTimeElapsed->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - sSizerTimeElapsed->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer42->Add( sSizerTimeElapsed, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); - - - bSizer40->Add( 0, 0, 1, wxEXPAND, 5 ); - - this->SetSizer( bSizer40 ); - this->Layout(); - bSizer40->Fit( this ); -} - -CompareStatusGenerated::~CompareStatusGenerated() -{ -} - SyncCfgDlgGenerated::SyncCfgDlgGenerated( 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 ); @@ -1663,7 +1663,7 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const fgSizer1->Add( m_buttonAutomatic, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_staticText81 = new wxStaticText( this, wxID_ANY, _("Identify and propagate changes on both sides using a database. Deletions and conflicts are detected automatically."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText81 = new wxStaticText( this, wxID_ANY, _("Identify and propagate changes on both sides using a database. Deletions, renaming and conflicts are detected automatically."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText81->Wrap( 400 ); fgSizer1->Add( m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); @@ -2282,12 +2282,12 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id, bSizerFinalStat = new wxBoxSizer( wxVERTICAL ); m_listbookResult = new wxListbook( m_panelBackground, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLB_TOP ); -#ifndef __WXGTK__ // Small icon style not supported in GTK - wxListView* m_listbookResultListView = m_listbookResult->GetListView(); - long m_listbookResultFlags = m_listbookResultListView->GetWindowStyleFlag(); - m_listbookResultFlags = ( m_listbookResultFlags & ~wxLC_ICON ) | wxLC_SMALL_ICON; - m_listbookResultListView->SetWindowStyleFlag( m_listbookResultFlags ); -#endif + wxSize m_listbookResultImageSize = wxSize( 180,1 ); + int m_listbookResultIndex = 0; + wxImageList* m_listbookResultImages = new wxImageList( m_listbookResultImageSize.GetWidth(), m_listbookResultImageSize.GetHeight() ); + m_listbookResult->AssignImageList( m_listbookResultImages ); + wxBitmap m_listbookResultBitmap; + wxImage m_listbookResultImage; bSizerFinalStat->Add( m_listbookResult, 1, wxEXPAND, 5 ); @@ -2351,14 +2351,6 @@ SyncStatusDlgGenerated::~SyncStatusDlgGenerated() } -MyPanel5::MyPanel5( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) -{ -} - -MyPanel5::~MyPanel5() -{ -} - LogControlGenerated::LogControlGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) { wxBoxSizer* bSizer153; @@ -3420,30 +3412,29 @@ GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWind m_checkBoxTransCopy = new wxCheckBox( this, wxID_ANY, _("Transactional file copy"), wxDefaultPosition, wxDefaultSize, 0 ); sbSizer23->Add( m_checkBoxTransCopy, 0, wxEXPAND|wxALL, 5 ); - m_textCtrl22 = new wxTextCtrl( this, wxID_ANY, _("Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER ); - m_textCtrl22->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - m_textCtrl22->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); - m_textCtrl22->SetMinSize( wxSize( 400,-1 ) ); + m_staticText82 = new wxStaticText( this, wxID_ANY, _("Write to a temporary file (*.ffs_tmp) first then rename it. This guarantees a consistent state even in case of fatal error."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText82->Wrap( 400 ); + m_staticText82->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - sbSizer23->Add( m_textCtrl22, 0, wxLEFT|wxEXPAND, 20 ); + sbSizer23->Add( m_staticText82, 0, wxLEFT, 20 ); m_checkBoxCopyLocked = new wxCheckBox( this, wxID_ANY, _("Copy locked files"), wxDefaultPosition, wxDefaultSize, 0 ); sbSizer23->Add( m_checkBoxCopyLocked, 0, wxALL|wxEXPAND, 5 ); - m_textCtrlCopyLocked = new wxTextCtrl( this, wxID_ANY, _("Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER ); - m_textCtrlCopyLocked->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - m_textCtrlCopyLocked->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_staticTextCopyLocked = new wxStaticText( this, wxID_ANY, _("Copy shared or locked files using Volume Shadow Copy Service (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCopyLocked->Wrap( 400 ); + m_staticTextCopyLocked->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - sbSizer23->Add( m_textCtrlCopyLocked, 0, wxLEFT|wxEXPAND, 20 ); + sbSizer23->Add( m_staticTextCopyLocked, 0, wxLEFT|wxEXPAND, 20 ); m_checkBoxCopyPermissions = new wxCheckBox( this, wxID_ANY, _("Copy file access permissions"), wxDefaultPosition, wxDefaultSize, 0 ); sbSizer23->Add( m_checkBoxCopyPermissions, 0, wxALL|wxEXPAND, 5 ); - m_textCtrl2211 = new wxTextCtrl( this, wxID_ANY, _("Transfer file and directory permissions (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxTE_READONLY|wxNO_BORDER ); - m_textCtrl2211->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - m_textCtrl2211->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + m_staticText8211 = new wxStaticText( this, wxID_ANY, _("Transfer file and directory permissions (Requires Administrator rights)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText8211->Wrap( 400 ); + m_staticText8211->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - sbSizer23->Add( m_textCtrl2211, 0, wxLEFT|wxEXPAND, 20 ); + sbSizer23->Add( m_staticText8211, 0, wxLEFT|wxEXPAND, 20 ); bSizer95->Add( sbSizer23, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); diff --git a/ui/gui_generated.h b/ui/gui_generated.h index de1dc89b..8fc345a2 100644 --- a/ui/gui_generated.h +++ b/ui/gui_generated.h @@ -46,14 +46,15 @@ namespace zen { class Graph2D; } #include <wx/textctrl.h> #include <wx/statline.h> #include <wx/frame.h> +#include <wx/gauge.h> #include <wx/choice.h> #include <wx/spinctrl.h> #include <wx/listbook.h> #include <wx/listctrl.h> #include <wx/dialog.h> -#include <wx/gauge.h> #include <wx/radiobut.h> #include <wx/animate.h> +#include <wx/imaglist.h> #include <wx/hyperlink.h> #include <wx/checklst.h> #include <wx/calctrl.h> @@ -263,6 +264,43 @@ public: }; /////////////////////////////////////////////////////////////////////////////// +/// Class CompareStatusGenerated +/////////////////////////////////////////////////////////////////////////////// +class CompareStatusGenerated : public wxPanel +{ +private: + +protected: + wxStaticText* m_staticText30; + wxTextCtrl* m_textCtrlStatus; + wxGauge* m_gauge2; + wxBoxSizer* bSizer42; + wxBoxSizer* bSizerFilesFound; + wxStaticText* m_staticText321; + wxStaticText* m_staticTextScanned; + wxBoxSizer* bSizerFilesRemaining; + wxStaticText* m_staticText46; + wxStaticText* m_staticTextFilesRemaining; + wxStaticText* m_staticText117; + wxStaticText* m_staticTextDataRemaining; + wxStaticText* m_staticText118; + wxBoxSizer* sSizerSpeed; + wxStaticText* m_staticText104; + wxStaticText* m_staticTextSpeed; + wxBoxSizer* sSizerTimeRemaining; + wxStaticText* m_staticTextTimeRemFixed; + wxStaticText* m_staticTextRemTime; + wxBoxSizer* sSizerTimeElapsed; + wxStaticText* m_staticTextTimeElapsed; + +public: + + CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL ); + ~CompareStatusGenerated(); + +}; + +/////////////////////////////////////////////////////////////////////////////// /// Class BatchDlgGenerated /////////////////////////////////////////////////////////////////////////////// class BatchDlgGenerated : public wxDialog @@ -365,43 +403,6 @@ public: }; /////////////////////////////////////////////////////////////////////////////// -/// Class CompareStatusGenerated -/////////////////////////////////////////////////////////////////////////////// -class CompareStatusGenerated : public wxPanel -{ -private: - -protected: - wxStaticText* m_staticText30; - wxTextCtrl* m_textCtrlStatus; - wxGauge* m_gauge2; - wxBoxSizer* bSizer42; - wxBoxSizer* bSizerFilesFound; - wxStaticText* m_staticText321; - wxStaticText* m_staticTextScanned; - wxBoxSizer* bSizerFilesRemaining; - wxStaticText* m_staticText46; - wxStaticText* m_staticTextFilesRemaining; - wxStaticText* m_staticText117; - wxStaticText* m_staticTextDataRemaining; - wxStaticText* m_staticText118; - wxBoxSizer* sSizerSpeed; - wxStaticText* m_staticText104; - wxStaticText* m_staticTextSpeed; - wxBoxSizer* sSizerTimeRemaining; - wxStaticText* m_staticTextTimeRemFixed; - wxStaticText* m_staticTextRemTime; - wxBoxSizer* sSizerTimeElapsed; - wxStaticText* m_staticTextTimeElapsed; - -public: - - CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxRAISED_BORDER|wxTAB_TRAVERSAL ); - ~CompareStatusGenerated(); - -}; - -/////////////////////////////////////////////////////////////////////////////// /// Class SyncCfgDlgGenerated /////////////////////////////////////////////////////////////////////////////// class SyncCfgDlgGenerated : public wxDialog @@ -586,22 +587,6 @@ public: }; /////////////////////////////////////////////////////////////////////////////// -/// Class MyPanel5 -/////////////////////////////////////////////////////////////////////////////// -class MyPanel5 : public wxPanel -{ -private: - -protected: - -public: - - MyPanel5( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL ); - ~MyPanel5(); - -}; - -/////////////////////////////////////////////////////////////////////////////// /// Class LogControlGenerated /////////////////////////////////////////////////////////////////////////////// class LogControlGenerated : public wxPanel @@ -904,11 +889,11 @@ protected: wxPanel* m_panel8; wxStaticText* m_staticText56; wxCheckBox* m_checkBoxTransCopy; - wxTextCtrl* m_textCtrl22; + wxStaticText* m_staticText82; wxCheckBox* m_checkBoxCopyLocked; - wxTextCtrl* m_textCtrlCopyLocked; + wxStaticText* m_staticTextCopyLocked; wxCheckBox* m_checkBoxCopyPermissions; - wxTextCtrl* m_textCtrl2211; + wxStaticText* m_staticText8211; wxStaticText* m_staticText100; zen::BitmapButton* m_buttonResetDialogs; wxGrid* m_gridCustomCommand; diff --git a/ui/gui_status_handler.cpp b/ui/gui_status_handler.cpp index b353e918..6809b362 100644 --- a/ui/gui_status_handler.cpp +++ b/ui/gui_status_handler.cpp @@ -114,21 +114,21 @@ void CompareStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 } -void CompareStatusHandler::reportStatus(const wxString& text) +void CompareStatusHandler::reportStatus(const std::wstring& text) { mainDlg.compareStatus->setStatusText_NoUpdate(text); requestUiRefresh(); //throw AbortThisProcess } -void CompareStatusHandler::reportInfo(const wxString& text) +void CompareStatusHandler::reportInfo(const std::wstring& text) { mainDlg.compareStatus->setStatusText_NoUpdate(text); requestUiRefresh(); //throw AbortThisProcess } -ProcessCallback::Response CompareStatusHandler::reportError(const wxString& message) +ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& message) { if (ignoreErrors) return ProcessCallback::IGNORE_ERROR; @@ -155,7 +155,7 @@ ProcessCallback::Response CompareStatusHandler::reportError(const wxString& mess } -void CompareStatusHandler::reportFatalError(const wxString& errorMessage) +void CompareStatusHandler::reportFatalError(const std::wstring& errorMessage) { forceUiRefresh(); @@ -165,7 +165,7 @@ void CompareStatusHandler::reportFatalError(const wxString& errorMessage) } -void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive) +void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) { if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also return; @@ -266,14 +266,14 @@ void SyncStatusHandler::updateProcessedData(int objectsProcessed, zen::Int64 dat } -void SyncStatusHandler::reportStatus(const wxString& text) +void SyncStatusHandler::reportStatus(const std::wstring& text) { syncStatusFrame.setStatusText_NoUpdate(text); //throw () requestUiRefresh(); //throw AbortThisProccess } -void SyncStatusHandler::reportInfo(const wxString& text) +void SyncStatusHandler::reportInfo(const std::wstring& text) { errorLog.logMsg(text, TYPE_INFO); @@ -282,7 +282,7 @@ void SyncStatusHandler::reportInfo(const wxString& text) } -ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMessage) +ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& errorMessage) { switch (handleError_) { @@ -320,13 +320,13 @@ ProcessCallback::Response SyncStatusHandler::reportError(const wxString& errorMe } -void SyncStatusHandler::reportFatalError(const wxString& errorMessage) +void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage) { errorLog.logMsg(errorMessage, TYPE_FATAL_ERROR); } -void SyncStatusHandler::reportWarning(const wxString& warningMessage, bool& warningActive) +void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) { errorLog.logMsg(warningMessage, TYPE_WARNING); diff --git a/ui/gui_status_handler.h b/ui/gui_status_handler.h index 28429d68..997e511f 100644 --- a/ui/gui_status_handler.h +++ b/ui/gui_status_handler.h @@ -29,13 +29,13 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportStatus(const wxString& text); - virtual void reportInfo(const wxString& text); + virtual void reportStatus(const std::wstring& text); + virtual void reportInfo(const std::wstring& text); virtual void forceUiRefresh(); - virtual Response reportError(const wxString& text); - virtual void reportFatalError(const wxString& errorMessage); - virtual void reportWarning(const wxString& warningMessage, bool& warningActive); + virtual Response reportError(const std::wstring& text); + virtual void reportFatalError(const std::wstring& errorMessage); + virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); private: void OnKeyPressed(wxKeyEvent& event); @@ -56,13 +56,13 @@ public: virtual void initNewProcess(int objectsTotal, zen::Int64 dataTotal, Process processID); virtual void updateProcessedData(int objectsProcessed, zen::Int64 dataProcessed); - virtual void reportStatus(const wxString& text); - virtual void reportInfo(const wxString& text); + virtual void reportStatus(const std::wstring& text); + virtual void reportInfo(const std::wstring& text); virtual void forceUiRefresh(); - virtual Response reportError(const wxString& text); - virtual void reportFatalError(const wxString& errorMessage); - virtual void reportWarning(const wxString& warningMessage, bool& warningActive); + virtual Response reportError(const std::wstring& text); + virtual void reportFatalError(const std::wstring& errorMessage); + virtual void reportWarning(const std::wstring& warningMessage, bool& warningActive); private: virtual void abortThisProcess(); diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp index e1227509..97c3625c 100644 --- a/ui/main_dlg.cpp +++ b/ui/main_dlg.cpp @@ -662,8 +662,8 @@ void MainDialog::init(const xmlAccess::XmlGuiConfig guiCfg, if (dirFmtLeft.empty() && dirFmtRight.empty()) //only skip check if both sides are empty! return; - dirEx.push_back(zen::async2<bool>([=]() { return !dirFmtLeft .empty() && zen::dirExists(dirFmtLeft); })); - dirEx.push_back(zen::async2<bool>([=]() { return !dirFmtRight.empty() && zen::dirExists(dirFmtRight); })); + dirEx.push_back(zen::async2<bool>([=] { return !dirFmtLeft .empty() && zen::dirExists(dirFmtLeft); })); + dirEx.push_back(zen::async2<bool>([=] { return !dirFmtRight.empty() && zen::dirExists(dirFmtRight); })); }; addDirCheck(currMainCfg.firstPair); std::for_each(currMainCfg.additionalPairs.begin(), currMainCfg.additionalPairs.end(), addDirCheck); @@ -972,7 +972,7 @@ public: mainDlg->enableAllElements(); } - virtual Response reportError(const wxString& errorMessage) + virtual Response reportError(const std::wstring& errorMessage) { if (abortRequested) throw AbortDeleteProcess(); @@ -1122,17 +1122,6 @@ wxString extractLastValidDir(const FileSystemObject& fsObj) return toWx(fullname); } -bool tryReplace(const wxString& phrase, const wxString& replacement, wxString& command) //return false on error -{ - if (command.find(phrase) != wxString::npos) - { - if (replacement.empty()) - return false; - replace(command, phrase, replacement); - } - return true; -} - void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const wxString& commandline) { @@ -1163,10 +1152,22 @@ void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const } wxString command = commandline; - if (tryReplace(L"%nameCo", nameCo, command) && //attention: replace %nameCo, %dirCo BEFORE %name, %dir to handle dependency - tryReplace(L"%dirCo", dirCo, command) && - tryReplace(L"%name", name, command) && - tryReplace(L"%dir", dir, command)) + + auto tryReplace = [&](const wxString& phrase, const wxString& replacement) -> bool + { + if (command.find(phrase) != wxString::npos) + { + if (replacement.empty()) + return false; + replace(command, phrase, replacement); + } + return true; + }; + + if (tryReplace(L"%nameCo", nameCo) && //attention: replace %nameCo, %dirCo BEFORE %name, %dir to handle dependency + tryReplace(L"%dirCo", dirCo ) && + tryReplace(L"%name", name ) && + tryReplace(L"%dir", dir )) zen::shellExecute(command); else //fallback { @@ -1246,9 +1247,6 @@ void MainDialog::disableAllElements(bool enableAbort) if (m_buttonAbort->IsShownOnScreen()) m_buttonAbort->SetFocus(); m_buttonCompare->Disable(); m_buttonCompare->Hide(); - m_bpButtonCmpConfig ->Disable(); - m_bpButtonSyncConfig->Disable(); - m_buttonStartSync ->Disable(); m_panelTopButtons->Layout(); } else @@ -1261,7 +1259,7 @@ void MainDialog::enableAllElements() EnableCloseButton(true); m_panelViewFilter ->Enable(); - m_bpButtonCmpConfig ->Enable(); + m_bpButtonCmpConfig ->Enable(); //wxGTK bug: this line seems to move main dialog to top!!!!!!! m_panelFilter ->Enable(); m_panelConfig ->Enable(); m_bpButtonSyncConfig ->Enable(); @@ -1277,9 +1275,6 @@ void MainDialog::enableAllElements() m_buttonAbort->Hide(); m_buttonCompare->Enable(); m_buttonCompare->Show(); - m_bpButtonCmpConfig ->Enable(); - m_bpButtonSyncConfig->Enable(); - m_buttonStartSync ->Enable(); m_panelTopButtons->Layout(); m_panelTopButtons->Enable(); @@ -3428,7 +3423,7 @@ void MainDialog::updateStatistics() //update preview of bytes to be transferred: const SyncStatistics st(gridDataView->getDataTentative()); const wxString toCreate = zen::toStringSep(st.getCreate()); - const wxString toUpdate = zen::toStringSep(st.getOverwrite()); + const wxString toUpdate = zen::toStringSep(st.getUpdate()); const wxString toDelete = zen::toStringSep(st.getDelete()); const wxString data = zen::filesizeToShortString(st.getDataToProcess()); @@ -3977,7 +3972,7 @@ void MainDialog::applySyncConfig() warningSyncDatabase_(warningSyncDatabase), parent_(parent) {} - virtual void reportWarning(const wxString& text) + virtual void reportWarning(const std::wstring& text) { if (warningSyncDatabase_) { @@ -4268,25 +4263,25 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) exportString += copyStringTo<zxString>(_("Legend")) + wxT('\n'); if (syncPreview->previewIsEnabled()) { - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_CREATE_NEW_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_LEFT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_CREATE_NEW_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_RIGHT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DELETE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_LEFT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DELETE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_RIGHT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_OVERWRITE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_LEFT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_OVERWRITE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_RIGHT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_DO_NOTHING)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DO_NOTHING)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_EQUAL)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(SO_UNRESOLVED_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_EQUAL)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_LEFT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_CREATE_NEW_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_CREATE_NEW_RIGHT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_LEFT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_OVERWRITE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_OVERWRITE_RIGHT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_LEFT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_LEFT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DELETE_RIGHT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DELETE_RIGHT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_DO_NOTHING)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_DO_NOTHING)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getSyncOpDescription(SO_UNRESOLVED_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(SO_UNRESOLVED_CONFLICT)) + wxT('\n'); } else { - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_LEFT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_RIGHT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_LEFT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_NEWER)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_RIGHT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_NEWER)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_DIFFERENT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_DIFFERENT)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_EQUAL)) + wxT('\n'); - exportString += wxT("\"") + copyStringTo<zxString>(getDescription(FILE_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_CONFLICT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_EQUAL)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_EQUAL)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_DIFFERENT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_DIFFERENT)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_SIDE_ONLY)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_SIDE_ONLY)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_SIDE_ONLY)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_LEFT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_LEFT_NEWER)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_RIGHT_NEWER)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_RIGHT_NEWER)) + wxT('\n'); + exportString += wxT("\"") + copyStringTo<zxString>(getCategoryDescription(FILE_CONFLICT)) + wxT("\";") + copyStringTo<zxString>(getSymbol(FILE_CONFLICT)) + wxT('\n'); } exportString += wxT('\n'); diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp index 25b9d6e8..092cb182 100644 --- a/ui/progress_indicator.cpp +++ b/ui/progress_indicator.cpp @@ -6,24 +6,23 @@ #include "progress_indicator.h" #include <memory> -#include "gui_generated.h" +#include <zen/basic_math.h> +#include <wx/imaglist.h> #include <wx/stopwatch.h> -#include "../lib/resources.h" -#include <wx+/string_conv.h> -#include <wx+/format_unit.h> -#include "../lib/statistics.h" #include <wx/wupdlock.h> -#include <zen/basic_math.h> -#include "tray_icon.h" -#include <memory> #include <wx+/mouse_move_dlg.h> -#include "../lib/error_log.h" #include <wx+/toggle_button.h> -#include "taskbar.h" +#include <wx+/string_conv.h> +#include <wx+/format_unit.h> #include <wx+/image_tools.h> #include <wx+/graph.h> #include <wx+/no_flicker.h> -#include <zen/basic_math.h> +#include "gui_generated.h" +#include "../lib/resources.h" +#include "../lib/error_log.h" +#include "../lib/statistics.h" +#include "tray_icon.h" +#include "taskbar.h" using namespace zen; @@ -289,7 +288,7 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() showProgressExternally(toStringSep(scannedObjects) + wxT(" - ") + _("Scanning...")); break; case COMPARING_CONTENT: - showProgressExternally(percentageToShortString(fraction) + wxT(" - ") + _("Comparing content..."), fraction); + showProgressExternally(fractionToShortString(fraction) + wxT(" - ") + _("Comparing content..."), fraction); break; } @@ -393,13 +392,15 @@ public: m_bpButtonErrors ->setActive(true); m_bpButtonWarnings->setActive(true); - m_bpButtonInfo ->setActive(false); + m_bpButtonInfo ->setActive(errorCount + warningCount == 0); m_bpButtonErrors ->Show(errorCount != 0); m_bpButtonWarnings->Show(warningCount != 0); m_bpButtonInfo ->Show(infoCount != 0); updateLogText(); + + m_textCtrlInfo->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(LogControl::onKeyEvent), NULL, this); } virtual void OnErrors(wxCommandEvent& event) @@ -421,6 +422,20 @@ public: } private: + void onKeyEvent(wxKeyEvent& event) + { + const int keyCode = event.GetKeyCode(); + + if (event.ControlDown()) + switch (keyCode) + { + case 'A': //CTRL + A + m_textCtrlInfo->SetSelection(-1, -1); //select all + return; + } + event.Skip(); + } + void updateLogText() { int includedTypes = 0; @@ -509,9 +524,12 @@ struct LabelFormatterBytes : public LabelFormatter { virtual double getOptimalBlockSize(double bytesProposed) const { + bytesProposed *= 2; //make blocks twice the default size + + if (bytesProposed <= 1024 * 1024) //set 1 MB min size: reduce initial rapid changes in y-label + return 1024 * 1024; + //round to next number which is a convenient to read block size - if (bytesProposed <= 0) - return 0; const double k = std::floor(std::log(bytesProposed) / std::log(2.0)); const double e = std::pow(2.0, k); @@ -530,8 +548,11 @@ struct LabelFormatterTimeElapsed : public LabelFormatter { virtual double getOptimalBlockSize(double secProposed) const { - if (secProposed <= 5) - return 5; //minimum block size + if (secProposed <= 10) + return 10; //minimum block size + + if (secProposed <= 20) //avoid flicker between 10<->15<->20 sec blocks + return bestFit(secProposed, 10, 20); //for seconds and minutes: nice numbers are 1, 5, 10, 15, 20, 30 auto calcBlock = [](double val) -> double @@ -803,10 +824,7 @@ SyncStatus::SyncStatusImpl::~SyncStatusImpl() if (mainDialog) { mainDialog->enableAllElements(); - - //restore title text - mainDialog->SetTitle(titelTextBackup); - + mainDialog->SetTitle(titelTextBackup); //restore title text mainDialog->Raise(); mainDialog->SetFocus(); } @@ -977,13 +995,13 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) showProgressExternally(wxString() + toStringSep(scannedObjects) + wxT(" - ") + _("Scanning...") + postFix); break; case SyncStatus::COMPARING_CONTENT: - showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Comparing content...") + postFix, fraction); + showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Comparing content...") + postFix, fraction); break; case SyncStatus::SYNCHRONIZING: - showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Synchronizing...") + postFix, fraction); + showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Synchronizing...") + postFix, fraction); break; case SyncStatus::PAUSE: - showProgressExternally(wxString() + percentageToShortString(fraction) + wxT(" - ") + _("Paused") + postFix, fraction); + showProgressExternally(wxString() + fractionToShortString(fraction) + wxT(" - ") + _("Paused") + postFix, fraction); break; case SyncStatus::ABORTED: showProgressExternally(_("Aborted") + postFix, fraction); @@ -1219,10 +1237,17 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, m_staticTextSpeed->SetLabel(timeElapMs <= 0 ? L"-" : zen::filesizeToShortString(zen::to<UInt64>(currentData * 1000 / timeElapMs)) + _("/sec")); //fill result listbox: + + //workaround wxListBox bug on Windows XP: labels are drawn on top of each other + assert(m_listbookResult->GetImageList()); //make sure listbook keeps *any* image list + //due to some crazy reasons that aren't worth debugging, this needs to be done directly in wxFormBuilder, + //the following call is *not* sufficient: m_listbookResult->AssignImageList(new wxImageList(0, 0)); + //note: alternative solutions involving wxLC_LIST, wxLC_REPORT and SetWindowStyleFlag() do not work portably! wxListBook using wxLC_ICON is obviously a class invariant! + //1. re-arrange graph into results listbook bSizerTop->Detach(m_panelProgress); m_panelProgress->Reparent(m_listbookResult); - m_listbookResult->AddPage(m_panelProgress, _("Statistics"), true); + m_listbookResult->AddPage(m_panelProgress, _("Statistics"), true); //AddPage() takes ownership! //2. log file LogControl* logControl = new LogControl(m_listbookResult, log); diff --git a/ui/small_dlgs.cpp b/ui/small_dlgs.cpp index 779bc427..cf323279 100644 --- a/ui/small_dlgs.cpp +++ b/ui/small_dlgs.cpp @@ -607,13 +607,13 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parent, m_staticTextVariant->SetLabel(variantName); m_textCtrlData->SetValue(zen::filesizeToShortString(statistics.getDataToProcess())); - m_textCtrlCreateL->SetValue(toStringSep(statistics.getCreate <LEFT_SIDE>())); - m_textCtrlUpdateL->SetValue(toStringSep(statistics.getOverwrite<LEFT_SIDE>())); - m_textCtrlDeleteL->SetValue(toStringSep(statistics.getDelete <LEFT_SIDE>())); + m_textCtrlCreateL->SetValue(toStringSep(statistics.getCreate<LEFT_SIDE>())); + m_textCtrlUpdateL->SetValue(toStringSep(statistics.getUpdate<LEFT_SIDE>())); + m_textCtrlDeleteL->SetValue(toStringSep(statistics.getDelete<LEFT_SIDE>())); - m_textCtrlCreateR->SetValue(toStringSep(statistics.getCreate <RIGHT_SIDE>())); - m_textCtrlUpdateR->SetValue(toStringSep(statistics.getOverwrite<RIGHT_SIDE>())); - m_textCtrlDeleteR->SetValue(toStringSep(statistics.getDelete <RIGHT_SIDE>())); + m_textCtrlCreateR->SetValue(toStringSep(statistics.getCreate<RIGHT_SIDE>())); + m_textCtrlUpdateR->SetValue(toStringSep(statistics.getUpdate<RIGHT_SIDE>())); + m_textCtrlDeleteR->SetValue(toStringSep(statistics.getDelete<RIGHT_SIDE>())); m_checkBoxDontShowAgain->SetValue(dontShowAgain); @@ -694,7 +694,7 @@ CompareCfgDialog::CompareCfgDialog(wxWindow* parent, #endif enumDescrHandleSyml. - add(SYMLINK_IGNORE, _("Ignore")). + add(SYMLINK_IGNORE, _("Exclude")). add(SYMLINK_USE_DIRECTLY, _("Direct")). add(SYMLINK_FOLLOW_LINK, _("Follow")); @@ -818,7 +818,7 @@ GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* parent, xmlAccess::XmlGlobalSetti m_checkBoxCopyPermissions->SetLabel(_("Copy NTFS permissions")); #else m_checkBoxCopyLocked->Hide(); - m_textCtrlCopyLocked->Hide(); + m_staticTextCopyLocked->Hide(); #endif set(globalSettings.gui.externelApplications); diff --git a/ui/sync_cfg.cpp b/ui/sync_cfg.cpp index d19520be..26ea5b2e 100644 --- a/ui/sync_cfg.cpp +++ b/ui/sync_cfg.cpp @@ -5,6 +5,7 @@ // ************************************************************************** #include "sync_cfg.h" +#include <memory> #include "../lib/resources.h" #include "../lib/dir_name.h" #include <wx/wupdlock.h> @@ -12,10 +13,10 @@ #include <wx+/string_conv.h> #include <wx+/dir_picker.h> #include "gui_generated.h" -#include <memory> #include <wx+/choice_enum.h> #include "../lib/dir_name.h" #include <wx+/image_tools.h> +#include "../file_hierarchy.h" using namespace zen; using namespace xmlAccess; @@ -97,15 +98,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("createRight"))); - buttonLeftOnly->SetToolTip(getDescription(SO_CREATE_NEW_RIGHT)); + buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_RIGHT)); break; case SYNC_DIR_LEFT: buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("deleteLeft"))); - buttonLeftOnly->SetToolTip(getDescription(SO_DELETE_LEFT)); + buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DELETE_LEFT)); break; case SYNC_DIR_NONE: buttonLeftOnly->SetBitmapLabel(GlobalResources::getImage(wxT("none"))); - buttonLeftOnly->SetToolTip(getDescription(SO_DO_NOTHING)); + buttonLeftOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); break; } @@ -113,15 +114,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("deleteRight"))); - buttonRightOnly->SetToolTip(getDescription(SO_DELETE_RIGHT)); + buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DELETE_RIGHT)); break; case SYNC_DIR_LEFT: buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("createLeft"))); - buttonRightOnly->SetToolTip(getDescription(SO_CREATE_NEW_LEFT)); + buttonRightOnly->SetToolTip(getSyncOpDescription(SO_CREATE_NEW_LEFT)); break; case SYNC_DIR_NONE: buttonRightOnly->SetBitmapLabel(GlobalResources::getImage(wxT("none"))); - buttonRightOnly->SetToolTip(getDescription(SO_DO_NOTHING)); + buttonRightOnly->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); break; } @@ -129,15 +130,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight"))); - buttonLeftNewer->SetToolTip(getDescription(SO_OVERWRITE_RIGHT)); + buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); break; case SYNC_DIR_LEFT: buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft"))); - buttonLeftNewer->SetToolTip(getDescription(SO_OVERWRITE_LEFT)); + buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); break; case SYNC_DIR_NONE: buttonLeftNewer->SetBitmapLabel(GlobalResources::getImage(wxT("none"))); - buttonLeftNewer->SetToolTip(getDescription(SO_DO_NOTHING)); + buttonLeftNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); break; } @@ -145,15 +146,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight"))); - buttonRightNewer->SetToolTip(getDescription(SO_OVERWRITE_RIGHT)); + buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); break; case SYNC_DIR_LEFT: buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft"))); - buttonRightNewer->SetToolTip(getDescription(SO_OVERWRITE_LEFT)); + buttonRightNewer->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); break; case SYNC_DIR_NONE: buttonRightNewer->SetBitmapLabel(GlobalResources::getImage(wxT("none"))); - buttonRightNewer->SetToolTip(getDescription(SO_DO_NOTHING)); + buttonRightNewer->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); break; } @@ -161,15 +162,15 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight"))); - buttonDifferent->SetToolTip(getDescription(SO_OVERWRITE_RIGHT)); + buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); break; case SYNC_DIR_LEFT: buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft"))); - buttonDifferent->SetToolTip(getDescription(SO_OVERWRITE_LEFT)); + buttonDifferent->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); break; case SYNC_DIR_NONE: buttonDifferent->SetBitmapLabel(GlobalResources::getImage(wxT("none"))); - buttonDifferent->SetToolTip(getDescription(SO_DO_NOTHING)); + buttonDifferent->SetToolTip(getSyncOpDescription(SO_DO_NOTHING)); break; } @@ -177,11 +178,11 @@ void updateConfigIcons(const DirectionConfig& directionCfg, { case SYNC_DIR_RIGHT: buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("updateRight"))); - buttonConflict->SetToolTip(getDescription(SO_OVERWRITE_RIGHT)); + buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_RIGHT)); break; case SYNC_DIR_LEFT: buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("updateLeft"))); - buttonConflict->SetToolTip(getDescription(SO_OVERWRITE_LEFT)); + buttonConflict->SetToolTip(getSyncOpDescription(SO_OVERWRITE_LEFT)); break; case SYNC_DIR_NONE: buttonConflict->SetBitmapLabel(GlobalResources::getImage(wxT("conflict"))); @@ -219,7 +220,7 @@ SyncCfgDialog::SyncCfgDialog(wxWindow* window, //a proper set-method may be in order some time... setEnumVal(enumDelhandDescr, *m_choiceHandleDeletion, syncCfg.handleDeletion); - customDelFolder.setName(syncCfg.customDeletionDirectory); + customDelFolder.setName(toWx(syncCfg.customDeletionDirectory)); updateGui(); //error handling @@ -330,7 +331,7 @@ void SyncCfgDialog::OnApply(wxCommandEvent& event) //write configuration to main dialog syncCfgOut.directionCfg = currentDirectionCfg; syncCfgOut.handleDeletion = getEnumVal(enumDelhandDescr, *m_choiceHandleDeletion); - syncCfgOut.customDeletionDirectory = customDelFolder.getName(); + syncCfgOut.customDeletionDirectory = toZ(customDelFolder.getName()); if (refHandleError) *refHandleError = getEnumVal(enumErrhandDescr, *m_choiceHandleError); diff --git a/ui/wx_form_build_hide_warnings.h b/ui/wx_form_build_hide_warnings.h index 277fa0e7..5988aa12 100644 --- a/ui/wx_form_build_hide_warnings.h +++ b/ui/wx_form_build_hide_warnings.h @@ -7,10 +7,14 @@ #ifndef WX_FORM_BUILD_230948324234234 #define WX_FORM_BUILD_230948324234234 -//hide compiler warnings in generated code +//pamper over wxFormBuilder "sub-optimal" code #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#pragma GCC diagnostic ignored "-Wunused-variable" + +#elif defined _MSC_VER +#pragma warning(disable: 4189) #endif #endif //WX_FORM_BUILD_230948324234234 diff --git a/version/version.h b/version/version.h index e1117ea0..f029c89d 100644 --- a/version/version.h +++ b/version/version.h @@ -3,7 +3,7 @@ namespace zen { -const wchar_t currentVersion[] = L"4.2"; //internal linkage! +const wchar_t currentVersion[] = L"4.3"; //internal linkage! } #endif diff --git a/version/version.rc b/version/version.rc index b902445b..60e22b93 100644 --- a/version/version.rc +++ b/version/version.rc @@ -1,2 +1,2 @@ -#define VER_FREEFILESYNC 4,2,0,0 -#define VER_FREEFILESYNC_STR "4.2\0" +#define VER_FREEFILESYNC 4,3,0,0 +#define VER_FREEFILESYNC_STR "4.3\0" diff --git a/wx+/format_unit.cpp b/wx+/format_unit.cpp index 994a2b29..361dbc62 100644 --- a/wx+/format_unit.cpp +++ b/wx+/format_unit.cpp @@ -135,7 +135,7 @@ std::wstring zen::remainingTimeToShortString(double timeInSec) } -std::wstring zen::percentageToShortString(double fraction) +std::wstring zen::fractionToShortString(double fraction) { return replaceCpy(_("%x%"), L"%x", printNumber<std::wstring>(L"%3.2f", fraction * 100.0), false); } diff --git a/wx+/format_unit.h b/wx+/format_unit.h index 4adf74f8..953910b6 100644 --- a/wx+/format_unit.h +++ b/wx+/format_unit.h @@ -15,7 +15,7 @@ namespace zen { std::wstring filesizeToShortString(UInt64 filesize); std::wstring remainingTimeToShortString(double timeInSec); -std::wstring percentageToShortString(double fraction); //within [0, 1] +std::wstring fractionToShortString(double fraction); //within [0, 1] template <class NumberType> std::wstring toStringSep(NumberType number); //convert number to std::wstring including thousands separator diff --git a/wx+/serialize.h b/wx+/serialize.h index cec70278..020b8709 100644 --- a/wx+/serialize.h +++ b/wx+/serialize.h @@ -7,11 +7,8 @@ #ifndef SERIALIZE_H_INCLUDED #define SERIALIZE_H_INCLUDED -#include <vector> #include <cstdint> -#include <memory> #include <wx/stream.h> -#include <zen/file_error.h> #include <zen/file_io.h> @@ -26,18 +23,13 @@ template <class S> void writeString(wxOutputStream& stream, const S& str); //############# wxWidgets stream adapter ############# -// can be used as base classes (have virtual destructors) class FileInputStream : public wxInputStream { public: - FileInputStream(const Zstring& filename) : //throw FileError - fileObj(filename) {} + FileInputStream(const Zstring& filename) : fileObj(filename) {} //throw FileError private: - virtual size_t OnSysRead(void* buffer, size_t bufsize) - { - return fileObj.read(buffer, bufsize); //throw FileError - } + virtual size_t OnSysRead(void* buffer, size_t bufsize) { return fileObj.read(buffer, bufsize); } //throw FileError zen::FileInput fileObj; }; @@ -46,8 +38,7 @@ private: class FileOutputStream : public wxOutputStream { public: - FileOutputStream(const Zstring& filename) : //throw FileError - fileObj(filename, zen::FileOutput::ACC_OVERWRITE) {} + FileOutputStream(const Zstring& filename) : fileObj(filename, zen::FileOutput::ACC_OVERWRITE) {} //throw FileError private: virtual size_t OnSysWrite(const void* buffer, size_t bufsize) @@ -60,11 +51,11 @@ private: }; - -class ReadInputStream //throw FileError +//wxInputStream proxy throwing FileError on error +class CheckedReader { -protected: - ReadInputStream(wxInputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} +public: + CheckedReader(wxInputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} template <class T> T readNumberC() const; //throw FileError, checked read operation @@ -72,23 +63,19 @@ protected: template <class S> S readStringC() const; //throw FileError, checked read operation - typedef std::shared_ptr<std::vector<char> > CharArray; //there's no guarantee std::string has a ref-counted implementation... so use this "thing" - CharArray readArrayC() const; //throw FileError - +private: void check() const; - wxInputStream& getStream() { return stream_; } - -private: wxInputStream& stream_; const Zstring& errorObjName_; //used for error text only }; -class WriteOutputStream //throw FileError +//wxOutputStream proxy throwing FileError on error +class CheckedWriter { -protected: - WriteOutputStream(const Zstring& errorObjName, wxOutputStream& stream) : stream_(stream), errorObjName_(errorObjName) {} +public: + CheckedWriter(wxOutputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} template <class T> void writeNumberC(T number) const; //throw FileError, checked write operation @@ -96,13 +83,9 @@ protected: template <class S> void writeStringC(const S& str) const; //throw FileError, checked write operation - void writeArrayC(const std::vector<char>& buffer) const; //throw FileError - +private: void check() const; - wxOutputStream& getStream() { return stream_; } - -private: wxOutputStream& stream_; const Zstring& errorObjName_; //used for error text only! }; @@ -130,11 +113,6 @@ private: - - - - - //-----------------------implementation------------------------------- template <class T> inline T readPOD(wxInputStream& stream) @@ -155,21 +133,15 @@ void writePOD(wxOutputStream& stream, const T& pod) template <class S> inline S readString(wxInputStream& stream) { + //don't even consider UTF8 conversions here! "string" is expected to handle arbitrary binary data! + typedef typename S::value_type CharType; const auto strLength = readPOD<std::uint32_t>(stream); - if (strLength <= 1000) - { - CharType buffer[1000]; - stream.Read(buffer, sizeof(CharType) * strLength); - return S(buffer, strLength); - } - else - { - std::vector<CharType> buffer(strLength); //throw std::bad_alloc - stream.Read(&buffer[0], sizeof(CharType) * strLength); - return S(&buffer[0], strLength); - } + S output; + output.resize(strLength); //throw std::bad_alloc + stream.Read(&*output.begin(), sizeof(CharType) * strLength); + return output; } @@ -182,7 +154,7 @@ void writeString(wxOutputStream& stream, const S& str) inline -void ReadInputStream::check() const +void CheckedReader::check() const { if (stream_.GetLastError() != wxSTREAM_NO_ERROR) throw zen::FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); @@ -191,7 +163,7 @@ void ReadInputStream::check() const template <class T> inline -T ReadInputStream::readNumberC() const //checked read operation +T CheckedReader::readNumberC() const //checked read operation { T output = readPOD<T>(stream_); check(); @@ -200,13 +172,15 @@ T ReadInputStream::readNumberC() const //checked read operation template <class S> inline -S ReadInputStream::readStringC() const //checked read operation +S CheckedReader::readStringC() const //checked read operation { S output; try { - output = readString<S>(stream_); //throw (std::bad_alloc) + output = readString<S>(stream_); //throw std::bad_alloc check(); + if (stream_.LastRead() != output.length() * sizeof(typename S::value_type)) //some additional check + throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); } catch (std::exception&) { @@ -216,24 +190,8 @@ S ReadInputStream::readStringC() const //checked read operation } -inline -ReadInputStream::CharArray ReadInputStream::readArrayC() const -{ - const std::uint32_t byteCount = readNumberC<std::uint32_t>(); - CharArray buffer(new std::vector<char>(byteCount)); - if (byteCount > 0) - { - stream_.Read(&(*buffer)[0], byteCount); - check(); - if (stream_.LastRead() != byteCount) //some additional check - throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); - } - return buffer; -} - - template <class T> inline -void WriteOutputStream::writeNumberC(T number) const //checked write operation +void CheckedWriter::writeNumberC(T number) const //checked write operation { writePOD<T>(stream_, number); check(); @@ -241,29 +199,17 @@ void WriteOutputStream::writeNumberC(T number) const //checked write operation template <class S> inline -void WriteOutputStream::writeStringC(const S& str) const //checked write operation +void CheckedWriter::writeStringC(const S& str) const //checked write operation { writeString(stream_, str); check(); + if (stream_.LastWrite() != str.length() * sizeof(typename S::value_type)) //some additional check + throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); } inline -void WriteOutputStream::writeArrayC(const std::vector<char>& buffer) const -{ - writeNumberC<std::uint32_t>(static_cast<std::uint32_t>(buffer.size())); - if (buffer.size() > 0) - { - stream_.Write(&buffer[0], buffer.size()); - check(); - if (stream_.LastWrite() != buffer.size()) //some additional check - throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); - } -} - - -inline -void WriteOutputStream::check() const +void CheckedWriter::check() const { if (stream_.GetLastError() != wxSTREAM_NO_ERROR) throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); diff --git a/lib/FindFilePlus/FindFilePlus.vcxproj b/zen/FindFilePlus/FindFilePlus.vcxproj index 2c4256a6..2c4256a6 100644 --- a/lib/FindFilePlus/FindFilePlus.vcxproj +++ b/zen/FindFilePlus/FindFilePlus.vcxproj diff --git a/lib/FindFilePlus/dll_main.cpp b/zen/FindFilePlus/dll_main.cpp index 5d64181b..5d64181b 100644 --- a/lib/FindFilePlus/dll_main.cpp +++ b/zen/FindFilePlus/dll_main.cpp diff --git a/lib/FindFilePlus/find_file_plus.cpp b/zen/FindFilePlus/find_file_plus.cpp index becfe553..becfe553 100644 --- a/lib/FindFilePlus/find_file_plus.cpp +++ b/zen/FindFilePlus/find_file_plus.cpp diff --git a/lib/FindFilePlus/find_file_plus.h b/zen/FindFilePlus/find_file_plus.h index aacdf0ea..72b76dbb 100644 --- a/lib/FindFilePlus/find_file_plus.h +++ b/zen/FindFilePlus/find_file_plus.h @@ -48,7 +48,7 @@ FindHandle openDir(const wchar_t* dirname); //returns NULL on error, call ::GetL //note: do NOT place an asterisk at end, e.g. C:\SomeDir\*, as one would do for ::FindFirstFile() DLL_FUNCTION_DECLARATION -bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES +bool readDir(FindHandle hnd, FileInformation& output); //returns false on error or if there are no more files; ::GetLastError() returns ERROR_NO_MORE_FILES in this case DLL_FUNCTION_DECLARATION void closeDir(FindHandle hnd); diff --git a/lib/FindFilePlus/init_dll_binding.h b/zen/FindFilePlus/init_dll_binding.h index 51b32c99..51b32c99 100644 --- a/lib/FindFilePlus/init_dll_binding.h +++ b/zen/FindFilePlus/init_dll_binding.h diff --git a/lib/FindFilePlus/load_dll.cpp b/zen/FindFilePlus/load_dll.cpp index 20d9a5fe..20d9a5fe 100644 --- a/lib/FindFilePlus/load_dll.cpp +++ b/zen/FindFilePlus/load_dll.cpp diff --git a/lib/FindFilePlus/load_dll.h b/zen/FindFilePlus/load_dll.h index 350de9f8..350de9f8 100644 --- a/lib/FindFilePlus/load_dll.h +++ b/zen/FindFilePlus/load_dll.h diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp index 81e49f89..c980c715 100644 --- a/zen/dir_watcher.cpp +++ b/zen/dir_watcher.cpp @@ -134,7 +134,8 @@ public: ReadChangesAsync(const Zstring& directory, //make sure to not leak in thread-unsafe types! const std::shared_ptr<SharedData>& shared) : shared_(shared), - dirname(directory) + dirname(directory), + hDir(INVALID_HANDLE_VALUE) { if (!endsWith(dirname, FILE_NAME_SEPARATOR)) dirname += FILE_NAME_SEPARATOR; @@ -143,8 +144,8 @@ public: //http://msdn.microsoft.com/en-us/library/aa363858(v=vs.85).aspx try { - Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError - Privileges::getInstance().ensureActive(SE_RESTORE_NAME); // + activatePrivilege(SE_BACKUP_NAME); //throw FileError + activatePrivilege(SE_RESTORE_NAME); // } catch (const FileError&) {} @@ -155,7 +156,7 @@ public: OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); - if (hDir == INVALID_HANDLE_VALUE ) + if (hDir == INVALID_HANDLE_VALUE) { const std::wstring errorMsg = _("Could not initialize directory monitoring:") + L"\n\"" + dirname + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); if (errorCodeForNotExisting(::GetLastError())) @@ -253,7 +254,7 @@ public: std::swap(hDir, other.hDir); } - HANDLE getDirHandle() const { return hDir; } //for reading purposes only, don't abuse (e.g. close handle)! + HANDLE getDirHandle() const { return hDir; } //for reading/monitoring purposes only, don't abuse (e.g. close handle)! private: //shared between main and worker: @@ -268,13 +269,9 @@ class HandleVolumeRemoval : public NotifyRequestDeviceRemoval { public: HandleVolumeRemoval(HANDLE hDir, - boost::thread& worker, - const std::shared_ptr<SharedData>& shared, - const Zstring& dirname) : + boost::thread& worker) : NotifyRequestDeviceRemoval(hDir), //throw FileError worker_(worker), - shared_(shared), - dirname_(dirname), removalRequested(false), operationComplete(false) {} @@ -291,16 +288,12 @@ private: worker_.join(); //now hDir should have been released - //report removal as change to main directory - shared_->addChange(dirname_); - removalRequested = true; } //don't throw! + virtual void onRemovalFinished(HANDLE hnd, bool successful) { operationComplete = true; } //throw()! boost::thread& worker_; - std::shared_ptr<SharedData> shared_; - Zstring dirname_; bool removalRequested; bool operationComplete; }; @@ -312,6 +305,7 @@ struct DirWatcher::Pimpl boost::thread worker; std::shared_ptr<SharedData> shared; + Zstring dirname; std::unique_ptr<HandleVolumeRemoval> volRemoval; }; @@ -320,9 +314,10 @@ DirWatcher::DirWatcher(const Zstring& directory) : //throw FileError pimpl_(new Pimpl) { pimpl_->shared = std::make_shared<SharedData>(); + pimpl_->dirname = directory; ReadChangesAsync reader(directory, pimpl_->shared); //throw FileError - pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker, pimpl_->shared, directory)); //throw FileError + pimpl_->volRemoval.reset(new HandleVolumeRemoval(reader.getDirHandle(), pimpl_->worker)); //throw FileError pimpl_->worker = boost::thread(std::move(reader)); } @@ -332,22 +327,29 @@ DirWatcher::~DirWatcher() pimpl_->worker.interrupt(); //pimpl_->worker.join(); -> we don't have time to wait... will take ~50ms anyway //caveat: exitting the app may simply kill this thread! +} + + +std::vector<Zstring> DirWatcher::getChanges(const std::function<void()>& processGuiMessages) //throw FileError +{ + std::vector<Zstring> output; - //wait until device removal is confirmed, to (hopefully!) prevent locking hDir again by new watch! + //wait until device removal is confirmed, to prevent locking hDir again by some new watch! if (pimpl_->volRemoval->requestReceived()) { - const boost::system_time maxwait = boost::get_system_time() + boost::posix_time::seconds(3); //HandleVolumeRemoval::finished() not guaranteed! + const boost::system_time maxwait = boost::get_system_time() + boost::posix_time::seconds(15); + //HandleVolumeRemoval::finished() not guaranteed! note: Windows gives unresponsive applications ca. 10 seconds until unmounting the usb stick in worst case while (!pimpl_->volRemoval->finished() && boost::get_system_time() < maxwait) + { + processGuiMessages(); //DBT_DEVICEREMOVECOMPLETE message is sent here! boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(50)); - } -} - + } -std::vector<Zstring> DirWatcher::getChanges() //throw FileError -{ - std::vector<Zstring> output; - pimpl_->shared->getChanges(output); //throw FileError + output.push_back(pimpl_->dirname); //report removal as change to main directory + } + else //the normal case... + pimpl_->shared->getChanges(output); //throw FileError return output; } @@ -454,7 +456,7 @@ DirWatcher::~DirWatcher() } -std::vector<Zstring> DirWatcher::getChanges() //throw FileError +std::vector<Zstring> DirWatcher::getChanges(const std::function<void()>&) //throw FileError { std::vector<char> buffer(1024 * (sizeof(struct inotify_event) + 16)); diff --git a/zen/dir_watcher.h b/zen/dir_watcher.h index df3c444c..a9898abb 100644 --- a/zen/dir_watcher.h +++ b/zen/dir_watcher.h @@ -9,6 +9,7 @@ #include <vector> #include <memory> +#include <functional> #include "file_error.h" namespace zen @@ -35,7 +36,7 @@ public: ~DirWatcher(); //extract accumulated changes since last call - std::vector<Zstring> getChanges(); //throw FileError + std::vector<Zstring> getChanges(const std::function<void()>& processGuiMessages); //throw FileError private: DirWatcher(const DirWatcher&); diff --git a/zen/file_handling.cpp b/zen/file_handling.cpp index 5d57938a..8523c633 100644 --- a/zen/file_handling.cpp +++ b/zen/file_handling.cpp @@ -15,7 +15,7 @@ #include "assert_static.h" #include <boost/thread/tss.hpp> #include <boost/thread/once.hpp> -#include "file_id_internal.h" +#include "file_id_def.h" #ifdef FFS_WIN #include "privilege.h" @@ -194,12 +194,15 @@ namespace #ifdef FFS_WIN DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! { - std::vector<wchar_t> buffer(10000); + //note: this even works for network shares: \\share\dirname + + const DWORD BUFFER_SIZE = 10000; + std::vector<wchar_t> buffer(BUFFER_SIZE); //full pathName need not yet exist! if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName, &buffer[0], //__out LPTSTR lpszVolumePathName, - static_cast<DWORD>(buffer.size()))) //__in DWORD cchBufferLength + BUFFER_SIZE)) //__in DWORD cchBufferLength return 0; Zstring volumePath = &buffer[0]; @@ -608,7 +611,7 @@ struct RemoveCallbackImpl : public CallbackRemoveDir moveCallback_(moveCallback) {} virtual void notifyFileDeletion(const Zstring& filename) { moveCallback_.requestUiRefresh(sourceDir_); } - virtual void notifyDirDeletion(const Zstring& dirname) { moveCallback_.requestUiRefresh(sourceDir_); } + virtual void notifyDirDeletion (const Zstring& dirname ) { moveCallback_.requestUiRefresh(sourceDir_); } private: RemoveCallbackImpl(const RemoveCallbackImpl&); @@ -620,7 +623,7 @@ private: } -void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError; +void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError { //call back once per folder if (callback) @@ -683,7 +686,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool } -void zen::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError; +void zen::moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExisting, CallbackMoveFile* callback) //throw FileError { #ifdef FFS_WIN const Zstring& sourceDirFormatted = sourceDir; @@ -999,13 +1002,13 @@ void copyObjectPermissions(const Zstring& source, const Zstring& target, ProcSym try { //enable privilege: required to read/write SACL information - Privileges::getInstance().ensureActive(SE_SECURITY_NAME); //polling allowed... + activatePrivilege(SE_SECURITY_NAME); //polling allowed... //enable privilege: required to copy owner information - Privileges::getInstance().ensureActive(SE_RESTORE_NAME); + activatePrivilege(SE_RESTORE_NAME); //the following privilege may be required according to http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx (although not needed nor active in my tests) - Privileges::getInstance().ensureActive(SE_BACKUP_NAME); + activatePrivilege(SE_BACKUP_NAME); } catch (const FileError& e) { @@ -1416,14 +1419,19 @@ public: throw FileError(errorMsg); } - void setSrcAttr(const FileAttrib& attr) { sourceAttr = attr; } - FileAttrib getSrcAttr() const { assert(sourceAttr.modificationTime != 0); return sourceAttr; } + void setNewAttr(const FileAttrib& attr) { newAttrib = attr; } + + FileAttrib getSrcAttr() const + { + assert(newAttrib.modificationTime != 0); + return newAttrib; + } private: CallbackData(const CallbackData&); CallbackData& operator=(const CallbackData&); - FileAttrib sourceAttr; + FileAttrib newAttrib; std::wstring errorMsg; // bool exceptionInUserCallback; //these two are exclusive! UInt64 bytesTransferredOnException; @@ -1456,19 +1464,27 @@ DWORD CALLBACK copyCallbackInternal( //#################### return source file attributes ################################ if (dwCallbackReason == CALLBACK_STREAM_SWITCH) //called up front for every file (even if 0-sized) { - BY_HANDLE_FILE_INFORMATION fileInfo = {}; - if (!::GetFileInformationByHandle(hSourceFile, &fileInfo)) + BY_HANDLE_FILE_INFORMATION fileInfoSrc = {}; + if (!::GetFileInformationByHandle(hSourceFile, &fileInfoSrc)) { cbd.reportError(_("Error reading file attributes:") + L"\n\"" + cbd.sourceFile_ + L"\"" + L"\n\n" + getLastErrorFormatted()); return PROGRESS_CANCEL; } - const FileAttrib attr = { UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh), - toTimeT(fileInfo.ftLastWriteTime) - }; - //extractFileID(fileInfo)); + BY_HANDLE_FILE_INFORMATION fileInfoTrg = {}; + if (!::GetFileInformationByHandle(hDestinationFile, &fileInfoTrg)) + { + cbd.reportError(_("Error reading file attributes:") + L"\n\"" + cbd.targetFile_ + L"\"" + L"\n\n" + getLastErrorFormatted()); + return PROGRESS_CANCEL; + } + + FileAttrib attr; + attr.fileSize = UInt64(fileInfoSrc.nFileSizeLow, fileInfoSrc.nFileSizeHigh); + attr.modificationTime = toTimeT(fileInfoSrc.ftLastWriteTime); + attr.sourceFileId = extractFileID(fileInfoSrc); + attr.targetFileId = extractFileID(fileInfoTrg); - cbd.setSrcAttr(attr); + cbd.setNewAttr(attr); //#################### copy file creation time ################################ FILETIME creationTime = {}; @@ -1527,7 +1543,7 @@ DWORD CALLBACK copyCallbackInternal( void rawCopyWinApi_sub(const Zstring& sourceFile, const Zstring& targetFile, CallbackCopyFile* callback, - FileAttrib* sourceAttr) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked + FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting, ErrorFileLocked { zen::ScopeGuard guardTarget = zen::makeGuard([&]() { removeFile(targetFile); }); //transactional behavior: guard just before starting copy, we don't trust ::CopyFileEx(), do we ;) @@ -1601,8 +1617,8 @@ void rawCopyWinApi_sub(const Zstring& sourceFile, throw FileError(errorMessage); } - if (sourceAttr) - *sourceAttr = cbd.getSrcAttr(); + if (newAttrib) + *newAttrib = cbd.getSrcAttr(); { const Int64 modTime = getFileTime(sourceFile, SYMLINK_FOLLOW); //throw FileError @@ -1972,7 +1988,7 @@ void rawCopyWinApi(const Zstring& sourceFile, void rawCopyStream(const Zstring& sourceFile, const Zstring& targetFile, CallbackCopyFile* callback, - FileAttrib* sourceAttr) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting + FileAttrib* newAttrib) //throw FileError, ErrorTargetPathMissing, ErrorTargetExisting { zen::ScopeGuard guardTarget = zen::makeGuard([&]() { removeFile(targetFile); }); //transactional behavior: place guard before lifetime of FileOutput try @@ -2012,23 +2028,29 @@ void rawCopyStream(const Zstring& sourceFile, //adapt file modification time: { - struct stat srcInfo = {}; + struct ::stat srcInfo = {}; if (::stat(sourceFile.c_str(), &srcInfo) != 0) //read file attributes from source directory throw FileError(_("Error reading file attributes:") + L"\n\"" + sourceFile + L"\"" + L"\n\n" + getLastErrorFormatted()); - if (sourceAttr) - { - sourceAttr->fileSize = UInt64(srcInfo.st_size); - sourceAttr->modificationTime = srcInfo.st_mtime; - } - - struct utimbuf newTimes = {}; + struct ::utimbuf newTimes = {}; newTimes.actime = srcInfo.st_atime; newTimes.modtime = srcInfo.st_mtime; //set new "last write time" if (::utime(targetFile.c_str(), &newTimes) != 0) throw FileError(_("Error changing modification time:") + L"\n\"" + targetFile + L"\"" + L"\n\n" + getLastErrorFormatted()); + + if (newAttrib) + { + struct ::stat trgInfo = {}; + if (::stat(targetFile.c_str(), &trgInfo) != 0) //read file attributes from source directory + throw FileError(_("Error reading file attributes:") + L"\n\"" + targetFile + L"\"" + L"\n\n" + getLastErrorFormatted()); + + newAttrib->fileSize = UInt64(srcInfo.st_size); + newAttrib->modificationTime = srcInfo.st_mtime; + newAttrib->sourceFileId = extractFileID(srcInfo); + newAttrib->targetFileId = extractFileID(trgInfo); + } } guardTarget.dismiss(); //target has been created successfully! diff --git a/zen/file_handling.h b/zen/file_handling.h index 02f3e532..8ffe38d0 100644 --- a/zen/file_handling.h +++ b/zen/file_handling.h @@ -10,6 +10,7 @@ #include "zstring.h" #include "file_error.h" #include "int64.h" +#include "file_id_def.h" namespace zen { @@ -68,7 +69,9 @@ void createDirectory(const Zstring& directory); //throw FileError; -> function o struct FileAttrib { UInt64 fileSize; - Int64 modificationTime; //size_t UTC compatible + Int64 modificationTime; //time_t UTC compatible + FileId sourceFileId; + FileId targetFileId; }; void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissing, ErrorFileLocked (Windows-only) @@ -76,7 +79,7 @@ void copyFile(const Zstring& sourceFile, //throw FileError, ErrorTargetPathMissi bool copyFilePermissions, bool transactionalCopy, CallbackCopyFile* callback, //may be NULL - FileAttrib* sourceAttr = NULL); //return current attributes at the time of copy + FileAttrib* newAttrib = NULL); //return current attributes at the time of copy //Note: it MAY happen that copyFile() leaves temp files behind, e.g. temporary network drop. // => clean them up at an appropriate time (automatically set sync directions to delete them). They have the following ending: const Zstring TEMP_FILE_ENDING = Zstr(".ffs_tmp"); diff --git a/zen/file_id.cpp b/zen/file_id.cpp index acbdcd7b..7527062b 100644 --- a/zen/file_id.cpp +++ b/zen/file_id.cpp @@ -5,7 +5,6 @@ // ************************************************************************** #include "file_id.h" -#include "file_id_internal.h" #ifdef FFS_WIN #include "win.h" //includes "windows.h" @@ -17,7 +16,7 @@ #endif -std::string zen::getFileID(const Zstring& filename) +zen::FileId zen::getFileID(const Zstring& filename) { #ifdef FFS_WIN //WARNING: CreateFile() is SLOW, while GetFileInformationByHandle() is cheap! @@ -43,11 +42,11 @@ std::string zen::getFileID(const Zstring& filename) #elif defined FFS_LINUX struct ::stat fileInfo = {}; - if (::lstat(filename.c_str(), &fileInfo) == 0) //lstat() does not follow symlinks + if (::stat(filename.c_str(), &fileInfo) == 0) //stat() follows symlinks return extractFileID(fileInfo); #endif - return std::string(); + return zen::FileId(); } @@ -56,10 +55,10 @@ bool zen::samePhysicalFile(const Zstring& file1, const Zstring& file2) if (EqualFilename()(file1, file2)) //quick check return true; - const std::string id1 = getFileID(file1); - const std::string id2 = getFileID(file2); + const auto id1 = getFileID(file1); + const auto id2 = getFileID(file2); - if (id1.empty() || id2.empty()) + if (id1 == zen::FileId() || id2 == zen::FileId()) return false; return id1 == id2; diff --git a/zen/file_id.h b/zen/file_id.h index f015569d..3fd4c6bb 100644 --- a/zen/file_id.h +++ b/zen/file_id.h @@ -7,6 +7,7 @@ #ifndef FILEID_H_INCLUDED #define FILEID_H_INCLUDED +#include "file_id_def.h" #include "zstring.h" #include <string> @@ -15,8 +16,8 @@ namespace zen { //get unique file id (symbolic link handling: opens the link!!!) -//returns empty string on error! -std::string getFileID(const Zstring& filename); +//returns initial FileId() on error! +FileId getFileID(const Zstring& filename); //test whether two distinct paths point to the same file or directory: // true: paths point to same files/dirs diff --git a/zen/file_id_def.h b/zen/file_id_def.h new file mode 100644 index 00000000..b2029879 --- /dev/null +++ b/zen/file_id_def.h @@ -0,0 +1,65 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** + +#ifndef FILE_ID_INTERNAL_HEADER_013287632486321493 +#define FILE_ID_INTERNAL_HEADER_013287632486321493 + +#include <utility> +#include "assert_static.h" + +#ifdef FFS_WIN +#include "win.h" //includes "windows.h" + +#elif defined FFS_LINUX +#include <sys/stat.h> +#endif + + +namespace zen +{ +#ifdef FFS_WIN +typedef std::pair<decltype(BY_HANDLE_FILE_INFORMATION().dwVolumeSerialNumber), decltype(ULARGE_INTEGER().QuadPart)> FileId; //(volume serial number, file ID) + +inline +FileId extractFileID(const BY_HANDLE_FILE_INFORMATION& fileInfo) +{ + ULARGE_INTEGER uint = {}; + uint.HighPart = fileInfo.nFileIndexHigh; + uint.LowPart = fileInfo.nFileIndexLow; + return std::make_pair(fileInfo.dwVolumeSerialNumber, uint.QuadPart); +} + +inline +FileId extractFileID(DWORD dwVolumeSerialNumber, ULARGE_INTEGER fileId) +{ + return std::make_pair(dwVolumeSerialNumber, fileId.QuadPart); +} + +namespace impl +{ +inline +void validate(const FileId& id, const BY_HANDLE_FILE_INFORMATION& fileInfo) +{ + assert_static(sizeof(id.second) == sizeof(fileInfo.nFileIndexHigh) + sizeof(fileInfo.nFileIndexLow)); + assert_static(sizeof(id.first ) == sizeof(DWORD)); + assert_static(sizeof(id.second) == sizeof(ULARGE_INTEGER)); +} +} + +#elif defined FFS_LINUX +namespace impl { typedef struct ::stat StatDummy; } //sigh... + +typedef std::pair<decltype(impl::StatDummy::st_dev), decltype(impl::StatDummy::st_ino)> FileId; //(device id, inode) + +inline +FileId extractFileID(const struct stat& fileInfo) +{ + return std::make_pair(fileInfo.st_dev, fileInfo.st_ino); +} +#endif +} + +#endif //FILE_ID_INTERNAL_HEADER_013287632486321493 diff --git a/zen/file_id_internal.h b/zen/file_id_internal.h deleted file mode 100644 index 492d8432..00000000 --- a/zen/file_id_internal.h +++ /dev/null @@ -1,48 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** - -#ifndef FILE_ID_INTERNAL_HEADER_013287632486321493 -#define FILE_ID_INTERNAL_HEADER_013287632486321493 - -#include <string> - -#ifdef FFS_WIN -#include "win.h" //includes "windows.h" - -#elif defined FFS_LINUX -#include <sys/stat.h> -#endif - -namespace -{ -template <class T> inline -std::string numberToBytes(T number) -{ - const char* rawBegin = reinterpret_cast<const char*>(&number); - return std::string(rawBegin, rawBegin + sizeof(number)); -} - -#ifdef FFS_WIN -inline -std::string extractFileID(const BY_HANDLE_FILE_INFORMATION& fileInfo) -{ - return numberToBytes(fileInfo.dwVolumeSerialNumber) + - numberToBytes(fileInfo.nFileIndexHigh) + - numberToBytes(fileInfo.nFileIndexLow); -} -#elif defined FFS_LINUX -inline -std::string extractFileID(const struct stat& fileInfo) -{ - return numberToBytes(fileInfo.st_dev) + - numberToBytes(fileInfo.st_ino); -} -#endif - -} - - -#endif //FILE_ID_INTERNAL_HEADER_013287632486321493 diff --git a/zen/file_traverser.cpp b/zen/file_traverser.cpp index 7a2df695..81e70383 100644 --- a/zen/file_traverser.cpp +++ b/zen/file_traverser.cpp @@ -14,8 +14,8 @@ #include "long_path_prefix.h" #include "dst_hack.h" #include "file_update_handle.h" -//#include "dll_loader.h" -//#include "FindFilePlus/find_file_plus.h" +#include "dll.h" +#include "FindFilePlus/find_file_plus.h" #elif defined FFS_LINUX #include <sys/stat.h> @@ -30,33 +30,34 @@ namespace { //implement "retry" in a generic way: -//returns "true" if "cmd" was invoked successfully, "false" if error occured and was ignored -template <class Command> inline //function object with bool operator()(std::wstring& errorMsg), returns "true" on success, "false" on error and writes "errorMsg" in this case -bool tryReportingError(Command cmd, zen::TraverseCallback& callback) +template <class Command> inline //function object expecting to throw FileError if operation fails +void tryReportingError(Command cmd, zen::TraverseCallback& callback) { for (;;) - { - std::wstring errorMsg; - if (cmd(errorMsg)) - return true; - - switch (callback.onError(errorMsg)) + try { - case TraverseCallback::TRAV_ERROR_RETRY: - break; - case TraverseCallback::TRAV_ERROR_IGNORE: - return false; - default: - assert(false); - break; + cmd(); + return; + } + catch (const FileError& e) + { + switch (callback.onError(e.toString())) + { + case TraverseCallback::TRAV_ERROR_RETRY: + break; + case TraverseCallback::TRAV_ERROR_IGNORE: + return; + default: + assert(false); + break; + } } - } } #ifdef FFS_WIN inline -bool setWin32FileInformationFromSymlink(const Zstring& linkName, zen::TraverseCallback::FileInfo& output) +bool extractFileInfoFromSymlink(const Zstring& linkName, zen::TraverseCallback::FileInfo& output) { //open handle to target of symbolic link HANDLE hFile = ::CreateFile(zen::applyLongPathPrefix(linkName).c_str(), @@ -75,288 +76,308 @@ bool setWin32FileInformationFromSymlink(const Zstring& linkName, zen::TraverseCa return false; //write output - output.lastWriteTimeRaw = toTimeT(fileInfoByHandle.ftLastWriteTime); output.fileSize = zen::UInt64(fileInfoByHandle.nFileSizeLow, fileInfoByHandle.nFileSizeHigh); + output.lastWriteTimeRaw = toTimeT(fileInfoByHandle.ftLastWriteTime); + //output.id = extractFileID(fileInfoByHandle); -> id from dereferenced symlink is problematic, since renaming will consider the link, not the target! return true; } + +DWORD retrieveVolumeSerial(const Zstring& pathName) //return 0 on error! +{ + //note: this even works for network shares: \\share\dirname + + const DWORD BUFFER_SIZE = 10000; + std::vector<wchar_t> buffer(BUFFER_SIZE); + + //full pathName need not yet exist! + if (!::GetVolumePathName(pathName.c_str(), //__in LPCTSTR lpszFileName, + &buffer[0], //__out LPTSTR lpszVolumePathName, + BUFFER_SIZE)) //__in DWORD cchBufferLength + return 0; + + Zstring volumePath = &buffer[0]; + if (!endsWith(volumePath, FILE_NAME_SEPARATOR)) + volumePath += FILE_NAME_SEPARATOR; + + DWORD volumeSerial = 0; + if (!::GetVolumeInformation(volumePath.c_str(), //__in_opt LPCTSTR lpRootPathName, + NULL, //__out LPTSTR lpVolumeNameBuffer, + 0, //__in DWORD nVolumeNameSize, + &volumeSerial, //__out_opt LPDWORD lpVolumeSerialNumber, + NULL, //__out_opt LPDWORD lpMaximumComponentLength, + NULL, //__out_opt LPDWORD lpFileSystemFlags, + NULL, //__out LPTSTR lpFileSystemNameBuffer, + 0)) //__in DWORD nFileSystemNameSize + return 0; + + return volumeSerial; +} + + +const DllFun<findplus::OpenDirFunc> openDir (findplus::getDllName(), findplus::openDirFuncName ); // +const DllFun<findplus::ReadDirFunc> readDir (findplus::getDllName(), findplus::readDirFuncName ); //load at startup: avoid pre C++11 static initialization MT issues +const DllFun<findplus::CloseDirFunc> closeDir(findplus::getDllName(), findplus::closeDirFuncName); // + + /* -warn_static("finish") - DllFun<findplus::OpenDirFunc> openDir (findplus::getDllName(), findplus::openDirFuncName); - DllFun<findplus::ReadDirFunc> readDir (findplus::getDllName(), findplus::readDirFuncName); - DllFun<findplus::CloseDirFunc> closeDir(findplus::getDllName(), findplus::closeDirFuncName); - -> thread safety! -*/ -#endif +Common C-style interface for Win32 FindFirstFile(), FindNextFile() and FileFilePlus openDir(), closeDir(): +struct X //see "policy based design" +{ +typedef ... Handle; +typedef ... FindData; +static Handle create(const Zstring& directoryPf, FindData& fileInfo); //throw FileError +static void destroy(Handle hnd); //throw() +static bool next(Handle hnd, const Zstring& directory, WIN32_FIND_DATA& fileInfo) //throw FileError + +//helper routines +static void extractFileInfo (const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output); +static Int64 getModTime (const FindData& fileInfo); +static const FILETIME& getModTimeRaw (const FindData& fileInfo); //yet another concession to DST hack +static const FILETIME& getCreateTimeRaw(const FindData& fileInfo); // +static const wchar_t* getShortName (const FindData& fileInfo); +static bool isDirectory (const FindData& fileInfo); +static bool isSymlink (const FindData& fileInfo); } +Note: Win32 FindFirstFile(), FindNextFile() is a weaker abstraction than FileFilePlus openDir(), readDir(), closeDir() and Unix opendir(), closedir(), stat(), + so unfortunately we have to use former as a greatest common divisor +*/ -class DirTraverser + +struct Win32Traverser { -public: - DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) : -#ifdef FFS_WIN - isFatFileSystem(dst::isFatDrive(baseDirectory)), -#endif - followSymlinks_(followSymlinks) + typedef HANDLE Handle; + typedef WIN32_FIND_DATA FindData; + + static Handle create(const Zstring& directory, FindData& fileInfo) //throw FileError { -#ifdef FFS_WIN - //format base directory name - const Zstring& directoryFormatted = baseDirectory; + const Zstring& directoryPf = endsWith(directory, FILE_NAME_SEPARATOR) ? + directory : + directory + FILE_NAME_SEPARATOR; -#elif defined FFS_LINUX - const Zstring directoryFormatted = //remove trailing slash - baseDirectory.size() > 1 && endsWith(baseDirectory, FILE_NAME_SEPARATOR) ? //exception: allow '/' - beforeLast(baseDirectory, FILE_NAME_SEPARATOR) : - baseDirectory; -#endif + HANDLE output = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo); + //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH + if (output == INVALID_HANDLE_VALUE) + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + //::GetLastError() == ERROR_FILE_NOT_FOUND -> actually NOT okay, even for an empty directory this should not occur (., ..) + return output; + } - //traverse directories - traverse(directoryFormatted, sink, 0); + static void destroy(Handle hnd) { ::FindClose(hnd); } //throw() - //apply daylight saving time hack AFTER file traversing, to give separate feedback to user -#ifdef FFS_WIN - if (isFatFileSystem && dstCallback) - applyDstHack(*dstCallback); -#endif + static bool next(Handle hnd, const Zstring& directory, FindData& fileInfo) //throw FileError + { + if (!::FindNextFile(hnd, &fileInfo)) + { + if (::GetLastError() == ERROR_NO_MORE_FILES) //not an error situation + return false; + //else we have a problem... report it: + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + } + return true; } -private: - DirTraverser(const DirTraverser&); - DirTraverser& operator=(const DirTraverser&); + //helper routines + template <class FindData> + static void extractFileInfo(const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output) + { + output.lastWriteTimeRaw = getModTime(fileInfo); + output.fileSize = UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); + } - void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level) + template <class FindData> + static Int64 getModTime(const FindData& fileInfo) { return toTimeT(fileInfo.ftLastWriteTime); } + + template <class FindData> + static const FILETIME& getModTimeRaw(const FindData& fileInfo) { return fileInfo.ftLastWriteTime; } + + template <class FindData> + static const FILETIME& getCreateTimeRaw(const FindData& fileInfo) { return fileInfo.ftCreationTime; } + + template <class FindData> + static const wchar_t* getShortName(const FindData& fileInfo) { return fileInfo.cFileName; } + + template <class FindData> + static bool isDirectory(const FindData& fileInfo) { return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } + + template <class FindData> + static bool isSymlink(const FindData& fileInfo) { return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } +}; + + +struct FilePlusTraverser +{ + typedef findplus::FindHandle Handle; + typedef findplus::FileInformation FindData; + + static Handle create(const Zstring& directory, FindData& fileInfo) //throw FileError { - tryReportingError([&](std::wstring& errorMsg) -> bool + Handle output = ::openDir(applyLongPathPrefix(directory).c_str()); + if (output == NULL) + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + + bool rv = next(output, directory, fileInfo); //throw FileError + if (!rv) //we expect at least two successful reads, even for an empty directory: ., .. + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(ERROR_NO_MORE_FILES)); + + return output; + } + + static void destroy(Handle hnd) { ::closeDir(hnd); } //throw() + + static bool next(Handle hnd, const Zstring& directory, FindData& fileInfo) //throw FileError + { + if (!::readDir(hnd, fileInfo)) { - if (level == 100) //notify endless recursion - { - errorMsg = _("Endless loop when traversing directory:") + L"\n\"" + directory + L"\""; + if (::GetLastError() == ERROR_NO_MORE_FILES) //not an error situation return false; - } - return true; - }, sink); + //else we have a problem... report it: + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + } + return true; + } -#ifdef FFS_WIN - /* - //ensure directoryPf ends with backslash - const Zstring& directoryPf = directory.EndsWith(FILE_NAME_SEPARATOR) ? - directory : - directory + FILE_NAME_SEPARATOR; - - FindHandle searchHandle = NULL; - tryReportingError([&](std::wstring& errorMsg) -> bool - { - searchHandle = this->openDir(applyLongPathPrefix(directoryPf).c_str()); - //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH + //helper routines + template <class FindData> + static void extractFileInfo(const FindData& fileInfo, const DWORD* volumeSerial, TraverseCallback::FileInfo& output) + { + output.fileSize = UInt64(fileInfo.fileSize.QuadPart); + output.lastWriteTimeRaw = getModTime(fileInfo); + if (volumeSerial) + output.id = extractFileID(*volumeSerial, fileInfo.fileId); + } - if (searchHandle == NULL) - { - //const DWORD lastError = ::GetLastError(); - //if (lastError == ERROR_FILE_NOT_FOUND) -> actually NOT okay, even for an empty directory this should not occur (., ..) - //return true; //fine: empty directory + template <class FindData> + static Int64 getModTime(const FindData& fileInfo) { return toTimeT(fileInfo.lastWriteTime); } - //else: we have a problem... report it: - errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(); - return false; - } - return true; - }, sink); + template <class FindData> + static const FILETIME& getModTimeRaw(const FindData& fileInfo) { return fileInfo.lastWriteTime; } - if (searchHandle == NULL) - return; //empty dir or ignore error - ZEN_ON_BLOCK_EXIT(this->closeDir(searchHandle)); + template <class FindData> + static const FILETIME& getCreateTimeRaw(const FindData& fileInfo) { return fileInfo.creationTime; } - FileInformation fileInfo = {}; - for (;;) - { - bool moreData = false; - tryReportingError([&](std::wstring& errorMsg) -> bool - { - if (!this->readDir(searchHandle, fileInfo)) - { - if (::GetLastError() == ERROR_NO_MORE_FILES) //this is fine - return true; - - //else we have a problem... report it: - errorMsg = _("Error traversing directory:") + "\n\"" + directory + "\"" + "\n\n" + zen::getLastErrorFormatted(); - return false; - } - - moreData = true; - return true; - }, sink); - if (!moreData) //no more items or ignore error - return; - - - //don't return "." and ".." - const Zchar* const shortName = fileInfo.shortName; - if (shortName[0] == L'.' && - (shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0'))) - continue; + template <class FindData> + static const wchar_t* getShortName(const FindData& fileInfo) { return fileInfo.shortName; } - const Zstring& fullName = directoryPf + shortName; + template <class FindData> + static bool isDirectory(const FindData& fileInfo) { return (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } - const bool isSymbolicLink = (fileInfo.fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + template <class FindData> + static bool isSymlink(const FindData& fileInfo) { return (fileInfo.fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; } +}; - if (isSymbolicLink && !followSymlinks_) //evaluate symlink directly - { - TraverseCallback::SymlinkInfo details; - try - { - details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError - } - catch (FileError& e) - { - (void)e; - #ifndef NDEBUG //show broken symlink / access errors in debug build! - sink.onError(e.msg()); - #endif - } - - details.lastWriteTimeRaw = toTimeT(fileInfo.lastWriteTime); - details.dirLink = (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; //directory symlinks have this flag on Windows - sink.onSymlink(shortName, fullName, details); - } - else if (fileInfo.fileAttributes & FILE_ATTRIBUTE_DIRECTORY) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!) - { - const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName); - if (rv) - traverse<followSymlinks_>(fullName, *rv, level + 1); - } - else //a file or symlink that is followed... - { - TraverseCallback::FileInfo details; - - if (isSymbolicLink) //dereference symlinks! - { - if (!setWin32FileInformationFromSymlink(fullName, details)) - { - //broken symlink... - details.lastWriteTimeRaw = 0; //we are not interested in the modification time of the link - details.fileSize = 0U; - } - } - else - { - //####################################### DST hack ########################################### - if (isFatFileSystem) - { - const dst::RawTime rawTime(fileInfo.creationTime, fileInfo.lastWriteTime); - - if (dst::fatHasUtcEncoded(rawTime)) //throw (std::runtime_error) - fileInfo.lastWriteTime = dst::fatDecodeUtcTime(rawTime); //return real UTC time; throw (std::runtime_error) - else - markForDstHack.push_back(std::make_pair(fullName, fileInfo.lastWriteTime)); - } - //####################################### DST hack ########################################### - - details.lastWriteTimeRaw = toTimeT(fileInfo.lastWriteTime); - details.fileSize = fileInfo.fileSize.QuadPart; - } - - sink.onFile(shortName, fullName, details); - } - } - */ +class DirTraverser +{ +public: + DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) : + isFatFileSystem(dst::isFatDrive(baseDirectory)), + followSymlinks_(followSymlinks), + volumeSerial(retrieveVolumeSerial(baseDirectory)) //return 0 on error + { + try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail) + { + activatePrivilege(SE_BACKUP_NAME); //throw FileError + } + catch (...) {} //don't cause issues in user mode + if (::openDir && ::readDir && ::closeDir) + traverse<FilePlusTraverser>(baseDirectory, sink, 0); + else //fallback + traverse<Win32Traverser>(baseDirectory, sink, 0); - //ensure directoryPf ends with backslash - const Zstring& directoryPf = endsWith(directory, FILE_NAME_SEPARATOR) ? - directory : - directory + FILE_NAME_SEPARATOR; - WIN32_FIND_DATA fileInfo = {}; + //apply daylight saving time hack AFTER file traversing, to give separate feedback to user + if (dstCallback && isFatFileSystem) + applyDstHack(*dstCallback); + } - HANDLE searchHandle = INVALID_HANDLE_VALUE; - tryReportingError([&](std::wstring& errorMsg) -> bool +private: + DirTraverser(const DirTraverser&); + DirTraverser& operator=(const DirTraverser&); + + template <class Trav> + void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level) + { + tryReportingError([&] { - searchHandle = ::FindFirstFile(applyLongPathPrefix(directoryPf + L'*').c_str(), &fileInfo); - //no noticable performance difference compared to FindFirstFileEx with FindExInfoBasic, FIND_FIRST_EX_CASE_SENSITIVE and/or FIND_FIRST_EX_LARGE_FETCH + if (level == 100) //notify endless recursion + throw FileError(_("Endless loop when traversing directory:") + L"\n\"" + directory + L"\""); + }, sink); - if (searchHandle == INVALID_HANDLE_VALUE) - { - //const DWORD lastError = ::GetLastError(); - //if (lastError == ERROR_FILE_NOT_FOUND) -> actually NOT okay, even for an empty directory this should not occur (., ..) - //return true; //fine: empty directory + typename Trav::FindData fileInfo = {}; - //else: we have a problem... report it: - errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); - return false; - } - return true; + typename Trav::Handle searchHandle = 0; + + tryReportingError([&] + { + typedef Trav Trav; //f u VS! + searchHandle = Trav::create(directory, fileInfo); //throw FileError }, sink); - if (searchHandle == INVALID_HANDLE_VALUE) - return; //empty dir or ignore error - ZEN_ON_BLOCK_EXIT(::FindClose(searchHandle)); + if (searchHandle == 0) + return; //ignored error + ZEN_ON_BLOCK_EXIT(typedef Trav Trav; Trav::destroy(searchHandle)); do { //don't return "." and ".." - const Zchar* const shortName = fileInfo.cFileName; + const Zchar* const shortName = Trav::getShortName(fileInfo); if (shortName[0] == L'.' && (shortName[1] == L'\0' || (shortName[1] == L'.' && shortName[2] == L'\0'))) continue; - const Zstring& fullName = directoryPf + shortName; - - const bool isSymbolicLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ? + directory + shortName : + directory + FILE_NAME_SEPARATOR + shortName; - if (isSymbolicLink && !followSymlinks_) //evaluate symlink directly + if (Trav::isSymlink(fileInfo) && !followSymlinks_) //evaluate symlink directly { TraverseCallback::SymlinkInfo details; try { details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError } - catch (FileError& e) - { - (void)e; -#ifndef NDEBUG //show broken symlink / access errors in debug build! - sink.onError(e.toString()); +#ifdef NDEBUG //Release + catch (FileError&) {} +#else + catch (FileError& e) { sink.onError(e.toString()); } //show broken symlink / access errors in debug build! #endif - } - details.lastWriteTimeRaw = toTimeT(fileInfo.ftLastWriteTime); - details.dirLink = (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; //directory symlinks have this flag on Windows + details.lastWriteTimeRaw = Trav::getModTime (fileInfo); + details.dirLink = Trav::isDirectory(fileInfo); //directory symlinks have this flag on Windows sink.onSymlink(shortName, fullName, details); } - else if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!) + else if (Trav::isDirectory(fileInfo)) //a directory... or symlink that needs to be followed (for directory symlinks this flag is set too!) { const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName); if (rv) - traverse(fullName, *rv, level + 1); + traverse<Trav>(fullName, *rv, level + 1); } else //a file or symlink that is followed... { TraverseCallback::FileInfo details; - if (isSymbolicLink) //dereference symlinks! + if (Trav::isSymlink(fileInfo)) //dereference symlinks! { - if (!setWin32FileInformationFromSymlink(fullName, details)) - { - //broken symlink... - details.lastWriteTimeRaw = 0; //we are not interested in the modification time of the link - details.fileSize = 0U; - } + extractFileInfoFromSymlink(fullName, details); //try to... + //keep details initial if symlink is broken } else { + Trav::extractFileInfo(fileInfo, volumeSerial != 0 ? &volumeSerial : nullptr, details); //make optional character of volumeSerial explicit in the interface + //####################################### DST hack ########################################### if (isFatFileSystem) { - const dst::RawTime rawTime(fileInfo.ftCreationTime, fileInfo.ftLastWriteTime); + const dst::RawTime rawTime(Trav::getCreateTimeRaw(fileInfo), Trav::getModTimeRaw(fileInfo)); if (dst::fatHasUtcEncoded(rawTime)) //throw (std::runtime_error) - fileInfo.ftLastWriteTime = dst::fatDecodeUtcTime(rawTime); //return real UTC time; throw (std::runtime_error) + details.lastWriteTimeRaw = toTimeT(dst::fatDecodeUtcTime(rawTime)); //return real UTC time; throw (std::runtime_error) else - markForDstHack.push_back(std::make_pair(fullName, fileInfo.ftLastWriteTime)); + markForDstHack.push_back(std::make_pair(fullName, Trav::getModTimeRaw(fileInfo))); } //####################################### DST hack ########################################### - details.lastWriteTimeRaw = toTimeT(fileInfo.ftLastWriteTime); - details.fileSize = zen::UInt64(fileInfo.nFileSizeLow, fileInfo.nFileSizeHigh); } sink.onFile(shortName, fullName, details); @@ -366,141 +387,18 @@ private: { bool moreData = false; - tryReportingError([&](std::wstring& errorMsg) -> bool + typedef Trav Trav1; //f u VS! + tryReportingError([&] { - if (!::FindNextFile(searchHandle, // handle to search - &fileInfo)) // pointer to structure for data on found file - { - if (::GetLastError() == ERROR_NO_MORE_FILES) //this is fine - return true; - - //else we have a problem... report it: - errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); - return false; - } - - moreData = true; - return true; + typedef Trav1 Trav; //f u VS! + moreData = Trav::next(searchHandle, directory, fileInfo); //throw FileError }, sink); return moreData; }()); - -#elif defined FFS_LINUX - DIR* dirObj = NULL; - if (!tryReportingError([&](std::wstring& errorMsg) -> bool - { - dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/" - if (dirObj == NULL) - { - errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); - return false; - } - return true; - }, sink)) - return; - ZEN_ON_BLOCK_EXIT(::closedir(dirObj)); //never close NULL handles! -> crash - - while (true) - { - struct dirent* dirEntry = NULL; - tryReportingError([&](std::wstring& errorMsg) -> bool - { - errno = 0; //set errno to 0 as unfortunately this isn't done when readdir() returns NULL because it can't find any files - dirEntry = ::readdir(dirObj); - if (dirEntry == NULL) - { - if (errno == 0) - return true; //everything okay, not more items - - //else: we have a problem... report it: - errorMsg = _("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); - return false; - } - return true; - }, sink); - if (dirEntry == NULL) //no more items or ignore error - return; - - - //don't return "." and ".." - const char* const shortName = dirEntry->d_name; - if (shortName[0] == '.' && - (shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0'))) - continue; - - const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ? //e.g. "/" - directory + shortName : - directory + FILE_NAME_SEPARATOR + shortName; - - struct stat fileInfo = {}; - - if (!tryReportingError([&](std::wstring& errorMsg) -> bool - { - if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks - { - errorMsg = _("Error reading file attributes:") + L"\n\"" + fullName + L"\"" + L"\n\n" + zen::getLastErrorFormatted(); - return false; - } - return true; - }, sink)) - continue; //ignore error: skip file - - const bool isSymbolicLink = S_ISLNK(fileInfo.st_mode); - - if (isSymbolicLink) - { - if (followSymlinks_) //on Linux Symlinks need to be followed to evaluate whether they point to a file or directory - { - if (::stat(fullName.c_str(), &fileInfo) != 0) //stat() resolves symlinks - { - sink.onFile(shortName, fullName, TraverseCallback::FileInfo()); //report broken symlink as file! - continue; - } - } - else //evaluate symlink directly - { - TraverseCallback::SymlinkInfo details; - try - { - details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError - } - catch (FileError& e) - { -#ifndef NDEBUG //show broken symlink / access errors in debug build! - sink.onError(e.toString()); -#endif - } - - details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second - details.dirLink = ::stat(fullName.c_str(), &fileInfo) == 0 && S_ISDIR(fileInfo.st_mode); //S_ISDIR and S_ISLNK are mutually exclusive on Linux => need to follow link - sink.onSymlink(shortName, fullName, details); - continue; - } - } - - //fileInfo contains dereferenced data in any case from here on - - if (S_ISDIR(fileInfo.st_mode)) //a directory... cannot be a symlink on Linux in this case - { - const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName); - if (rv) - traverse(fullName, *rv, level + 1); - } - else //a file... (or symlink; pathological!) - { - TraverseCallback::FileInfo details; - details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second - details.fileSize = zen::UInt64(fileInfo.st_size); - - sink.onFile(shortName, fullName, details); - } - } -#endif } -#ifdef FFS_WIN //####################################### DST hack ########################################### void applyDstHack(zen::DstHackCallback& dstCallback) { @@ -517,7 +415,7 @@ private: const dst::RawTime encodedTime = dst::fatEncodeUtcTime(i->second); //throw (std::runtime_error) { //may need to remove the readonly-attribute (e.g. FAT usb drives) - FileUpdateHandle updateHandle(i->first, [ = ]() + FileUpdateHandle updateHandle(i->first, [=]() { return ::CreateFile(zen::applyLongPathPrefix(i->first).c_str(), GENERIC_READ | GENERIC_WRITE, //use both when writing over network, see comment in file_io.cpp @@ -571,20 +469,167 @@ private: typedef std::vector<std::pair<Zstring, FILETIME> > FilenameTimeList; FilenameTimeList markForDstHack; //####################################### DST hack ########################################### -#endif + const bool followSymlinks_; + const DWORD volumeSerial; //may be 0! }; -void zen::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback& sink, DstHackCallback* dstCallback) +#elif defined FFS_LINUX +class DirTraverser { -#ifdef FFS_WIN - try //traversing certain folders with restricted permissions requires this privilege! (but copying these files may still fail) +public: + DirTraverser(const Zstring& baseDirectory, bool followSymlinks, zen::TraverseCallback& sink, zen::DstHackCallback* dstCallback) : + followSymlinks_(followSymlinks) { - zen::Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError + const Zstring directoryFormatted = //remove trailing slash + baseDirectory.size() > 1 && endsWith(baseDirectory, FILE_NAME_SEPARATOR) ? //exception: allow '/' + beforeLast(baseDirectory, FILE_NAME_SEPARATOR) : + baseDirectory; + + /* quote: "Since POSIX.1 does not specify the size of the d_name field, and other nonstandard fields may precede + that field within the dirent structure, portable applications that use readdir_r() should allocate + the buffer whose address is passed in entry as follows: + len = offsetof(struct dirent, d_name) + pathconf(dirpath, _PC_NAME_MAX) + 1 + entryp = malloc(len); */ + const long maxPath = std::max<long>(::pathconf(directoryFormatted.c_str(), _PC_NAME_MAX), 10000); //::pathconf may return -1 + buffer.resize(offsetof(struct ::dirent, d_name) + maxPath + 1); + + traverse(directoryFormatted, sink, 0); } - catch (...) {} //don't cause issues in user mode + +private: + DirTraverser(const DirTraverser&); + DirTraverser& operator=(const DirTraverser&); + + void traverse(const Zstring& directory, zen::TraverseCallback& sink, int level) + { + tryReportingError([&] + { + if (level == 100) //notify endless recursion + throw FileError(_("Endless loop when traversing directory:") + L"\n\"" + directory + L"\""); + }, sink); + + + DIR* dirObj = NULL; + tryReportingError([&] + { + dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/" + if (dirObj == NULL) + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + }, sink); + + if (dirObj == NULL) + return; //ignored error + ZEN_ON_BLOCK_EXIT(::closedir(dirObj)); //never close NULL handles! -> crash + + while (true) + { + struct ::dirent* dirEntry = NULL; + tryReportingError([&] + { + if (::readdir_r(dirObj, reinterpret_cast< ::dirent*>(&buffer[0]), &dirEntry) != 0) + throw FileError(_("Error traversing directory:") + L"\n\"" + directory + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + }, sink); + if (dirEntry == NULL) //no more items or ignore error + return; + + + //don't return "." and ".." + const char* const shortName = dirEntry->d_name; //evaluate dirEntry *before* going into recursion => we use a single "buffer"! + if (shortName[0] == '.' && + (shortName[1] == '\0' || (shortName[1] == '.' && shortName[2] == '\0'))) + continue; + + const Zstring& fullName = endsWith(directory, FILE_NAME_SEPARATOR) ? //e.g. "/" + directory + shortName : + directory + FILE_NAME_SEPARATOR + shortName; + + struct ::stat fileInfo = {}; + bool haveData = false; + tryReportingError([&] + { + if (::lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks + throw FileError(_("Error reading file attributes:") + L"\n\"" + fullName + L"\"" + L"\n\n" + zen::getLastErrorFormatted()); + haveData = true; + }, sink); + if (!haveData) + continue; //ignore error: skip file + + if (S_ISLNK(fileInfo.st_mode)) + { + if (followSymlinks_) //on Linux Symlinks need to be followed to evaluate whether they point to a file or directory + { + if (::stat(fullName.c_str(), &fileInfo) != 0) //stat() resolves symlinks + { + sink.onFile(shortName, fullName, TraverseCallback::FileInfo()); //report broken symlink as file! + continue; + } + + fileInfo.st_dev = 0; //id from dereferenced symlink is problematic, since renaming will consider the link, not the target! + fileInfo.st_ino = 0; // + } + else //evaluate symlink directly + { + TraverseCallback::SymlinkInfo details; + try + { + details.targetPath = getSymlinkRawTargetString(fullName); //throw FileError + } + catch (FileError& e) + { +#ifndef NDEBUG //show broken symlink / access errors in debug build! + sink.onError(e.toString()); #endif + } + + details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second + details.dirLink = ::stat(fullName.c_str(), &fileInfo) == 0 && S_ISDIR(fileInfo.st_mode); + //S_ISDIR and S_ISLNK are mutually exclusive on Linux => explicitly need to follow link + sink.onSymlink(shortName, fullName, details); + continue; + } + } + + //fileInfo contains dereferenced data in any case from here on + + if (S_ISDIR(fileInfo.st_mode)) //a directory... cannot be a symlink on Linux in this case + { + const std::shared_ptr<TraverseCallback> rv = sink.onDir(shortName, fullName); + if (rv) + traverse(fullName, *rv, level + 1); + } + else //a file... (or symlink; pathological!) + { + TraverseCallback::FileInfo details; + details.fileSize = zen::UInt64(fileInfo.st_size); + details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time (time_t format); unit: 1 second + details.id = extractFileID(fileInfo); + + sink.onFile(shortName, fullName, details); + } + } + } + std::vector<char> buffer; + const bool followSymlinks_; +}; +#endif +} + + +void zen::traverseFolder(const Zstring& directory, bool followSymlinks, TraverseCallback& sink, DstHackCallback* dstCallback) +{ DirTraverser(directory, followSymlinks, sink, dstCallback); } + + +bool zen::supportForFileId() //Linux: always; Windows: if FindFilePlus_Win32.dll was loaded correctly +{ +#ifdef FFS_WIN + return ::openDir && ::readDir && ::closeDir; + +#elif defined FFS_LINUX + return true; +#endif +} diff --git a/zen/file_traverser.h b/zen/file_traverser.h index 3f4f47d5..075c32e5 100644 --- a/zen/file_traverser.h +++ b/zen/file_traverser.h @@ -10,6 +10,8 @@ #include <memory> #include "zstring.h" #include "int64.h" +#include "file_id_def.h" + //advanced file traverser returning metadata and hierarchical information on files and directories @@ -24,6 +26,7 @@ public: { UInt64 fileSize; //unit: bytes! Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC + FileId id; //optional: may be initial! }; struct SymlinkInfo @@ -67,6 +70,10 @@ void traverseFolder(const Zstring& directory, //throw(); //followSymlinks: //"true": Symlinks dereferenced and reported via onFile() and onDir() => onSymlink not used! //"false": Symlinks directly reported via onSymlink(), directory symlinks are not followed + + +//determine whether FileId can be expected to be retrieved +bool supportForFileId(); //Linux: always; Windows: if FindFilePlus_Win32.dll was loaded correctly } #endif // FILETRAVERSER_H_INCLUDED @@ -10,7 +10,7 @@ #include <string> #include <boost/uuid/uuid.hpp> -#ifdef __MINGW32__ //boost should start and clean up! +#ifdef __MINGW32__ //boost should start cleaning this mess up #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wuninitialized" diff --git a/zen/int64.h b/zen/int64.h index e8a9cbe0..91e24437 100644 --- a/zen/int64.h +++ b/zen/int64.h @@ -56,7 +56,7 @@ public: value(rhs) {} //-> std::int64_t equals long int on x64 Linux! Still we want implicit behavior for all other systems! //unsafe explicit but checked conversion from arbitrary integer type - template <class T> explicit Int64(T rhs) : value(rhs) { checkRange<std::int64_t>(rhs); } + template <class T> explicit Int64(T rhs) : value(static_cast<std::int64_t>(rhs)) { checkRange<std::int64_t>(rhs); } Int64& operator=(const Int64& rhs) { value = rhs.value; return *this; } @@ -135,7 +135,7 @@ public: value(rhs) {} //-> std::uint64_t equals unsigned long int on x64 Linux! Still we want implicit behavior for all other systems! //unsafe explicit but checked conversion from arbitrary integer type - template <class T> explicit UInt64(T rhs) : value(rhs) { checkRange<std::uint64_t>(rhs); } + template <class T> explicit UInt64(T rhs) : value(static_cast<std::uint64_t>(rhs)) { checkRange<std::uint64_t>(rhs); } UInt64& operator=(const UInt64& rhs) { value = rhs.value; return *this; } diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h index 1d9213d1..d03409e1 100644 --- a/zen/long_path_prefix.h +++ b/zen/long_path_prefix.h @@ -7,6 +7,7 @@ #ifndef LONGPATHPREFIX_H_INCLUDED #define LONGPATHPREFIX_H_INCLUDED +#include "win.h" #include "zstring.h" namespace zen diff --git a/zen/notify_removal.cpp b/zen/notify_removal.cpp index 8d8eeb90..2b6b9003 100644 --- a/zen/notify_removal.cpp +++ b/zen/notify_removal.cpp @@ -74,11 +74,10 @@ private: const wchar_t MessageProvider::WINDOW_NAME[] = L"E6AD5EB1-527B-4EEF-AC75-27883B233380"; //random name -LRESULT CALLBACK topWndProc( - HWND hwnd, //handle to window - UINT uMsg, //message identifier - WPARAM wParam, //first message parameter - LPARAM lParam) //second message parameter +LRESULT CALLBACK topWndProc(HWND hwnd, //handle to window + UINT uMsg, //message identifier + WPARAM wParam, //first message parameter + LPARAM lParam) //second message parameter { if (messageProviderConstructed) //attention: this callback is triggered in the middle of singleton construction! It is a bad idea to to call back at this time! try @@ -110,18 +109,17 @@ MessageProvider::MessageProvider() : zen::ScopeGuard guardClass = zen::makeGuard([&]() { ::UnregisterClass(WINDOW_NAME, process); }); //create dummy-window - windowHandle = ::CreateWindow( - WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word! - NULL, //LPCTSTR lpWindowName, - 0, //DWORD dwStyle, - 0, //int x, - 0, //int y, - 0, //int nWidth, - 0, //int nHeight, - 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)! - NULL, //HMENU hMenu, - process, //HINSTANCE hInstance, - NULL); //LPVOID lpParam + windowHandle = ::CreateWindow(WINDOW_NAME, //LPCTSTR lpClassName OR ATOM in low-order word! + NULL, //LPCTSTR lpWindowName, + 0, //DWORD dwStyle, + 0, //int x, + 0, //int y, + 0, //int nWidth, + 0, //int nHeight, + 0, //note: we need a toplevel window to receive device arrival events, not a message-window (HWND_MESSAGE)! + NULL, //HMENU hMenu, + process, //HINSTANCE hInstance, + NULL); //LPVOID lpParam if (windowHandle == NULL) throw zen::FileError(std::wstring(L"Could not start monitoring window notifications:") + L"\n\n" + getLastErrorFormatted() + L" (CreateWindow)"); @@ -160,17 +158,16 @@ public: filter.dbch_devicetype = DBT_DEVTYP_HANDLE; filter.dbch_handle = hDir; - hNotification = ::RegisterDeviceNotification( - MessageProvider::instance().getWnd(), //__in HANDLE hRecipient, - &filter, //__in LPVOID NotificationFilter, - DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags + hNotification = ::RegisterDeviceNotification(MessageProvider::instance().getWnd(), //__in HANDLE hRecipient, + &filter, //__in LPVOID NotificationFilter, + DEVICE_NOTIFY_WINDOW_HANDLE); //__in DWORD Flags if (hNotification == NULL) { const DWORD lastError = ::GetLastError(); if (lastError != ERROR_CALL_NOT_IMPLEMENTED && //fail on SAMBA share: this shouldn't be a showstopper! lastError != ERROR_SERVICE_SPECIFIC_ERROR && //neither should be fail for "Pogoplug" mapped network drives lastError != ERROR_INVALID_DATA) //this seems to happen for a NetDrive-mapped FTP server - throw zen::FileError(std::wstring(L"Could not register device removal notifications:") + L"\n\n" + getLastErrorFormatted(lastError)); + throw zen::FileError(L"Could not register device removal notifications:" L"\n\n" + getLastErrorFormatted(lastError)); } } diff --git a/zen/privilege.cpp b/zen/privilege.cpp index 809202b7..6dd0b2d7 100644 --- a/zen/privilege.cpp +++ b/zen/privilege.cpp @@ -1,17 +1,15 @@ #include "privilege.h" +#include <map> +#include "thread.h" //includes <boost/thread.hpp> +#include "zstring.h" #include "scope_guard.h" using namespace zen; -Privileges& Privileges::getInstance() +namespace { - static Privileges instance; - return instance; -} - - -bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw FileError +bool privilegeIsActive(LPCTSTR privilege) //throw FileError { HANDLE hToken = NULL; if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, @@ -42,7 +40,7 @@ bool Privileges::privilegeIsActive(LPCTSTR privilege) //throw FileError } -void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw FileError +void setPrivilege(LPCTSTR privilege, bool enable) //throw FileError { HANDLE hToken = NULL; if (!::OpenProcessToken(::GetCurrentProcess(), //__in HANDLE ProcessHandle, @@ -62,15 +60,67 @@ void Privileges::setPrivilege(LPCTSTR privilege, bool enable) //throw FileError tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - if (!::AdjustTokenPrivileges( - hToken, //__in HANDLE TokenHandle, - false, //__in BOOL DisableAllPrivileges, - &tp, //__in_opt PTOKEN_PRIVILEGES NewState, - 0, //__in DWORD BufferLength, - NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState, - NULL)) //__out_opt PDWORD ReturnLength + if (!::AdjustTokenPrivileges(hToken, //__in HANDLE TokenHandle, + false, //__in BOOL DisableAllPrivileges, + &tp, //__in_opt PTOKEN_PRIVILEGES NewState, + 0, //__in DWORD BufferLength, + NULL, //__out_opt PTOKEN_PRIVILEGES PreviousState, + NULL)) //__out_opt PDWORD ReturnLength throw FileError(_("Error setting privilege:") + L" \"" + privilege + L"\"" + L"\n\n" + getLastErrorFormatted()); if (::GetLastError() == ERROR_NOT_ALL_ASSIGNED) //check although previous function returned with success! throw FileError(_("Error setting privilege:") + L" \"" + privilege + L"\"" + L"\n\n" + getLastErrorFormatted()); } + + +class Privileges +{ +public: + static Privileges& getInstance() + { + static Privileges inst; + return inst; + } + + void ensureActive(LPCTSTR privilege) //throw FileError + { + if (activePrivileges.find(privilege) != activePrivileges.end()) + return; //privilege already active + + if (privilegeIsActive(privilege)) //privilege was already active before starting this tool + activePrivileges.insert(std::make_pair(privilege, false)); + else + { + setPrivilege(privilege, true); + activePrivileges.insert(std::make_pair(privilege, true)); + } + } + +private: + Privileges() {} + Privileges(Privileges&); + void operator=(Privileges&); + + ~Privileges() //clean up: deactivate all privileges that have been activated by this application + { + for (auto iter = activePrivileges.begin(); iter != activePrivileges.end(); ++iter) + if (iter->second) + try + { + setPrivilege(iter->first.c_str(), false); + } + catch (...) {} + } + + std::map<Zstring, bool> activePrivileges; //bool: enabled by this application +}; + +boost::mutex lockPrivileges; +} + + +void zen::activatePrivilege(LPCTSTR privilege) //throw FileError +{ + boost::lock_guard<boost::mutex> dummy(lockPrivileges); + Privileges::getInstance().ensureActive(privilege); +} diff --git a/zen/privilege.h b/zen/privilege.h index 4545aac7..88fc8992 100644 --- a/zen/privilege.h +++ b/zen/privilege.h @@ -7,57 +7,12 @@ #ifndef PRIVILEGE_H_INCLUDED #define PRIVILEGE_H_INCLUDED -#include <map> -#include "zstring.h" #include "file_error.h" #include "win.h" //includes "windows.h" namespace zen { -#ifdef FFS_WIN -class Privileges -{ -public: - static Privileges& getInstance(); - - void ensureActive(LPCTSTR privilege) //throw FileError - { - if (activePrivileges.find(privilege) != activePrivileges.end()) - return; //privilege already active - - if (privilegeIsActive(privilege)) //privilege was already active before starting this tool - activePrivileges.insert(std::make_pair(privilege, false)); - else - { - setPrivilege(privilege, true); - activePrivileges.insert(std::make_pair(privilege, true)); - } - } - -private: - Privileges() {} - Privileges(Privileges&); - void operator=(Privileges&); - - ~Privileges() //clean up: deactivate all privileges that have been activated by this application - { - for (PrivBuffType::const_iterator i = activePrivileges.begin(); i != activePrivileges.end(); ++i) - try - { - if (i->second) - Privileges::setPrivilege(i->first.c_str(), false); - } - catch (...) {} - } - - static bool privilegeIsActive(LPCTSTR privilege); //throw FileError - static void setPrivilege(LPCTSTR privilege, bool enable); //throw FileError - - typedef std::map<Zstring, bool> PrivBuffType; //bool: enabled by this application - - PrivBuffType activePrivileges; -}; -#endif +void activatePrivilege(LPCTSTR privilege); //throw FileError; thread-safe!!! } diff --git a/zen/process_status.h b/zen/process_status.h index cc5825aa..15266b28 100644 --- a/zen/process_status.h +++ b/zen/process_status.h @@ -3,29 +3,55 @@ #ifdef FFS_WIN #include "win.h" //includes "windows.h" + +#elif defined FFS_LINUX #endif namespace zen { -struct DisableStandby //signal a "busy" state to the operating system +struct PreventStandby //signal a "busy" state to the operating system { #ifdef FFS_WIN - DisableStandby() { ::SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED /* | ES_AWAYMODE_REQUIRED*/ ); } - ~DisableStandby() { ::SetThreadExecutionState(ES_CONTINUOUS); } + PreventStandby() { ::SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED /* | ES_AWAYMODE_REQUIRED*/ ); } + ~PreventStandby() { ::SetThreadExecutionState(ES_CONTINUOUS); } #endif }; +struct ScheduleForBackgroundProcessing //lower CPU and file I/O priorities +{ +#ifdef FFS_WIN #ifndef PROCESS_MODE_BACKGROUND_BEGIN #define PROCESS_MODE_BACKGROUND_BEGIN 0x00100000 // Windows Server 2003 and Windows XP/2000: This value is not supported! #define PROCESS_MODE_BACKGROUND_END 0x00200000 // #endif -struct ScheduleForBackgroundProcessing //lower CPU and file I/O priorities -{ -#ifdef FFS_WIN - ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN); } + ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN); } //this call lowers CPU priority, too!! ~ScheduleForBackgroundProcessing() { ::SetPriorityClass(::GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END); } + +#elif defined FFS_LINUX + /* + CPU prio: + int getpriority(PRIO_PROCESS, 0); - errno caveat! + int ::setpriority(PRIO_PROCESS, 0, int prio); //a zero value for "who" denotes the calling process + + priority can be decreased, but NOT increased :( + + file I/O prio: + ScheduleForBackgroundProcessing() : oldIoPrio(::ioprio_get(IOPRIO_WHO_PROCESS, ::getpid())) + { + if (oldIoPrio != -1) + ::ioprio_set(IOPRIO_WHO_PROCESS, ::getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); + } + ~ScheduleForBackgroundProcessing() + { + if (oldIoPrio != -1) + ::ioprio_set(IOPRIO_WHO_PROCESS, ::getpid(), oldIoPrio); + } + + private: + const int oldIoPrio; + */ #endif }; } diff --git a/zen/stl_tools.h b/zen/stl_tools.h index 1707a1eb..96101821 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -28,11 +28,11 @@ void map_remove_if(M& map, Predicate p); template <class ForwardIterator, class T, typename Compare> ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp); -template<class BidirectionalIterator, class T> +template <class BidirectionalIterator, class T> BidirectionalIterator find_last(BidirectionalIterator first, BidirectionalIterator last, const T& value); //replacement for std::find_end taking advantage of bidirectional iterators (and giving the algorithm a reasonable name) -template<class BidirectionalIterator1, class BidirectionalIterator2> +template <class BidirectionalIterator1, class BidirectionalIterator2> BidirectionalIterator1 search_last(BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIterator2 first2, BidirectionalIterator2 last2); @@ -96,45 +96,47 @@ ForwardIterator binary_search(ForwardIterator first, ForwardIterator last, const } -template<class BidirectionalIterator, class T> inline +template <class BidirectionalIterator, class T> inline BidirectionalIterator find_last(const BidirectionalIterator first, BidirectionalIterator last, const T& value) { + //reverse iteration: 1. check 2. decrement 3. evaluate const BidirectionalIterator iterNotFound = last; - do + for (;;) //VS 2010 doesn't like "while (true)" { if (last == first) return iterNotFound; --last; + + if (*last == value) + return last; } - while (!(*last == value)); //loop over "last": 1. check 2. decrement 3. evaluate - return last; } -template<class BidirectionalIterator1, class BidirectionalIterator2> inline +template <class BidirectionalIterator1, class BidirectionalIterator2> inline BidirectionalIterator1 search_last(const BidirectionalIterator1 first1, BidirectionalIterator1 last1, const BidirectionalIterator2 first2, BidirectionalIterator2 last2) { - if (first1 == last1 || - first2 == last2) - return last1; - - int diff = static_cast<int>(std::distance(first1, last1)) - - static_cast<int>(std::distance(first2, last2)); - const BidirectionalIterator1 iterNotFound = last1; - --last2; - while (diff-- >= 0) //loop over "last1": 1. check 2. decrement 3. evaluate + //reverse iteration: 1. check 2. decrement 3. evaluate + for (;;) { - --last1; + BidirectionalIterator1 it1 = last1; + BidirectionalIterator2 it2 = last2; - BidirectionalIterator1 iter1 = last1; - for (BidirectionalIterator2 iter2 = last2; *iter1 == *iter2; --iter1, --iter2) - if (iter2 == first2) - return iter1; + for (;;) + { + if (it2 == first2) return it1; + if (it1 == first1) return iterNotFound; + + --it1; + --it2; + + if (*it1 != *it2) break; + } + --last1; } - return iterNotFound; } } diff --git a/zen/symlink_target.h b/zen/symlink_target.h index 370a0c56..dfbbba6d 100644 --- a/zen/symlink_target.h +++ b/zen/symlink_target.h @@ -66,7 +66,7 @@ Zstring getSymlinkRawTargetString(const Zstring& linkPath) //throw FileError try //reading certain symlinks/junctions requires admin rights! This shall not cause an error in user mode! { - Privileges::getInstance().ensureActive(SE_BACKUP_NAME); //throw FileError + activatePrivilege(SE_BACKUP_NAME); //throw FileError } catch (...) {} @@ -175,7 +175,10 @@ String formatTime(const String2& format, const TimeComp& comp, UserDefinedFormat { typedef typename GetCharType<String>::Result CharType; - const struct std::tm& ctc = toClibTimeComponents(comp); + struct std::tm ctc = toClibTimeComponents(comp); + std::mktime (&ctc); // unfortunately std::strftime() needs all elements of "struct tm" filled, e.g. tm_wday, tm_yday + //note: although std::mktime() explicitly expects "local time", calculating weekday and day of year *should* be time-zone and DST independent + CharType buffer[256]; const size_t charsWritten = strftimeWrap(buffer, 256, strBegin(format), &ctc); return String(buffer, charsWritten); |