From 19eb73ff543c81c6886725a20dea0060cb0c0c26 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 2 Oct 2015 14:56:27 +0200 Subject: 7.3 --- FreeFileSync/Build/Changelog.txt | 20 +- FreeFileSync/Build/Help/html/Tips and Tricks.html | 10 +- .../Build/Help/images/copy_alternative_path.png | Bin 0 -> 4195 bytes FreeFileSync/Build/Help/images/two_folder_drop.png | Bin 0 -> 13318 bytes FreeFileSync/Build/Languages/arabic.lng | 1768 ------------------- .../Build/Languages/chinese_traditional.lng | 3 + FreeFileSync/Build/Languages/english_uk.lng | 60 +- FreeFileSync/Build/Languages/german.lng | 75 +- FreeFileSync/Build/Languages/italian.lng | 106 +- FreeFileSync/Build/Languages/norwegian.lng | 1713 ------------------- FreeFileSync/Build/Languages/outdated/arabic.lng | 1790 ++++++++++++++++++++ .../Build/Languages/outdated/norwegian.lng | 1713 +++++++++++++++++++ .../Build/Languages/outdated/portuguese.lng | 1716 +++++++++++++++++++ FreeFileSync/Build/Languages/portuguese.lng | 1716 ------------------- FreeFileSync/Build/Languages/turkish.lng | 385 +++-- FreeFileSync/Build/Resources.zip | Bin 288512 -> 288163 bytes FreeFileSync/Source/RealtimeSync/application.cpp | 16 - .../Source/RealtimeSync/folder_selector2.cpp | 61 +- .../Source/RealtimeSync/folder_selector2.h | 16 +- FreeFileSync/Source/RealtimeSync/main_dlg.cpp | 14 +- FreeFileSync/Source/RealtimeSync/monitor.cpp | 74 +- FreeFileSync/Source/RealtimeSync/monitor.h | 2 +- FreeFileSync/Source/RealtimeSync/tray_menu.cpp | 2 +- FreeFileSync/Source/RealtimeSync/xml_proc.cpp | 12 +- FreeFileSync/Source/algorithm.cpp | 422 +++-- FreeFileSync/Source/algorithm.h | 29 +- FreeFileSync/Source/application.cpp | 25 +- FreeFileSync/Source/comparison.cpp | 10 +- FreeFileSync/Source/comparison.h | 12 +- FreeFileSync/Source/file_hierarchy.h | 3 - FreeFileSync/Source/fs/abstract.cpp | 12 +- FreeFileSync/Source/fs/abstract.h | 24 +- FreeFileSync/Source/fs/native.cpp | 70 +- FreeFileSync/Source/lib/binary.cpp | 23 +- FreeFileSync/Source/lib/cmp_filetime.h | 12 +- FreeFileSync/Source/lib/db_file.cpp | 9 +- FreeFileSync/Source/lib/dir_exist_async.h | 65 +- FreeFileSync/Source/lib/dir_lock.cpp | 29 +- FreeFileSync/Source/lib/dir_lock.h | 2 +- FreeFileSync/Source/lib/generate_logfile.h | 1 - FreeFileSync/Source/lib/hard_filter.cpp | 8 - FreeFileSync/Source/lib/icon_buffer.cpp | 62 +- FreeFileSync/Source/lib/icon_holder.h | 18 +- FreeFileSync/Source/lib/parallel_scan.cpp | 84 +- FreeFileSync/Source/lib/parallel_scan.h | 2 +- FreeFileSync/Source/lib/parse_lng.h | 2 +- FreeFileSync/Source/lib/process_xml.cpp | 37 +- FreeFileSync/Source/lib/process_xml.h | 114 +- FreeFileSync/Source/lib/resolve_path.cpp | 20 +- FreeFileSync/Source/lib/resolve_path.h | 4 +- FreeFileSync/Source/lib/status_handler.h | 2 +- FreeFileSync/Source/lib/status_handler_impl.h | 16 +- FreeFileSync/Source/lib/versioning.cpp | 32 +- FreeFileSync/Source/structures.cpp | 4 +- FreeFileSync/Source/structures.h | 18 +- FreeFileSync/Source/synchronization.cpp | 9 +- FreeFileSync/Source/ui/batch_config.cpp | 2 +- FreeFileSync/Source/ui/batch_status_handler.cpp | 8 +- FreeFileSync/Source/ui/batch_status_handler.h | 2 - FreeFileSync/Source/ui/check_version.cpp | 4 +- FreeFileSync/Source/ui/custom_grid.cpp | 38 +- FreeFileSync/Source/ui/folder_history_types.h | 1 - FreeFileSync/Source/ui/folder_selector.cpp | 121 +- FreeFileSync/Source/ui/folder_selector.h | 45 +- FreeFileSync/Source/ui/grid_view.cpp | 16 +- FreeFileSync/Source/ui/grid_view.h | 8 +- FreeFileSync/Source/ui/gui_generated.cpp | 215 ++- FreeFileSync/Source/ui/gui_generated.h | 48 +- FreeFileSync/Source/ui/gui_status_handler.cpp | 75 +- FreeFileSync/Source/ui/gui_status_handler.h | 32 +- FreeFileSync/Source/ui/main_dlg.cpp | 513 +++--- FreeFileSync/Source/ui/main_dlg.h | 14 +- FreeFileSync/Source/ui/on_completion_box.cpp | 2 - FreeFileSync/Source/ui/on_completion_box.h | 4 +- FreeFileSync/Source/ui/progress_indicator.cpp | 47 +- FreeFileSync/Source/ui/progress_indicator.h | 2 +- FreeFileSync/Source/ui/small_dlgs.cpp | 161 +- FreeFileSync/Source/ui/small_dlgs.h | 9 + FreeFileSync/Source/ui/sorting.h | 12 +- FreeFileSync/Source/ui/sync_cfg.cpp | 7 +- FreeFileSync/Source/ui/sync_cfg.h | 18 +- FreeFileSync/Source/ui/taskbar.cpp | 32 +- FreeFileSync/Source/ui/tree_view.h | 4 +- .../Source/ui/wx_form_build_hide_warnings.h | 22 - FreeFileSync/Source/version/version.h | 2 +- wx+/file_drop.h | 8 +- wx+/grid.cpp | 52 +- wx+/grid.h | 9 +- wx+/image_resources.cpp | 5 +- wx+/tooltip.cpp | 2 +- zen/async_task.h | 26 +- zen/dir_watcher.cpp | 41 +- zen/file_access.cpp | 31 +- zen/format_unit.cpp | 18 +- zen/guid.h | 2 +- zen/long_path_prefix.h | 1 - zen/process_priority.cpp | 1 - zen/recycler.cpp | 2 +- zen/scope_guard.h | 3 +- zen/stl_tools.h | 13 +- zen/string_base.h | 27 +- zen/string_tools.h | 6 +- zen/string_traits.h | 14 +- zen/symlink_target.h | 5 +- zen/thread.h | 285 +++- zen/zstring.cpp | 26 +- 106 files changed, 7587 insertions(+), 6906 deletions(-) create mode 100644 FreeFileSync/Build/Help/images/copy_alternative_path.png create mode 100644 FreeFileSync/Build/Help/images/two_folder_drop.png delete mode 100644 FreeFileSync/Build/Languages/arabic.lng delete mode 100644 FreeFileSync/Build/Languages/norwegian.lng create mode 100644 FreeFileSync/Build/Languages/outdated/arabic.lng create mode 100644 FreeFileSync/Build/Languages/outdated/norwegian.lng create mode 100644 FreeFileSync/Build/Languages/outdated/portuguese.lng delete mode 100644 FreeFileSync/Build/Languages/portuguese.lng delete mode 100644 FreeFileSync/Source/ui/wx_form_build_hide_warnings.h diff --git a/FreeFileSync/Build/Changelog.txt b/FreeFileSync/Build/Changelog.txt index 1b4363ae..25c8e121 100644 --- a/FreeFileSync/Build/Changelog.txt +++ b/FreeFileSync/Build/Changelog.txt @@ -1,6 +1,24 @@ +FreeFileSync 7.3 [2015-08-01] +----------------------------- +New context menu option to copy selected files to alternate folder (create diffs) +Fill a folder pair by dropping two folders at a time from Explorer +Added option to set non-standard SFTP port +Prevent recursive creation of temporary Recycle Bin directories (Windows) +Retrieve grid column label colors from the system +Fixed detection of already existing files when moving (Linux) +Follow os convention for preferences (OS X) +Prevent progress dialog from hiding behind main dialog (OS X) +Fixed config saved status not updating when changing certain settings +Support for high dpi display settings +Fixed crash when help viewer is open during exit (Windows) +Show manual deletion progress within comparison status panel +Further reduced number of file accesses during versioning +Fixed folder picker failing to select Desktop folder (Windows) + + FreeFileSync 7.2 [2015-07-01] ----------------------------- -Support synchronization with SFTP (SSH File Transfer Protocol) +Support synchronization via SFTP (SSH File Transfer Protocol) Detailed error reporting when checking folder existence Synchronize MTP devices with no modification time support Set focus to comparison button on startup diff --git a/FreeFileSync/Build/Help/html/Tips and Tricks.html b/FreeFileSync/Build/Help/html/Tips and Tricks.html index 88132bfd..0a816759 100644 --- a/FreeFileSync/Build/Help/html/Tips and Tricks.html +++ b/FreeFileSync/Build/Help/html/Tips and Tricks.html @@ -56,7 +56,15 @@ You can open a batch configuration without running it via the Windows Explorer context menu.
Explorer context menu
- + + You can drag and drop two folders at a time from Windows Explorer to fill a folder pair in one go.
+ Two-folder drop +
+ + You can copy files selected on the main dialog to an alternate folder and thereby save a "diff".
+ Copy to alternative path +
+
  • You can use a volume name instead of a drive letter.
    Drive letter by volume name diff --git a/FreeFileSync/Build/Help/images/copy_alternative_path.png b/FreeFileSync/Build/Help/images/copy_alternative_path.png new file mode 100644 index 00000000..c402f67b Binary files /dev/null and b/FreeFileSync/Build/Help/images/copy_alternative_path.png differ diff --git a/FreeFileSync/Build/Help/images/two_folder_drop.png b/FreeFileSync/Build/Help/images/two_folder_drop.png new file mode 100644 index 00000000..b71d163f Binary files /dev/null and b/FreeFileSync/Build/Help/images/two_folder_drop.png differ diff --git a/FreeFileSync/Build/Languages/arabic.lng b/FreeFileSync/Build/Languages/arabic.lng deleted file mode 100644 index c70f3237..00000000 --- a/FreeFileSync/Build/Languages/arabic.lng +++ /dev/null @@ -1,1768 +0,0 @@ -
    - العربية - MEinea - ar - flag_arabic.png - 6 - n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5 -
    - -Both sides have changed since last synchronization. -كلا الجانبين قد تغير منذ المزامنة الأخيرة. - -Cannot determine sync-direction: -لا يمكن تحديد اتجاه المزامنة: - -No change since last synchronization. -لم يطرأ أي تغيير منذ المزامنة الأخيرة. - -The database entry is not in sync considering current settings. -مدخلات قواعد البيانات غير متزامنة حسب إعدادات المزامنة الحالية. - -Setting default synchronization directions: Old files will be overwritten with newer files. -تحديد الاتجاهات الافتراضية للمزامنة: ستتم الكتابة فوق الملفات القديمة بالملفات الأحدث. - -Checking recycle bin availability for folder %x... -التحقق من توافر سلة المحذوفات من أجل المجلد %x... - -Moving file %x to the recycle bin -نقل الملف %x إلى سلة المهملات - -Moving folder %x to the recycle bin -نقل المجلد %x إلى سلة المهملات - -Moving symbolic link %x to the recycle bin -نقل الارتباط الرمزي %x إلى سلة المهملات - -Deleting file %x -حذف الملف %x - -Deleting folder %x -حذف المجلد %x - -Deleting symbolic link %x -حذف الارتباط الرمزي %x - -The recycle bin is not available for the following folders. Files will be deleted permanently instead: -سلة المهملات غير متوفرة للمجلدات التالية. سيتم حذف الملفات بشكل نهائي بدلاً عن ذلك: - -An exception occurred -حدث استثناء - -A directory path is expected after %x. -مسار متوقع بعد %x. - -Syntax error -خطأ في البنية - -Cannot find file %x. - - -File %x does not contain a valid configuration. -لا يحتوي الملف %x تكويناً صحيحاً. - -Unequal number of left and right directories specified. -لم يتم تحديد عدد متساوي من المسارات على الطرفين - -The config file must not contain settings at directory pair level when directories are set via command line. -يجب أن يحتوي ملف الخيارات الخيارات على مستوى أزواج المسارات عند تحديد المسارات بواسطة سطر الأوامر - -Directories cannot be set for more than one configuration file. -لا يمكن اختيار المسارات لأكثر من ملف خيارات واحد - -Command line -سطر الأوامر - -Syntax: -بنية: - -global config file: -ملف الخيارات العام: - -config files: -ملفات الخيارات: - -directory -مسار - -Path to an alternate GlobalSettings.xml file. -تحديد مسار مختلف لملف GlobalSettings.xml - -Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. -أي عدد من ملفات خيارات FreeFileSyn أو\و _gui and/or .ffs_batch - -Any number of alternative directory pairs for at most one config file. -أي عدد من أزواج المسارات البديلة من أجل ملف خيارات واحد - -Open configuration for editing without executing it. - - -Cannot find the following folders: -تعذر العثور على المجلدات التالية: - -You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. -بإمكانك إهمال هذا الخطأ لاعتبار كل مجلد على أنه مجلد فارغ. سيتم إنشاء المجلدات تلقائياً خلال المزامنة - -A folder input field is empty. -حقل إدخال خاص بمجلد فارغ. - -The corresponding folder will be considered as empty. -سيتم اعتبار المجلد الموافق كمجلد فارغ - -The following folder paths are dependent from each other: -مسارات المجلدات التالية معتمدة على بعضها: - -File %x has an invalid date. -يحتوي الملف %x تاريخ غير صالح. - -Date: -التاريخ: - -Files %x have the same date but a different size. -الملفات %x لها نفس التاريخ ولكن حجم مختلف. - -Size: -الحجم: - -Content comparison was skipped for excluded files %x. -تم تجاهل مقارنة المحتوى للملفات المستثناة %x. - -Items differ in attributes only -العناصر مختلفة في السمات فقط - -Resolving symbolic link %x -جاري حل المسار الرمزي %x - -Comparing content of files %x -مقارنة محتويات الملفات %x - -Generating file list... -إنشاء قائمة الملفات... - -Starting comparison -بدأ عملية المقارنة - -Calculating sync directions... -جاري حساب اتجاهات المزامنة... - -Out of memory. -نفدت الذاكرة. - -Item exists on left side only -العنصر موجود على الجانب الأيمن فقط - -Item exists on right side only -العنصر موجود في الجانب الأيسر فقط - -Left side is newer -الجانب الأيمن أحدث - -Right side is newer -الجانب الأيسر أحدث - -Items have different content -العناصر مختلفة بالمحتوى - -Both sides are equal -كلا الجانبين متماثلان - -Conflict/item cannot be categorized -الاختلاف\العنصر لا يمكن تصنيفه - -Copy new item to left -نسخ عنصر جديد إلى اليمين - -Copy new item to right -نسخ عنصر جديد إلى اليسار - -Delete left item -حذف العنصر الأيمن - -Delete right item -حذف العنصر الأيسر - -Move file on left -نقل ملف على اليمين - -Move file on right -نقل ملف على اليسار - -Update left item -تحديث العنصر اليميني - -Update right item -تحديث العنصر اليساري - -Do nothing -لا تفعل شيئا - -Update attributes on left -تحديث السمات على اليمين - -Update attributes on right -تحديث السمات على اليسار - -Cannot read file %x. -لا يمكن قراءة الملف %x. - - -Unexpected size of data stream. -Expected: %x bytes -Actual: %y bytes - - - -Cannot write permissions of %x. -لا يمكن كتابة أذونات %x. - -Operation not supported for different base folder types. - - -Cannot write file %x. -لا يمكن كتابة الملف %x. - -Cannot copy symbolic link %x to %y. -لا يمكن نسخ الرابط الرمزي من %x إلى %y - -Cannot move file %x to %y. -لا يمكن نقل الملف %x إلى %y. - -Cannot enumerate directory %x. -لا يمكن تعداد المسار %x. - -Cannot read file attributes of %x. -لا يمكن قراءة سمات الملف %x. - -Cannot find %x. - - -Cannot open file %x. -تعذر فتح الملف %x. - -Cannot delete directory %x. -لا يمكن حذف المسار %x. - -Cannot delete file %x. -لا يمكن حذف الملف %x. - -Cannot find device %x. - - -Cannot determine free disk space for %x. - - -Cannot create directory %x. -لا يمكن إنشاء المسار %x. - -Cannot write modification time of %x. -لا يمكن كتابة وقت تعديل %x. - -Cannot determine final path for %x. -تعذر تحديد المسار النهائي لـ %x. - -Cannot resolve symbolic link %x. -لا يمكن حل الارتباط الرمزي %x. - -Unable to move %x to the recycle bin. -تعذر نقل %x إلى سلة المحذوفات. - -Cannot open directory %x. -لا يمكن فتح المسار %x. - -Incorrect command line: -سطر أوامر خاطئ: - -Error Code %x: -خطأ رقم %x: - -Failed to connect to SFTP server %x. - - - -1 byte -%x bytes - - -0 byte -1 byte -2 bytes -%x bytes -%x bytes -%x bytes - - -%x MB -%x MB - -%x KB -%x KB - -%x GB -%x GB - -Cannot load file %x. -لا يمكن فتح الملف %x. - -Database file %x is incompatible. -ملف قاعدة البيانات %x غير متوافق. - -Initial synchronization: -المزامنة الأولية: - -Database file %x does not yet exist. -ملف قاعدة البيانات %x غير موجود حتى الآن. - -Database file is corrupt: -ملف قاعدة البيانات معطوب: - -Database files do not share a common session. -ملفات قواعد البيانات لا تشترك في جلسة عمل مشتركة. - -Searching for folder %x... -البحث عن المجلد %x... - -Time out while searching for folder %x. - - -Cannot get process information. -لا يمكن الحصول على معلومات العملية. - -Waiting while directory is locked: -انتظر بينما يتم إنشاء قفل للمسار: - -Lock owner: -صاحب القفل: - - -1 sec -%x sec - - -0 ثانية -1 ثانية واحدة -2 ثانيتين -%x ثواني -%x ثانية -%x ثانية - - -Detecting abandoned lock... -اكتشاف قفل مهمل... - -Creating file %x -إنشاء الملف %x - -Saving file %x... -جاري حفظ الملف %x... - -Items processed: -معالجة العناصر: - -Items remaining: -العناصر المتبقية: - -Total time: -مجموع الوقت: - -Error parsing file %x, row %y, column %z. -حدث خطأ أثناء تحليل الملف %x، الصف %y، و العمود %z. - -Cannot set directory lock for %x. -تعذر إنشاء قفل للمسار %x. - -Scanning: -الفحص: - - -1 thread -%x threads - - -0 بند -1 بند واحد -2 بندان -%x بنود -%x بنداً -%x بند - - -/sec -\ثانية - -%x items/sec -%x عنصر\الثانية - -Show in Explorer -إظهار في المستكشف - -Open with default application -فتح باستخدام التطبيق الافتراضي - -Browse directory -تصفح المسار - -Cannot access the Volume Shadow Copy Service. -لا يمكن الوصول إلى خدمة "نسخ الظل لوحدة التخزين". - -Please use FreeFileSync 64-bit version to create shadow copies on this system. -الرجاء استخدام إصدار الـ 64-bit للبرنامج لإنشاء ملفات الظل الاحتياطية على هذا النظام. - -Cannot determine volume name for %x. -تعذر تحديد اسم الوسط %x - -Volume name %x is not part of file path %y. -اسم وحدة التخزين %x ليس جزءاُ من اسم الملف %y. - -Stop requested: Waiting for current operation to finish... -طلب إحباط المهمة: في انتظار انتهاء المهمة الحالية... - -Unable to create time stamp for versioning: -تعذر إنشاء بصمة زمنية من أجل المفاضلة الزمنية: - -Drag && drop -سحب و إفلات - -Cannot find folder %x. -تعذر العثور على المجلد %x. - -Select a folder -تحديد مجلد - -&Open... -&فتح... - -Save &as... -&حفظ باسم... - -E&xit -&إغلاق - -&File -&ملف - -&View help -إ&ظهار المساعدة - -&About -&حول - -&Help -&تعليمات - -Usage: -الاستخدام: - -1. Select folders to watch. -1. حدد المجلدات للمتابعة. - -2. Enter a command line. -2. إدخال سطر أوامر. - -3. Press 'Start'. -3. اضغط على 'ابدأ'. - -To get started just import a .ffs_batch file. -للبدء قم باستيراد ملف .ffs_batch. - -Folders to watch: -المجلدات للمتابعة: - -Add folder -إضافة مجلد - -Remove folder -إزالة مجلد - -Browse -تصفح - -Idle time (in seconds): -وقت الخمول (بالثانية) - -Idle time between last detected change and execution of command -وقت الخمول بين آخر تغيير تم الكشف عنه وتنفيذ الأوامر - -Command line: -سطر الأوامر: - - -The command is triggered if: -- files or subfolders change -- new folders arrive (e.g. USB stick insert) - - -يتم تشغيل الأمر إذا: --حدوث تغيير في الملفات أو المجلدات الفرعية --ظهور مجلدات جديدة (مثال: إدخال USB stick) - - -&Start -&ابدأ - -About -حول - -Build: %x -بناء: %x - -All files -جميع الملفات - -Automated Synchronization -مزامنة تلقائية - -Directory monitoring active -مراقبة المسارات فعالة - -Waiting until all directories are available... -انتظر حتى توفر جميع المسارات... - -Error -خطأ - -&Restore -&استعادة - -&Show error -إ&ظهار الخطأ - -&Quit -إ&نهاء - -&Retry -إ&عادة المحاولة - -File content -محتوى الملف - -File time and size -تاريخ الملف و حجمه - -Two way -بالاتجاهين - -Mirror -انعكاس - -Update -تحديث - -Custom -مخصص - -Multiple... -متعددة... - -Moving file %x to %y -نقل الملف %x إلى %y - -Moving folder %x to %y -نقل المجلد %x إلى %y - -Moving symbolic link %x to %y -نقل الارتباط الرمزي %x إلى %y - -Removing old versions... -إزالة الإصدارات القديمة... - -Creating symbolic link %x -إنشاء ارتباط رمزي %x - -Creating folder %x -إنشاء مجلد %x - -Updating file %x -جاري تحديث الملف %x - -Updating symbolic link %x -جاري تحديث المسار الرمزي %x - -Verifying file %x -التحقق من الملف %x - -Updating attributes of %x -تحديث سمات %x - -%x and %y have different content. - - -Data verification error: - - -Creating a Volume Shadow Copy for %x... -جاري إنشاء نسخة ظل وسيطة لـ %x... - -Target folder %x already existing. -المجلد الهدف %x موجود سابقاً. - -Target folder input field must not be empty. -يجب أن لا يكون حقل إدخال المجلد الهدف فارغاً. - -Source folder %x not found. -لم يتم العثور على المجلد المصدر %x. - -Please enter a target folder for versioning. -الرجاء تحديد مجلد هدف من أجل الوسم حسب الإصدار. - -The following items have unresolved conflicts and will not be synchronized: -العناصر التالية لم تحل اختلافاتها، و لن يتم مزامنتها: - -The following folders are significantly different. Make sure you have selected the correct folders for synchronization. - - -Not enough free disk space available in: -المساحة الحرة المتوفرة على القرص غير كافية: - -Required: -مطلوب: - -Available: -متاح: - -Multiple folder pairs write to a common subfolder. Please review your configuration. -عدد من أزواج المجلدات يكتب إلى مجلد فرعي مشترك. رجاءً أعد النظر في خياراتك. - -Synchronizing folder pair: -مزامنة زوج مجلدات: - -Generating database... -إنشاء قاعدة بيانات... - -job name -اسم المهمة - -Synchronization stopped -توقفت عملية المزامنة - -Stopped -توقف - -Synchronization completed with errors -انتهاء عملية المزامنة مع وجود أخطء - -Synchronization completed with warnings -انتهاء عملية المزامنة مع وجود تحذيرات - -Warning -تحذير - -Nothing to synchronize -لا يوجد شيء للمزامنة - -Synchronization completed successfully -تمت المزامنة بنجاح - -Cleaning up old log files... -جاري تنظيف ملفات المتابعة القديمة... - -You can switch to FreeFileSync's main window to resolve this issue. -بإمكانك العودة إلى نافذة FreeFileSync الرئيسية لحل هذه المشكلة. - -&Don't show this warning again -&لا تظهر هذا التنبيه مرة ثانية - -&Ignore -&تجاهل - -&Switch -&تبديل - -Switching to FreeFileSync's main window -العودة إلى نافذة FreeFileSync الرئيسية - - -Automatic retry in 1 second... -Automatic retry in %x seconds... - - -إعادة المحاولة بعد 0 ثانية... -إعادة المحاولة بعد 1 ثانية واحدة... -إعادة المحاولة بعد 2 ثانيتين... -إعادة المحاولة بعد %x ثواني... -إعادة المحاولة بعد %x ثانية... -إعادة المحاولة بعد %x ثانية... - - -&Ignore subsequent errors -&تجاهلا الأخطاء المماثلة - -Retrying operation... -إعادة محاولة العملية... - -Serious Error -خطأ فادح - -Check for Program Updates -تفقد وجود تحديثات للبرنامج - -A new version of FreeFileSync is available: -يتوفر إصدار جديد من FreeFileSync: - -Download now? -تنزيل الآن؟ - -&Download -&تنزيل - -FreeFileSync is up to date. -البرنامج هو الأحدث حتى الآن. - -Unable to connect to www.freefilesync.org. -تعذر الاتصال بـ www.freefilesync.org - -Cannot find current FreeFileSync version number online. Do you want to check manually? -لم نستطع العثور على على رقم إصدار FreeFileSync على الشبكة. هل تريد التحقق يدوياً؟ - -&Check -&تحقق - -Symlink -ارتباط-رمزي - -Folder -المجلد - -Full path -المسار الكامل - -Name -الاسم - -Relative folder -مجلد نسبي - -Base folder -المجلد الأساسي (القاعدي) - -Size -الحجم - -Date -تاريخ - -Extension -اللاحقة - -Category -الفئة - -Action -التصرف - -Local comparison settings -إعدادات المقارنة المحلية - -Local synchronization settings -إعدادات المزامنة المحلية - -Local filter -فلتر محلي - -Active -مفعل - -None -لا شيء - -Remove local settings -إزالة الإعدادات المحلية - -Clear local filter -إزالة الفلتر المحلي - -Copy -نسخ - -Paste -لصق - -Local Synchronization Settings -إعدادات المزامنة المحلية - -The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. - - -&New -&جديد - -&Save -&حفظ - -Save as &batch job... -&حفظ كمهمة دفعية... - -Start &comparison -بدأ الم&قارنة - -C&omparison settings -&مقارنة - -&Filter settings -إعدادات ال&فلتر - -S&ynchronization settings -إ&عدادات - -Start &synchronization -بدأ الم&زامنة - -&Actions -&مهام - -&Options -&خيارات - -&Language -الل&غة - -&Find... -&بحث... - -&Reset layout -إعادة ال&تنسيق إلى الإفتراضي - -&Export file list... -&تصدير قائمة الملفات... - -&Tools -أ&دوات - -&Check for new version -ال&تحقق من وجود نسخة جديدة - -&Check now -&تحقق الآن - -Check &automatically once a week -&تحقق أوتوماتيكياً بشكل أسبوعي - -Cancel -إلغاء الأمر - -Compare -قارن - -Synchronize -مزامنة - -Add folder pair -إضافة زوج مجلدات - -Remove folder pair -إزالة زوج مجلدات - -Select SFTP folder - - -Swap sides -مبادلة الجانبين - -Close search bar -إغلاق شريط البحث - -Find: -بحث - -Match case -مطابقة حالة الأحرف (Match case) - -New -جديد - -Open... -فتح... - -Save -حفظ - -Save as... -حفظ كـ... - -View type: -عرض النوع: - -Select view: -اختيار نمط العرض: - -Statistics: -إحصائيات: - -Number of files and folders that will be deleted -عدد الملفات و المجلدات التي سيتم حذفها - -Number of files that will be updated -عدد الملفات التي سيتم تحديثها - -Number of files and folders that will be created -عدد الملفات و المجلدات التي سيتم إنشاؤها - -Total bytes to copy -إجمالي عدد الـ bytes التي سيتم نسخها - -Use local settings: -استخدام الإعدادات المحلية: - -Select a variant: -اختيار بديل: - -Identify equal files by comparing modification time and size. -التعرف على الملفات المتساوية عن طريق مقارنة التاريخ و الحجم - -Identify equal files by comparing the file content. -التعرف على الملفات المتساوية عن طريق مقارنة محتوى الملف - -&Ignore time shift (in hours) - - -Consider file times with specified offset as equal -اعتبار الملفات ذات الفارق الزمني المحدد و كأنها متساوية - -Handle daylight saving time -تعامل مع التوقيت الصيفي - -Include &symbolic links: - - -&Follow - - -&Direct - - -More information -المزيد من المعلومات - -Local settings: -الإعدادات المحلية - -Include: -إدخال: - -Exclude: -استثناء: - -Show examples -إظهار أمثلة - -Time span: -المجال الزمني: - -File size: -حجم الملف: - -Minimum: -الحد الأدنى: - -Maximum: -الحد الأقصى: - -Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. -اختيار قوانين فلترة لاستثناء ملفات معينة من المزامنة. أدخل مسارات الملفات منسوبة إلى زوج المجلدات المقابل. - -C&lear -إ&زالة - -Detect moved files -اكتشاف الملفات المنقولة - - -- Not supported by all file systems -- Requires and creates database files -- Detection not available for first sync - - - -Detect synchronization directions with the help of database files -تحديد اتجاه المزامنة بالاستعانة بقواعد بيانات الملفات - -Delete files: -حذف الملفات: - -&Permanent -&دائم - -Delete or overwrite files permanently -حذف أو الكتابة فوق الملفات بشكل دائم - -&Recycle bin -&سلة المهملات - -Back up deleted and overwritten files in the recycle bin -نسخ احتياطي للملفات المحذوفة و المستبدلة في سلة المهملات - -&Versioning -ال&وسم حسب الإصدار - -Move files to a user-defined folder -نقل الملفات إلى المجلد المحدد من قبل المستخدم - -Naming convention: -اصطلاح التسمية: - -Handle errors: -التعامل مع الأخطاء: - -Hide all error and warning messages -إخفاء جميع رسائل الأخطاء و التحذير - -&Pop-up -&منبثق - -Show pop-up on errors or warnings -إظهار إطارات منبثقة عند حصول أخطاء أو تحذيرات - -On completion: -عند الانتهاء: - -OK -موافق - -Enter your SFTP login details: - - -Server name or IP address: - - -Examples: - - -User name: - - -Password: - - -&Show password - - -Directory on server: - - - - -Start synchronization now? -بدأ المزامنة الآن؟ - -Variant: -بديل - -&Don't show this dialog again -&لا تظهر نافذة الحوار هذه مرة ثانية - -Arrange folder pair - - -Items found: -العناصر التي تم العثور عليها: - -Time remaining: -الوقت المتبقي: - -Time elapsed: -الوقت المنقضي: - -Synchronizing... -مزامنة... - -Minimize to notification area -تصغير إلى منطقة التنبيهات - -Bytes copied: -Bytes المنسوخة: - -Close -إغلاق - -&Pause -إ&يقاف مؤقت - -Stop -توقف - -Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x -إنشاء ملف دفعي من أجل عمليات المزامنة غير المحضورة. للبدأ, انقر نقراً مزدوجاً على الملف أو المهمة المجدولة في منظم المهام: %x - -&Stop -&توقف - -Stop synchronization at first error -إحباط المزامنة عند أول خطأ - -Run minimized -تشغيل بوضع التصغير - -Save log: -حفظ السجل - -Limit: -حدود - -Limit maximum number of log files -تقييد الحد الأقصى لعدد ملفات السجل - -How can I schedule a batch job? -كيف يمكنني جدولة مهمة دفعية؟ - -The following settings are used for all synchronization jobs. -هذه الإعدادات مستخدمة لجميع مهمات المزامنة - -Fail-safe file copy -نسخ ملفات آمن من الفشل - - -Copy to a temporary file (*.ffs_tmp) before overwriting target. -This guarantees a consistent state even in case of a serious error. - - -قم بالنسخ إلى ملف مؤقت (*.ffs_tmp) قبل استبدال الملف الهدف. -هذه العملية تضمن حالة مستقرة حتى في حال حدوث خطأ فادح. - - -(recommended) -(موصى به) - -Copy locked files -نسخ الملفات المقفلة - -Copy shared or locked files using the Volume Shadow Copy Service. -نسخ الملفات المشتركة مع مستخدمين آخرين أو المقفولة باستخدام خدمة نسخ الظل الوسيط - -(requires administrator rights) -(بحاجة امتيازات المدير) - -Copy file access permissions -نسخ أذونات الوصول إلى الملف - -Transfer file and folder permissions. -نقل أذونات الملفات و المجلدات. - -Automatic retry on error: -إعادة المحاولة بشكل تلقائي عند حصول خطأ: - -Retry count: -تعداد محاولات الإعادة: - -Delay (in seconds): -التأخير (بالثواني): - -Customize context menu: -تخصيص القائمة المحلية - -Description -الوصف - -Show hidden dialogs again -إظهار التنبهات و نوافذ الحوار المخفية - -Show all permanently hidden dialogs and warning messages again -إعادة إظهار جميع التنبهات و نوافذ الحوار التي تم إخفاؤها - -&Default -الا&فتراضي - -Source code written in C++ using: -الرماز المصدري مكتوب بلغة C++ باستخدام: - -If you like FreeFileSync: -إذا أعجبك FreeFileSync: - -Donate with PayPal -تبرع باستخدام PayPal - -Feedback and suggestions are welcome -التعليقات و الاقتراحات موضع ترحيب - -Homepage -الصفحة الرئيسية - -Email -البريد الإلكتروني - -Published under the GNU General Public License -نشر تحت رخصة GNU General Public License - -Many thanks for localization: -شكرا جزيلا للترجمة: - -SSH File Transfer Protocol - - -Save as Batch Job -حفظ كمهمة دفعية - -Delete Items -حذف العناصر - -Options -خيارات - -Select Time Span -اختيار المطال الزمني - -&Preferences - - -Main Bar -الشريط الرئيسي - -Folder Pairs -أزواج المجلدات - -Find -بحث - -View Settings -عرض الإعدادات - -Configuration -التكوين - -Overview -نظرة عامة - -Confirm -تأكيد - - -Do you really want to execute the command %y for one item? -Do you really want to execute the command %y for %x items? - - -هل تريد حقاً تنفيذ العملية %y من أجل عنصر 0 -هل تريد حقاً تنفيذ العملية %y من أجل عنصر وحيد 1 -هل تريد حقاً تنفيذ العملية %y من أجل عنصرين اثنين 2 -هل تريد حقاً تنفيذ العملية %y من أجل %x عناصر -هل تريد حقاً تنفيذ العملية %y من أجل %x عنصراً -هل تريد حقاً تنفيذ العملية %y من أجل %x عنصر - - -&Execute -&تنفيذ - - -1 directory -%x directories - - -0 مسار -1 مسار واحد -2 مساران -%x مسارات -%x مساراً -%x مسار - - - -1 file -%x files - - -0 ملف -1 ملف واحد -2 ملفان -%x ملفات -%x ملفاً -%x ملف - - - -Showing %y of 1 row -Showing %y of %x rows - - -الظاهر %y من أصل سطر 0 -الظاهر %y من أصل سطر وحيد 1 -الظاهر %y من أصل سطرين اثنين 2 -الظاهر %y من أصل %x سطور -الظاهر %y من أصل %x سطراً -الظاهر %y من أصل %x سطر - - -Set direction: -تحديد الاتجاه: - -multiple selection -تحديد متعدد - -Include via filter: -تضمن عن طريق فلتر - -Exclude via filter: -استبعاد باستخدام عامل الفلترة: - -Include temporarily -شمول مؤقتاً - -Exclude temporarily -استبعاد مؤقتاً - -Delete -حذف - -Include all -شمول الكل - -Exclude all -استبعاد الكل - -Show icons: -إظهار الأيقونات: - -Small -صغيرة - -Medium -متوسطة - -Large -كبيرة - -Select time span... -حدد المجال الزمني... - -Show "%x" -إظهار "%x" - -Last session -مصدر الجلسة - -Folder Comparison and Synchronization -مقارنة و مزامنة المجلد - -Configuration saved -تم حفظ التكوين - -FreeFileSync batch -دفعة FreeFileSync - -Do you want to save changes to %x? -هل تريد حفظ التغييرات إلى %x؟ - -Never save &changes -&لا تقم بحفظ التغيرات - -Do&n't save -&لا تحفظ - -Remove entry from list - - -Synchronization Settings -إعدادات المزامنة - -Clear filter -إزالة الفلاتر الحالية - -Show files that exist on left side only -إظهار الملفات الموجودة في الجانب الأيمن فقط - -Show files that exist on right side only -إظهار الملفات الموجودة في الجانب الأيسر فقط - -Show files that are newer on left -إظهار الملفات الأحدث في اليمين - -Show files that are newer on right -إظهار الملفات الأحدث في اليسار - -Show files that are equal -إظهار الملفات المتماثلة على الطرفين - -Show files that are different -إظهار الملفات المختلفة على الطرفين - -Show conflicts -إظهار الاختلافات - -Show files that will be created on the left side -إظهار الملفات التي سيتم إنشاؤها في الجانب الأيمن - -Show files that will be created on the right side -إظهار الملفات التي سيتم إنشاؤها في الجانب الأيسر - -Show files that will be deleted on the left side -إظهار الملفات التي سيتم حذفها من من الجانب الأيمن - -Show files that will be deleted on the right side -إظهار الملفات التي سيتم حذفها من الجانب الأيسر - -Show files that will be updated on the left side -إظهار الملفات التي سيتم تحديثها في الجانب الأيسر - -Show files that will be updated on the right side -إظهار الملفات التي سيتم تحديثها في الجانب الأيمن - -Show files that won't be copied -إظهار الملفات التي لن يتم نسخها - -Show filtered or temporarily excluded files -إظهار الملفات التي تم فلترتها أو استبعادها بشكل مؤقت - -Save as default - - -Filter -عامل الفلترة - -All files are in sync -جميع الملفات في تزامن كامل - -Cannot find %x -لا يمكن العثور على %x - -Move up - - -Move down - - -Comma-separated values -قائمة قيم مفصولة بفواصل - -File list exported -تم تصدير قائمة الملفات - -Searching for program updates... -جاري البحث عن تحديثات للبرنامج... - -Close progress dialog -إنهاء نافذة حوار تقدم العملية - -Log off -تسجيل الخروج - -Standby -وضع الاستعداد - -Shut down -إيقاف التشغيل - -Scanning... -جاري الفحص... - -Comparing content... -مقارنة المحتوى... - -Info -معلومات - -Select all -اختيار الجميع - -Paused -تم الإيقاف مؤقتاً - -Initializing... -التجهيز للبدأ... - -Completed -انتهت العملية - -&Continue -&مواصلة - -Progress -التقدم - -Log -السجل - - -Do you really want to move the following item to the recycle bin? -Do you really want to move the following %x items to the recycle bin? - - -هل تريد حقاً نقل 0 ملف إلى سلة المهملات ؟ -هل تريد حقاً نقل هذا الملف الوحيد 1 إلى سلة المهملات ؟ -هل تريد حقاً نقل هذين الملفبن 2 إلى سلة المهملات ؟ -هل تريد حقاً نقل %x ملفات إلى سلة المهملات ؟ -هل تريد حقاً نقل %x ملفاً إلى سلة المهملات ؟ -هل تريد حقاً نقل %x ملف إلى سلة المهملات ؟ - - -Move -نقل - - -Do you really want to delete the following item? -Do you really want to delete the following %x items? - - -هل تريد حقاً حذف 0 ملف التالي ؟ -هل تريد حقاً حذف الملف 1 التالي ؟ -هل تريد حقاً حذف الملفين 2 التاليين ؟ -هل تريد حقاً حذف الـ %x ملفات التالية ؟ -هل تريد حقاً حذف الـ %x ملفاً التالية ؟ -هل تريد حقاً حذف الـ %x ملف التالية ؟ - - -Preferences -خيارات - -Copy DACL, SACL, Owner, Group - - -Integrate external applications into context menu. The following macros are available: -دمج تطبيقات خارجية في قائمة السياق. تتوفر وحدات الماكرو التالية: - -- full file or folder name -- اسم الملف أو المجلد كاملاً - -- folder part only -- جزء مجلد فقط - -- Other side's counterpart to %item_path% -- النظير للجانب الآخر لـ %item_path% - -- Other side's counterpart to %item_folder% -- االنظير للجانب الآخر لـ %item_folder% - -Show hidden dialogs and warning messages again? -إظهار التنبيهات و نوافذ الحوار المخفية مرة ثانية؟ - -&Show -&إظهار - -Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. -تحديد التغيرات و مواكبتها على الجانبين. عمليات الحذف, النقل و المشاكل المكتشفة باستخدام قواعد البيانات - -Create a mirror backup of the left folder by adapting the right folder to match. -إنشاء نسخة احتياطية من الجانب الأيمن عن طريق تعديل الطرف الأيسر ليطابق الأيمن. - -Copy new and updated files to the right folder. -نسخ الملفات المحدثة إلى المجلد المناسب - -Configure your own synchronization rules. -تحديد قواعد المزامنة الخاصة بك. - -Today -اليوم - -This week -هذا الأسبوع - -This month -هذا الشهر - -This year -هذه السنة - -Last x days -الأيام x الماضية - -Byte -Byte - -KB -KB - -MB -MB - -Replace -استبدال - -Move files and replace if existing -نقل الملفات و استبدال الموجودة بها إن وجدت - -Time stamp -البصمة الزمنية - -Append a time stamp to each file name -إلحاق ختم زمني بكل اسم ملف - -Comparison -المقارنة - -Synchronization -المزامنة - -Leave as unresolved conflict -ترك كاختلافات من دون حل - -File -ملف - -YYYY-MM-DD hhmmss -YYYY-MM-DD hhmmss - -Files -ملفات - -Items -عناصر - -Percentage -النسبة المئوية - -Unable to register to receive system messages. -تعذر التسجيل لاستقبال رسائل النظام. - -Unable to register device notifications for %x. - - -Cannot monitor directory %x. -لا يمكن مراقبة المسار %x. - -The file is locked by another process: -الملف مقفول من قبل عملية أخرى: - -Cannot write file attributes of %x. -لا يمكن كتابة سمات الملف %x. - -Cannot read security context of %x. -لا يمكن قراءة سياق الأمان %x. - -Cannot write security context of %x. -لا يمكن كتابة سياق الأمان %x. - -Cannot read permissions of %x. -لا يمكن قراءة أذونات %x. - -Cannot copy permissions from %x to %y. - - -Cannot find system function %x. -لا يمكن العثور على وظيفة نظام %x. - -Cannot copy attributes from %x to %y. - - -Cannot copy file %x to %y. -لا يمكن نسخ الملف %x إلى %y. - -Type of item %x is not supported: -نوع العنصر %x غير مدعوم: - -%x TB -%x TB - -%x PB -%x PB - - -1 min -%x min - - -0 دقيقة -1 دقيقة واحدة -2 دقيقتان -%x دقائق -%x دقيقة -%x دقيقة - - - -1 hour -%x hours - - -0 ساعة -1 ساعة واحدة -2 ساعتين -%x ساعات -%x ساعة -%x ساعة - - - -1 day -%x days - - -0 يوم -1 يوم واحد -2 يومان -%x أيام -%x يوماً -%x يوم - - -Cannot set privilege %x. -لا يمكن تعيين امتيازات %x. - -Unable to suspend system sleep mode. -تعذر تعليق وضع النوم للنظام. - -Cannot change process I/O priorities. -تعذر تغيير أولويات I/O للعملية - -Checking recycle bin failed for folder %x. -فشل تصفح سلة المهملات من أجل الملف %x. - -The following XML elements could not be read: - - -Configuration file %x is incomplete. The missing elements will be set to their default values. - - -Prepare installation -الاستعداد للتثبيت - -Choose which components you want to install. -اختر المكونات التي تريد تنصيبها - -Select installation type: -اختيار نوع التنصيب: - -Local -محلي - -Portable -متنقل - -recommended -‏منصوح به‏ - -Save settings to "%APPDATA%\FreeFileSync" -حفظ الإعدادات إلى ‏‪"%APPDATA%\FreeFileSync" - -Register FreeFileSync file extensions -تسجيل لاحقةالملفات - -Create Explorer context menu entries -إنشاء مدخلات القوائم المحلية في متصفح الملفات - -Save settings in installation directory -احفظ إعدادات التثبيت في مسار التثبيت - -Do not write to Registry -لا تسجل في ملفات الرجيستري - -Just copy the files -انسخ الملفات فقط - -Choose a directory for installation: -اختيار مسار التثبيت - -Create shortcuts: -إنشاء اختصار - -Desktop -سطح المكتب - -Start menu -قائمة إبدأ - -Registering FreeFileSync file extensions -تسجيل لاحقة الملفات - -Unregistering FreeFileSync file extensions -إلغاء تسجيل لاحقةالملفات - -FreeFileSync Configuration -تضبيطات FreeFileSync - -FreeFileSync Batch File -الملف الدفعي الخاص بـ FreeFileSync - -FreeFileSync Synchronization Database -قاعدة بيانات المزامنة الخاصة بـ FreeFileSync - -RealtimeSync Configuration -تضبيطات RealtimeSync - -Edit with FreeFileSync -تعديل بواسطة FreeFileSync - diff --git a/FreeFileSync/Build/Languages/chinese_traditional.lng b/FreeFileSync/Build/Languages/chinese_traditional.lng index 01d388d8..375f0aac 100644 --- a/FreeFileSync/Build/Languages/chinese_traditional.lng +++ b/FreeFileSync/Build/Languages/chinese_traditional.lng @@ -7,6 +7,9 @@ 0 +Port: + + Both sides have changed since last synchronization. 自上次同步後,兩邊均已變更過。 diff --git a/FreeFileSync/Build/Languages/english_uk.lng b/FreeFileSync/Build/Languages/english_uk.lng index ba5160de..f7446956 100644 --- a/FreeFileSync/Build/Languages/english_uk.lng +++ b/FreeFileSync/Build/Languages/english_uk.lng @@ -7,6 +7,33 @@ n == 1 ? 0 : 1 +Please enter a target folder. + + + +Copy the following item to another folder? +Copy the following %x items to another folder? + + + +Copy to... + + +Copy items + + +&Copy + + +&Overwrite existing files + + +&Keep relative paths + + +Port: + + Both sides have changed since last synchronization. Both sides have changed since last synchronisation. @@ -22,8 +49,14 @@ Setting default synchronization directions: Old files will be overwritten with newer files. Setting default synchronisation directions: Old files will be overwritten with newer files. -Checking recycle bin availability for folder %x... -Checking recycle bin availability for folder %x... +Creating folder %x +Creating folder %x + +Creating file %x +Creating file %x + +Creating symbolic link %x +Creating symbolic link %x Moving file %x to the recycle bin Moving file %x to the recycle bin @@ -43,6 +76,9 @@ Deleting symbolic link %x Deleting symbolic link %x +Checking recycle bin availability for folder %x... +Checking recycle bin availability for folder %x... + The recycle bin is not available for the following folders. Files will be deleted permanently instead: The recycle bin is not available for the following folders. Files will be deleted permanently instead: @@ -345,9 +381,6 @@ Actual: %y bytes Detecting abandoned lock... Detecting abandoned lock... -Creating file %x -Creating file %x - Saving file %x... Saving file %x... @@ -557,12 +590,6 @@ The command is triggered if: Removing old versions... Removing old versions... -Creating symbolic link %x -Creating symbolic link %x - -Creating folder %x -Creating folder %x - Updating file %x Updating file %x @@ -797,8 +824,8 @@ The command is triggered if: &Actions &Actions -&Options -&Options +&Preferences +&Preferences &Language &Language @@ -1189,8 +1216,8 @@ This guarantees a consistent state even in case of a serious error. Select Time Span Select Time Span -&Preferences -&Preferences +&Options +&Options Main Bar Main Bar @@ -1462,9 +1489,6 @@ This guarantees a consistent state even in case of a serious error. Do you really want to delete the following %x items? -Preferences -Preferences - Copy DACL, SACL, Owner, Group Copy DACL, SACL, Owner, Group diff --git a/FreeFileSync/Build/Languages/german.lng b/FreeFileSync/Build/Languages/german.lng index a0b4ecaa..dc96d9d9 100644 --- a/FreeFileSync/Build/Languages/german.lng +++ b/FreeFileSync/Build/Languages/german.lng @@ -22,8 +22,14 @@ Setting default synchronization directions: Old files will be overwritten with newer files. Setze Standardwerte für Synchronisationsrichtungen: Alte Dateien werden durch neuere überschrieben. -Checking recycle bin availability for folder %x... -Prüfe Verfügbarkeit des Papierkorbs für Ordner %x... +Creating folder %x +Erstelle Ordner %x + +Creating file %x +Erstelle Datei %x + +Creating symbolic link %x +Erstelle symbolischen Verknüpfung %x Moving file %x to the recycle bin Verschiebe Datei %x in den Papierkorb @@ -43,6 +49,9 @@ Deleting symbolic link %x Lösche symbolische Verknüpfung %x +Checking recycle bin availability for folder %x... +Prüfe Verfügbarkeit des Papierkorbs für Ordner %x... + The recycle bin is not available for the following folders. Files will be deleted permanently instead: Der Papierkorb ist für die folgenden Ordner nicht verfügbar. Dateien werden stattdessen permanent gelöscht: @@ -243,12 +252,6 @@ Tatsächlich: %y bytes Cannot open file %x. Die Datei %x kann nicht geöffnet werden. -Cannot delete directory %x. -Das Verzeichnis %x kann nicht gelöscht werden. - -Cannot delete file %x. -Die Datei %x kann nicht gelöscht werden. - Cannot find device %x. Das Gerät %x wurde nicht gefunden. @@ -258,6 +261,12 @@ Tatsächlich: %y bytes Cannot create directory %x. Das Verzeichnis %x kann nicht erstellt werden. +Cannot delete directory %x. +Das Verzeichnis %x kann nicht gelöscht werden. + +Cannot delete file %x. +Die Datei %x kann nicht gelöscht werden. + Cannot write modification time of %x. Die Änderungszeit von %x kann nicht geschrieben werden. @@ -345,9 +354,6 @@ Tatsächlich: %y bytes Detecting abandoned lock... Ermittle aufgegebene Sperre... -Creating file %x -Erstelle Datei %x - Saving file %x... Speichere Datei %x... @@ -557,12 +563,6 @@ Die Befehlszeile wird ausgelöst, wenn: Removing old versions... Entferne alte Versionen... -Creating symbolic link %x -Erstelle symbolischen Verknüpfung %x - -Creating folder %x -Erstelle Ordner %x - Updating file %x Aktualisiere Datei %x @@ -797,8 +797,8 @@ Die Befehlszeile wird ausgelöst, wenn: &Actions &Aktionen -&Options -&Optionen +&Preferences +&Einstellungen &Language &Sprache @@ -1015,6 +1015,9 @@ Die Befehlszeile wird ausgelöst, wenn: Server name or IP address: Servername oder IP-Adresse: +Port: +Port: + Examples: Beispiele: @@ -1093,6 +1096,15 @@ Die Befehlszeile wird ausgelöst, wenn: How can I schedule a batch job? Wie können Batchaufträge in den Taskplaner eingetragen werden? +&Keep relative paths +&Relative Pfade beibehalten + +&Overwrite existing files +&Existierende Dateien überschreiben + +&Copy +&Kopieren + The following settings are used for all synchronization jobs. Die folgenden Einstellungen werden für alle Synchronisationsaufgaben verwendet. @@ -1183,14 +1195,17 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. Delete Items Elemente löschen +Copy items +Elemente kopieren + Options Optionen Select Time Span Zeitspanne auswählen -&Preferences -&Einstellungen +&Options +&Optionen Main Bar Hauptleiste @@ -1270,6 +1285,9 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. Exclude temporarily Temporär ausschließen +Copy to... +Kopieren nach... + Delete Löschen @@ -1441,6 +1459,18 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. Log Protokoll + +Copy the following item to another folder? +Copy the following %x items to another folder? + + +Soll das folgende Element in einen anderen Ordner kopiert werden? +Sollen die folgenden %x Elemente in einen anderen Ordner kopiert werden? + + +Please enter a target folder. +Bitte geben Sie einen Zielorder ein. + Do you really want to move the following item to the recycle bin? Do you really want to move the following %x items to the recycle bin? @@ -1462,9 +1492,6 @@ Dadurch wird ein konsistenter Datenstand auch im schweren Fehlerfall garantiert. Sollen die folgenden %x Elemente wirklich gelöscht werden? -Preferences -Einstellungen - Copy DACL, SACL, Owner, Group DACL, SACL, Besitzer und Gruppe kopieren diff --git a/FreeFileSync/Build/Languages/italian.lng b/FreeFileSync/Build/Languages/italian.lng index c76c3bf7..3542ee7e 100644 --- a/FreeFileSync/Build/Languages/italian.lng +++ b/FreeFileSync/Build/Languages/italian.lng @@ -56,7 +56,7 @@ Errore di sintassi Cannot find file %x. - +Impossibile trovare il file %x. File %x does not contain a valid configuration. Il file %x non contiene una configurazione valida. @@ -95,7 +95,7 @@ Qualsiasi numero di coppie di directory alternative per al massimo un file di configurazione. Open configuration for editing without executing it. - +Apri configurazione per la modifica senza eseguirlo. Cannot find the following folders: Impossibile trovare le seguenti cartelle: @@ -210,13 +210,17 @@ Unexpected size of data stream. Expected: %x bytes Actual: %y bytes - + +Dimensioni impreviste del flusso di dati. +Previsto: %x byte +Attuale: %y byte + Cannot write permissions of %x. Impossibile scrivere i permessi di %x. Operation not supported for different base folder types. - +Operazione non supportata per i diversi tipi di cartelle di base. Cannot write file %x. Impossibile scrivere il file %x. @@ -234,26 +238,26 @@ Actual: %y bytes Impossibile leggere gli attributi del file %x. Cannot find %x. - +Impossibile trovare %x. Cannot open file %x. Impossibile aprire il file %x. -Cannot delete directory %x. -Impossibile eliminare la directory %x. - -Cannot delete file %x. -Impossibile eliminare il file %x. - Cannot find device %x. - +Impossibile trovare dispositivo %x. Cannot determine free disk space for %x. - +Impossibile determinare lo spazio libero su disco per %x. Cannot create directory %x. Impossibile creare la cartella %x. +Cannot delete directory %x. +Impossibile eliminare la directory %x. + +Cannot delete file %x. +Impossibile eliminare il file %x. + Cannot write modification time of %x. Impossibile scrivere data e ora di modifica di %x. @@ -276,7 +280,7 @@ Actual: %y bytes Codice Errore %x: Failed to connect to SFTP server %x. - +Impossibile connettersi al server SFTP %x. 1 byte @@ -318,7 +322,7 @@ Actual: %y bytes Ricerca della cartella %x... Time out while searching for folder %x. - +Pausa durante la ricerca per la cartella %x. Cannot get process information. Impossibile ottenere informazioni sul processo. @@ -378,7 +382,7 @@ Actual: %y bytes /sec %x items/sec -%x elementi/sec +%x oggetti/sec Show in Explorer Mostra in Esplora Risorse @@ -450,7 +454,7 @@ Actual: %y bytes 3. Premi 'Avvio'. To get started just import a .ffs_batch file. -Per iniziare è sufficiente importare un file con estensione .ffs_batch +Per iniziare è sufficiente importare un file con estensione .ffs_batch. Folders to watch: Cartelle da guardare: @@ -572,10 +576,10 @@ Il comando è attivato se: Aggiornamento attributi di %x %x and %y have different content. - +%x e %y hanno un contenuto diverso. Data verification error: - +Errore di verifica dei dati: Creating a Volume Shadow Copy for %x... Creazione di un Volume Shadow Copy per %x... @@ -596,7 +600,7 @@ Il comando è attivato se: I seguenti oggetti hanno conflitti irrisolti e non saranno sincronizzati: The following folders are significantly different. Make sure you have selected the correct folders for synchronization. - +Le seguenti cartelle sono significativamente differenti. Assicurarsi di aver selezionato le cartelle corrette per la sincronizzazione. Not enough free disk space available in: Spazio libero su disco insufficiente in: @@ -731,7 +735,7 @@ Il comando è attivato se: Categoria Action -Azioni +Azione Local comparison settings Impostazioni di confronto locali @@ -764,7 +768,7 @@ Il comando è attivato se: Impostazioni di sincronizzazione locale The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. - +La cartella selezionata %x non può essere utilizzata con FreeFileSync. Si prega di selezionare una cartella su un file system locale, di rete o un dispositivo MTP. &New &Nuovo @@ -836,7 +840,7 @@ Il comando è attivato se: Elimina la coppia di cartelle Select SFTP folder - +Selezionare la cartella SFTP Swap sides Inverti i lati @@ -896,7 +900,7 @@ Il comando è attivato se: Identificare i file uguali confrontando il contenuto del file. &Ignore time shift (in hours) - +&Ignora tempo di spostamento (in ore) Consider file times with specified offset as equal Considerare i tempi dei file con specifico offset o uguale @@ -905,13 +909,13 @@ Il comando è attivato se: Maneggiare l'ora legale Include &symbolic links: - +Includere collegamenti &simbolici: &Follow - +&Esegui &Direct - +&Diretta More information Maggiori informazioni @@ -954,7 +958,11 @@ Il comando è attivato se: - Requires and creates database files - Detection not available for first sync - + +- Non supportato da tutti i file system +- Richiede e crea file di database +- Rilevazione non disponibile per prima sincronizzazione + Detect synchronization directions with the help of database files Rileva indicazioni sincronizzazione con l'aiuto del file di database @@ -1002,27 +1010,25 @@ Il comando è attivato se: OK Enter your SFTP login details: - +Inserisci i tuoi dati d'accesso SFTP: Server name or IP address: - +Nome server o indirizzo IP: Examples: - +Esempi: User name: - +Nome utente: Password: - +Password: &Show password - +&Mostra password Directory on server: - - - +Directory su server: Start synchronization now? Avviare la sincronizzazione ora? @@ -1034,7 +1040,7 @@ Il comando è attivato se: &Non mostrare più questo avviso Arrange folder pair - +Disporre coppia di cartelle Items found: Oggetti trovati: @@ -1169,7 +1175,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Ringraziamenti per la traduzione: SSH File Transfer Protocol - +Protocollo di trasferimento SSH Save as Batch Job Salva come Processo Batch @@ -1184,7 +1190,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Selezionare Intervallo di Tempo &Preferences - +&Preferenze Main Bar Barra Principale @@ -1313,7 +1319,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. No&n salvare Remove entry from list - +Togliere voce dalla lista Synchronization Settings Impostazioni di Sincronizzazione @@ -1367,7 +1373,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Mostra file filtrati o temporaneamente esclusi Save as default - +Salva come predefinito Filter Filtro @@ -1379,10 +1385,10 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Impossibile trovare %x Move up - +Sposta su Move down - +Sposta giù Comma-separated values Valori separati da virgole @@ -1460,7 +1466,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Preferenze Copy DACL, SACL, Owner, Group - +Copia DACL, SACL, Proprietario, Gruppo Integrate external applications into context menu. The following macros are available: Integra applicazioni esterne nel menu contestuale. Sono disponibili le seguenti macro: @@ -1559,7 +1565,7 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Impossibile registrarsi per ricevere i messaggi di sistema. Unable to register device notifications for %x. - +Impossibile registrare le notifiche di dispositivo per %x. Cannot monitor directory %x. Impossibile monitorare la directory %x. @@ -1580,13 +1586,13 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Impossibile leggere i permessi di %x. Cannot copy permissions from %x to %y. - +Non è possibile copiare i permessi da %x per %y. Cannot find system function %x. Impossibile trovare la funzione di sistema %x. Cannot copy attributes from %x to %y. - +Non è possibile copiare gli attributi da %x per %y. Cannot copy file %x to %y. Impossibile copiare il file %x in %y. @@ -1640,10 +1646,10 @@ Questo garantisce uno stato consistente anche in caso di errore grave. Controllo cestino non riuscito per la cartella %x. The following XML elements could not be read: - +I seguenti elementi XML non possono essere letti: Configuration file %x is incomplete. The missing elements will be set to their default values. - +File di configurazione %x incompleta. Gli elementi mancanti saranno impostati sui valori predefiniti. Prepare installation Preparare l'installazione diff --git a/FreeFileSync/Build/Languages/norwegian.lng b/FreeFileSync/Build/Languages/norwegian.lng deleted file mode 100644 index 37efb208..00000000 --- a/FreeFileSync/Build/Languages/norwegian.lng +++ /dev/null @@ -1,1713 +0,0 @@ -
    - Norsk - bjorn96 - nb_NO - flag_norway.png - 2 - n == 1 ? 0 : 1 -
    - -Both sides have changed since last synchronization. -Begge sider er endret siden siste synkronisering. - -Cannot determine sync-direction: -Kan ikke bestemme retning: - -No change since last synchronization. -Ingen endringer siden siste synkronisering. - -The database entry is not in sync considering current settings. -Databaseemnet er ikke i synkronisering med de aktuelle innstillinger. - -Setting default synchronization directions: Old files will be overwritten with newer files. -Setter standardretning: Gamle filer overskrives med nyere. - -Checking recycle bin availability for folder %x... -Sjekker papirkurvens tilgjengelighet for mappen %x... - -Moving file %x to the recycle bin -Flytter filen %x til papirkurv - -Moving folder %x to the recycle bin -Flytter mappen %x til papirkurv - -Moving symbolic link %x to the recycle bin -Flytter symbolsk link %x til papirkurv - -Deleting file %x -Sletter filen %x - -Deleting folder %x -Sletter mappen %x - -Deleting symbolic link %x -Sletter symlink %x - -The recycle bin is not available for the following folders. Files will be deleted permanently instead: -Papirkurven kan ikke brukes til følgende mapper. Filene slettes permanent: - -An exception occurred -Unntagelse oppstod - -A directory path is expected after %x. -Det forventes en mappestil etter %x. - -Syntax error -Syntaksfeil - -Cannot find file %x. - - -File %x does not contain a valid configuration. -Filen %x inneholder ikke gyldige innstillinger. - -Unequal number of left and right directories specified. -Det er angitt et ulikt antall høyre og venstre mapper. - -The config file must not contain settings at directory pair level when directories are set via command line. -Instillingsfilen må ikke indeholde innstillinger på mappepar nivå når mapper er satt via kommando. - -Directories cannot be set for more than one configuration file. -Mapper kan ikke settes til mere enn en innstillingsfil. - -Command line -Kommando - -Syntax: -Syntaks: - -global config file: -Global konfigureringsfil - -config files: -Konfigurer filer - -directory -mappe - -Path to an alternate GlobalSettings.xml file. -Sti til en alternativ GlobalSettings.xml fil - -Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. -Vilkårlig antall FreeFileSync .ffs_gui og/eller .ffs_batch indstillingsfiler. - -Any number of alternative directory pairs for at most one config file. -Et ubegrenset antall alternative kataloger for maksimalt én konfigurasjonsfil - -Open configuration for editing without executing it. - - -Cannot find the following folders: -Kan ikke finne følgende mapper: - -You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. -Ignorer denne fil for at betrakte hver mappe som tom. Mapperne blir så automatisk opprettet ved synkronisering. - -A folder input field is empty. -Der er ikke valgt noen mapper. - -The corresponding folder will be considered as empty. -Den tilsvarende mappe betraktes som tom. - -The following folder paths are dependent from each other: -De følgende mappebaner er avhengige av hverandre - -File %x has an invalid date. -Filen %x har en ugyldig dato. - -Date: -Dato: - -Files %x have the same date but a different size. -Filene %x har den samme dato men forskjellig størrelse. - -Size: -Størrelse: - -Content comparison was skipped for excluded files %x. -Innholdsanalyse er utelatt for ekskluderte filer %x - -Items differ in attributes only -Enhetene har kun forskjellige attributter - -Resolving symbolic link %x -Løser symbolsk link %x - -Comparing content of files %x -Sammenligner innhold av filer %x - -Generating file list... -Oppretter filliste... - -Starting comparison -Starter analyse - -Calculating sync directions... -Forbereder synkronisering... - -Out of memory. -Ikke nok minne. - -Item exists on left side only -Mappen finnes kun på venstre side - -Item exists on right side only -Mappen finnes kun på høyre side - -Left side is newer -Venstre er nyest - -Right side is newer -Høyre er nyest - -Items have different content -Emnene har forskjellig innhold - -Both sides are equal -Begge sider er like - -Conflict/item cannot be categorized -Konflikt/ukjent mappe - -Copy new item to left -Kopier ny mappe mot venstre - -Copy new item to right -Kopier ny mappe mot høyre - -Delete left item -Slett venstre mappe - -Delete right item -Slett høyre mappe - -Move file on left -Flytt filen til venstre - -Move file on right -Flytt filen til høyre - -Update left item -Oppdater fil til venstre - -Update right item -Oppdater fil til høyre - -Do nothing -Ikke gjør noe - -Update attributes on left -Oppdater attributter til venstre - -Update attributes on right -Oppdater attributter til høyre - -Cannot read file %x. -Kan ikke lese filen %x. - - -Unexpected size of data stream. -Expected: %x bytes -Actual: %y bytes - - - -Cannot write permissions of %x. -Kan ikke skrive tillatelsene til %x. - -Operation not supported for different base folder types. - - -Cannot write file %x. -Kan ikke opprette filen %x. - -Cannot copy symbolic link %x to %y. -Kan ikke kopiere symolsk link %x til %y - -Cannot move file %x to %y. -Kan ikke flytte filen %x til %y. - -Cannot enumerate directory %x. -Kan ikke telle mappen %x. - -Cannot read file attributes of %x. -Kan ikke lese filattributterne på %x. - -Cannot find %x. - - -Cannot open file %x. -Filen %x kan ikke åpnes. - -Cannot delete directory %x. -Kan ikke slette mappen %x. - -Cannot delete file %x. -Kan ikke slette filen %x. - -Cannot find device %x. - - -Cannot determine free disk space for %x. - - -Cannot create directory %x. -Kan ikke opprette mappen %x. - -Cannot write modification time of %x. -Kan ikke oppdatere tidsendring på %x. - -Cannot determine final path for %x. -Kan ikke bestemme endelig sti for %x - -Cannot resolve symbolic link %x. -Kan ikke følge symlinken %x. - -Unable to move %x to the recycle bin. -Kunne ikke flytte %x til papirkurv. - -Cannot open directory %x. -Kan ikke åpne mappen %x. - -Incorrect command line: -Ugyldig kommando: - -Error Code %x: -Feilkode %x: - -Failed to connect to SFTP server %x. - - - -1 byte -%x bytes - - -1 byte -%x byte - - -%x MB -%x MB - -%x KB -%x KB - -%x GB -%x GB - -Cannot load file %x. -Kan ikke lese filen %x. - -Database file %x is incompatible. -Databasefilen %x er inkompatibel. - -Initial synchronization: -Forbereder synkronisering: - -Database file %x does not yet exist. -Databasefilen %x finnes ikke. - -Database file is corrupt: -Databasefilen er ødelagt: - -Database files do not share a common session. -Databasefiler kan ikke dele handling. - -Searching for folder %x... -Søker etter mappen %x... - -Time out while searching for folder %x. - - -Cannot get process information. -Kan ikke hente prosessinformasjon. - -Waiting while directory is locked: -Venter mens mappe låses: - -Lock owner: -Låsens eier - - -1 sec -%x sec - - -1 sek -%x sek - - -Detecting abandoned lock... -Finner etterlatt lås... - -Creating file %x -Oppretter filen %x - -Saving file %x... -Lagrer fil %x... - -Items processed: -Mapper behandlet: - -Items remaining: -Gjenstående mapper: - -Total time: -Samlet tid: - -Error parsing file %x, row %y, column %z. -Behandlingsfeil i filen %x, rekke %y, kolonne %z. - -Cannot set directory lock for %x. -Kan ikke låse mappen %x. - -Scanning: -Skanner: - - -1 thread -%x threads - - -1 tråd -%x tråder - - -/sec -/sek - -%x items/sec -%x mapper/sek - -Show in Explorer -Åpne filplassering - -Open with default application -Åpne med standardprogram - -Browse directory -Gjennomse mappe - -Cannot access the Volume Shadow Copy Service. -VSS tjenesten er ikke tilgjengelig - -Please use FreeFileSync 64-bit version to create shadow copies on this system. -Bruk FreeFileSync 64-bit til å lage VSS kopier på dette system. - -Cannot determine volume name for %x. -Kan ikke bestemme volumnavn for %x. - -Volume name %x is not part of file path %y. -Volumnavnet %x er ikke en del av filstien %y. - -Stop requested: Waiting for current operation to finish... -Avbryter: Venter til aktuell oppgave avsluttes... - -Unable to create time stamp for versioning: -Kan ikke opprette tidsstempel til versionering: - -Drag && drop -Trekk mapper hit - -Cannot find folder %x. -Finner ikke mappen %x. - -Select a folder -Velg en mappe - -&Open... -&Åpne... - -Save &as... -Lagre &som... - -E&xit -A&vslutt - -&File -&Fil - -&View help -&Åpne hjelp - -&About -&Om - -&Help -&Hjelp - -Usage: -Gjør slik: - -1. Select folders to watch. -1. Velg mapper til jobben. - -2. Enter a command line. -2. Angi en kommando. - -3. Press 'Start'. -3. Klikk 'Start'. - -To get started just import a .ffs_batch file. -Importer en .ffs_batchfil (Filer > Åpne...) for å komme igang. - -Folders to watch: -Jobbens mapper: - -Add folder -Tilføy mappe - -Remove folder -Fjern mappe - -Browse - - -Idle time (in seconds): -PC ikke brukt i (sek) - -Idle time between last detected change and execution of command -Tid mellom sist funnet endring og utførelse - -Command line: -Kommando: - - -The command is triggered if: -- files or subfolders change -- new folders arrive (e.g. USB stick insert) - - -Kommandoen utføres hvis: -- filer eller undermapper endres -- nye mapper finnes (f.eks USB nøkkel) - - -&Start -&Start - -About -Om - -Build: %x -Utgitt: %x - -All files -Alle filer - -Automated Synchronization -Automatisk synkronisering - -Directory monitoring active -Mappeovervåkning aktiv - -Waiting until all directories are available... -Venter til alle mapper er tilgjengelige... - -Error -Feil - -&Restore -&Vis vinduer - -&Show error -&Vis feil - -&Quit -&Avslutt - -&Retry -&Prøv igjen - -File content -Innhold - -File time and size -Størrelse og tid - -Two way -Toveis - -Mirror -Speiling - -Update -Oppdater - -Custom -Tilpasset - -Multiple... -Flere... - -Moving file %x to %y -Flytter filen %x til %y - -Moving folder %x to %y -Flytter mappen %x til %y - -Moving symbolic link %x to %y -Flytter symlinken %x til %y - -Removing old versions... -Fjerner gamle utgaver... - -Creating symbolic link %x -Oppretter symlinken %x - -Creating folder %x -Oppretter mappen %x - -Updating file %x -Oppdaterer fil %x - -Updating symbolic link %x -Oppdaterer symbolsk link %x - -Verifying file %x -Verifiserer filen %x - -Updating attributes of %x -Oppdaterer attributter for %x - -%x and %y have different content. - - -Data verification error: - - -Creating a Volume Shadow Copy for %x... -Oppretter VSS kopi for %x... - -Target folder %x already existing. -Destinasjonsmappen %x finnes allerede. - -Target folder input field must not be empty. -Destinasjonsmappen skal angis. - -Source folder %x not found. -Kildemappen %x ble ikke funnet. - -Please enter a target folder for versioning. -Angi mappe til versionering. - -The following items have unresolved conflicts and will not be synchronized: -Følgende mapper har uløste konflikter og synkroniseres ikke: - -The following folders are significantly different. Make sure you have selected the correct folders for synchronization. - - -Not enough free disk space available in: -Ikke nok ledig diskplass på: - -Required: -Krav: - -Available: -Tilgjengelig: - -Multiple folder pairs write to a common subfolder. Please review your configuration. -Flere mappepar til er skrevet til en felles undermappe. Se konfigureringen. - -Synchronizing folder pair: -Synkroniserer mappepar: - -Generating database... -Oppretter database... - -job name -Jobbnavn - -Synchronization stopped -Synkronisering avbrudt - -Stopped -Avbrutt - -Synchronization completed with errors -Synkronisering gjennomført med feil - -Synchronization completed with warnings -Synkronisering gjennomført med advarsel - -Warning -Advarsel - -Nothing to synchronize -Alt er synkronisert - -Synchronization completed successfully -Synkronisering gjennomført - -Cleaning up old log files... -Fjerner gamle loggfiler - -You can switch to FreeFileSync's main window to resolve this issue. -Skift til FreeFileSyncs hovedvindu for at løse problemet. - -&Don't show this warning again -&Vis ikke igen - -&Ignore -&Ignorer - -&Switch -&Skift - -Switching to FreeFileSync's main window -Skifter til hovedvinduet - - -Automatic retry in 1 second... -Automatic retry in %x seconds... - - -Prøver igjen om 1 sekund... -Prøver igjen om %x sekunder... - - -&Ignore subsequent errors -&Ignorer etterfølgende feil - -Retrying operation... -Prøver igen... - -Serious Error -Kritisk feil - -Check for Program Updates -Søk etter oppdatering - -A new version of FreeFileSync is available: -Oppdatering tilgjengelig: - -Download now? -Last ned nå? - -&Download -&Last ned - -FreeFileSync is up to date. -FreeFileSync er oppdatert. - -Unable to connect to www.freefilesync.org. -Kan ikke koble til www.freefilesync.org - -Cannot find current FreeFileSync version number online. Do you want to check manually? -Kunne ikke finne FreeFileSync's versjonsnummer online. Vil du kontrollere manuelt? - -&Check -&Kontroller - -Symlink -Symlink - -Folder -Mappe - -Full path -Full sti - -Name -Navn - -Relative folder -Relativ mappe - -Base folder -Hovedmappe - -Size -Størrelse - -Date -Dato - -Extension -Filtype - -Category -Status - -Action -Handling - -Local comparison settings -Lokale sammenlignings-instillinger - -Local synchronization settings -Lokale synkroniserings-instillinger - -Local filter -Lokalt filter - -Active -Aktiv - -None -Ingen - -Remove local settings -Fjern lokale instillinger - -Clear local filter -Slett lokalt filter - -Copy -Kopiér - -Paste -Lim inn - -Local Synchronization Settings -Lokale synkroniseringsinstillinger - -The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. - - -&New -&Ny - -&Save -&Lagre - -Save as &batch job... -Lagre som &batchfil - -Start &comparison -Start &sammenligning - -C&omparison settings -S&ammenligner instillinger - -&Filter settings -&Filtrer instillinger - -S&ynchronization settings -S&ynkroniserings-instillinger - -Start &synchronization -Start &synkronisering - -&Actions -&Handling - -&Options -&Valg - -&Language -&Språk - -&Find... -&Søk - -&Reset layout -&Reset layout - -&Export file list... -&Eksporter filliste... - -&Tools -&Verktøy - -&Check for new version -&Søk etter oppdatering - -&Check now -&Søk nå - -Check &automatically once a week -Søk &automatisk en gang i uken - -Cancel -Avbryt - -Compare -Analysér - -Synchronize -Synkronisér - -Add folder pair -Tilføy mappepar - -Remove folder pair -Fjern mappepar - -Select SFTP folder - - -Swap sides -Bytt side - -Close search bar -Lukk søkelinje - -Find: -Søk: - -Match case -Treffølsomhet (a/A) - -New -Ny - -Open... -Åpne... - -Save -Lagre - -Save as... -Lagre som - -View type: -Visning: - -Select view: -Velg visning: - -Statistics: -Statistikk: - -Number of files and folders that will be deleted -Antall filer og mapper som slettes - -Number of files that will be updated -Antall filer som vil bli oppdatert - -Number of files and folders that will be created -Antall filer og mapper som vil bli opprettet - -Total bytes to copy -Antal bytes som kopieres - -Use local settings: -Bruk lokale instillinger - -Select a variant: -Velg metode: - -Identify equal files by comparing modification time and size. -Gjennkjenn like filer etter filtid og størrelse. - -Identify equal files by comparing the file content. -Gjennkjenn like filer etter innhold. - -&Ignore time shift (in hours) - - -Consider file times with specified offset as equal -Vurder filtidspunkt med spesifisert oppstilling som like - -Handle daylight saving time -Behandle sommertid - -Include &symbolic links: - - -&Follow - - -&Direct - - -More information -Mer informasjon - -Local settings: -Lokale instillinger - -Include: -Inkludér: - -Exclude: -Ekskludér: - -Show examples -Vis eksempler - -Time span: -Intervall: - -File size: -Filstørrelse: - -Minimum: -Minimum: - -Maximum: -Maksimum: - -Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. -Angi filterregler til ekskludering av bestemte filer fra synkroniseringen. Filstier skal relatere til kildemappene. - -C&lear -F&jern - -Detect moved files -Gjennkjenn flyttede filer - - -- Not supported by all file systems -- Requires and creates database files -- Detection not available for first sync - - - -Detect synchronization directions with the help of database files -Gjennkjenn synkretninger ved hjelp av databasefiler - -Delete files: -Slett filer: - -&Permanent -&Permanent - -Delete or overwrite files permanently -Slett eller overskriv filer permanent - -&Recycle bin -&Papirkurv - -Back up deleted and overwritten files in the recycle bin -Backup slettede og overskrevne filer i papirkurven - -&Versioning -&Versjonering - -Move files to a user-defined folder -Flytt filer til brukerdefinert mappe - -Naming convention: -Navneregler: - -Handle errors: -Feilhåndtering: - -Hide all error and warning messages -Skjul feilmeldinger og advarsler - -&Pop-up -&Pop-up - -Show pop-up on errors or warnings -Vis feilmeldinger og advarsler - -On completion: -Når gjennomført: - -OK -OK - -Enter your SFTP login details: - - -Server name or IP address: - - -Examples: - - -User name: - - -Password: - - -&Show password - - -Directory on server: - - - - -Start synchronization now? -Synkroniser nå? - -Variant: -Jobbtype: - -&Don't show this dialog again -&Ikke vis igjen - -Arrange folder pair - - -Items found: -Mapper funnet: - -Time remaining: -Resterende tid: - -Time elapsed: -Brukt tid: - -Synchronizing... -Synkroniserer... - -Minimize to notification area -Minimér til systemfeltet - -Bytes copied: -Byte kopiert - -Close -Lukk - -&Pause -&Pause - -Stop -Stopp - -Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x -Oppret batchfil til automatisk synkronisering. Start ved aå dobbeltklikke på filen eller planlegg via oppgaveplanlegger: %x - -&Stop -&Stopp - -Stop synchronization at first error -Stopp synkronisering ved første feil - -Run minimized -Kjør minimert - -Save log: -Lagre logg: - -Limit: -Grense: - -Limit maximum number of log files -Begrens antall rapporter - -How can I schedule a batch job? -Hvordan opprettes en batchfil? - -The following settings are used for all synchronization jobs. -Disse innstillinger gjelder alle synkroniseringer. - -Fail-safe file copy -Sikker filkopiering - - -Copy to a temporary file (*.ffs_tmp) before overwriting target. -This guarantees a consistent state even in case of a serious error. - -Kopiér til midlertidig fil (*.ffs_tmp) før overskriving. Sikrer prosessen ved alvorlige feil. - -(recommended) -(anbefalt) - -Copy locked files -Kopier låste filer - -Copy shared or locked files using the Volume Shadow Copy Service. -Kopiér delte eller låste filer med VSS kopiering. - -(requires administrator rights) -(administrator) - -Copy file access permissions -Kopier adgangstillatelser - -Transfer file and folder permissions. -Overfør fil og mappetillatelser. - -Automatic retry on error: -Antall forsøk ved feil: - -Retry count: -Antall forsøk: - -Delay (in seconds): -Forsinkelse (sek): - -Customize context menu: -Tilpass kontekstmeny: - -Description -Beskrivelse - -Show hidden dialogs again -Vis skjulte vinduer - -Show all permanently hidden dialogs and warning messages again -Vis alle vinduer og advarsler igjen - -&Default -&Standard - -Source code written in C++ using: -Kildekoden er skrevet i C++ med hjelp fra: - -If you like FreeFileSync: -Hvis du liker FreeFileSync: - -Donate with PayPal -Donér med PayPal - -Feedback and suggestions are welcome -Kritikk og forslag er ønsket - -Homepage -Hjemmeside - -Email -Email - -Published under the GNU General Public License -Utgitt under GNU General Public Licence - -Many thanks for localization: -Takk for oversettelse: - -SSH File Transfer Protocol - - -Save as Batch Job -Lagre som batchfil - -Delete Items -Slett mapperr - -Options -Valg - -Select Time Span -Velg tidsintervall - -&Preferences - - -Main Bar -Hovedlinje - -Folder Pairs -Mappepar - -Find -Søk - -View Settings -Visninger - -Configuration -Innstilling - -Overview -Oversikt - -Confirm -Bekreft - - -Do you really want to execute the command %y for one item? -Do you really want to execute the command %y for %x items? - - -Vil du kjøre kommandoen %y for 1 mappe? -Vil du kjøre kommandoen %y for %x mapper? - - -&Execute -&Utfør - - -1 directory -%x directories - - -1 mappe -%x mapper - - - -1 file -%x files - - -1 fil -%x filer - - - -Showing %y of 1 row -Showing %y of %x rows - - -Viser %y av 1 rekke -Viser %y av %x rekker - - -Set direction: -Retning: - -multiple selection -velg flere - -Include via filter: -Inkludér via filter: - -Exclude via filter: -Ekskluder m. filter: - -Include temporarily -Inkluder midlertidig - -Exclude temporarily -Ekskluder midlertidig - -Delete -Slett - -Include all -Velg alle - -Exclude all -Ekskluder alle - -Show icons: -Vis ikoner: - -Small -Små - -Medium -Medium - -Large -Store - -Select time span... -Velg tidsinterval... - -Show "%x" -Vis "%x" - -Last session -Siste oppgave - -Folder Comparison and Synchronization -Mappeanalyse og synkronisering - -Configuration saved -Lagrede instillinger - -FreeFileSync batch -FreeFileSync batchfil - -Do you want to save changes to %x? -Vil du lagre endringer i %x? - -Never save &changes -&Aldri lagre endringer - -Do&n't save -&Ikke lagre - -Remove entry from list - - -Synchronization Settings -Synkroniseringsinnstillinger - -Clear filter -Slett filter - -Show files that exist on left side only -Vis filer som kun finnes på venstre side - -Show files that exist on right side only -Vis filer som kun finnes på høyre side - -Show files that are newer on left -Vis nyere filer på venstre side - -Show files that are newer on right -Vis nyere filer på høyre side - -Show files that are equal -Vis like filer - -Show files that are different -Vis ulike filer - -Show conflicts -Vis konflikter - -Show files that will be created on the left side -Vis filer som opprettes på venstre side - -Show files that will be created on the right side -Vis filer som opprettes på høyre side - -Show files that will be deleted on the left side -Vis filer som slettes på venstre side - -Show files that will be deleted on the right side -Vis filer som slettes på høyre side - -Show files that will be updated on the left side -Vis filer som vil bli oppdaters på venstre side - -Show files that will be updated on the right side -Vis filer som vil bli oppdatert på høyre side - -Show files that won't be copied -Vis filer som ikke kopieres - -Show filtered or temporarily excluded files -Vis filtrerte eller midlertidig ekskluderte filer - -Save as default - - -Filter -Filter - -All files are in sync -Alt er synkronisert - -Cannot find %x -Kan ikke finne %x - -Move up - - -Move down - - -Comma-separated values -Kommaoppdelte verdier - -File list exported -Fillisten ble eksportert - -Searching for program updates... -Søker etter oppdatering... - -Close progress dialog -Lukk dialogen - -Log off -Logg av - -Standby -Standby - -Shut down -Avslutt - -Scanning... -Skanner... - -Comparing content... -Analyserer innhold... - -Info -Info - -Select all -Velg alt - -Paused -Pauset - -Initializing... -Forbereder... - -Completed -Gjennomført - -&Continue -&Fortsett - -Progress -Fremskritt - -Log -Logg - - -Do you really want to move the following item to the recycle bin? -Do you really want to move the following %x items to the recycle bin? - - -Vil du flytte følgende mappe til papirkurven? -Vil du flytte følgende %x mapper til papirkurven? - - -Move -Flytt - - -Do you really want to delete the following item? -Do you really want to delete the following %x items? - - -Vil du slette følgende mappe? -Vil du slette følgende %x mapper? - - -Preferences -Egenskaper - -Copy DACL, SACL, Owner, Group - - -Integrate external applications into context menu. The following macros are available: -Integrer eksterne programmer i kontekstmeny. Bruk følgende makroer: - -- full file or folder name -Komplett fil- eller mappenavn - -- folder part only -Kun mappedelen - -- Other side's counterpart to %item_path% -Motsatt sides motstykke til %item_path% - -- Other side's counterpart to %item_folder% -Motsatt sides motstykke til %item_folder% - -Show hidden dialogs and warning messages again? -Vis gjemte vinduer og advarsler igjen? - -&Show -&Vis - -Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. -Finn og fordel endringer på begge sider. Slettede filer, omdøpninger og konflikter finnes automatisk i en database. - -Create a mirror backup of the left folder by adapting the right folder to match. -Oppret speiling av venstre mappe ved å tilpasse den høyre mappe - -Copy new and updated files to the right folder. -Kopier nye og oppdaterte filer til høyre mappe. - -Configure your own synchronization rules. -Oppret dine egne synkroniseringsregler. - -Today -I dag - -This week -Denne uke - -This month -Denne måned - -This year -Dette år - -Last x days -Siste x dager - -Byte -Byte - -KB -KB - -MB -MB - -Replace -Erstat - -Move files and replace if existing -Flytt fil og erstatt eventuelt eksisterende - -Time stamp -Tidsstempel - -Append a time stamp to each file name -Legg til tidsstempel til hvert filnavn - -Comparison -Sammenligning - -Synchronization -Synkronisering - -Leave as unresolved conflict -Etterlat som uløst konflikt - -File -Fil - -YYYY-MM-DD hhmmss -YYYY-MM-DD hhmmss - -Files -Filer - -Items -Mapper - -Percentage -Prosent - -Unable to register to receive system messages. -Kunne ikke registrere mottakelse av systembesjkeder. - -Unable to register device notifications for %x. - - -Cannot monitor directory %x. -Kan ikke overvåke mappen %x. - -The file is locked by another process: -Filen er låst av en annen prosess: - -Cannot write file attributes of %x. -Kan ikke skrive filattributter til %x. - -Cannot read security context of %x. -Kan ikke lese sikkerhetsinnstillinger på %x. - -Cannot write security context of %x. -Kan ikke skrive sikkerhetsinnstillinger til %x. - -Cannot read permissions of %x. -Kan ikke lese tillatelsene på %x. - -Cannot copy permissions from %x to %y. - - -Cannot find system function %x. -Kan ikke finne systemfunksjonen %x. - -Cannot copy attributes from %x to %y. - - -Cannot copy file %x to %y. -Kan ikke kopiere filen %x til %y. - -Type of item %x is not supported: -Filtypen %x støttes ikke: - -%x TB -%x TB - -%x PB -%x PB - - -1 min -%x min - - -1 min -%x min - - - -1 hour -%x hours - - -1 time -%x timer - - - -1 day -%x days - - -1 dag -%x dager - - -Cannot set privilege %x. -Kan ikke sette %x privilegier. - -Unable to suspend system sleep mode. -Kunne ikke oppheve standby. - -Cannot change process I/O priorities. -Kan ikke endre I/O prioriteter. - -Checking recycle bin failed for folder %x. -Sjekk papirkurv-feil for mappen %x - -The following XML elements could not be read: - - -Configuration file %x is incomplete. The missing elements will be set to their default values. - - -Prepare installation -Forbered installering - -Choose which components you want to install. -Velg hva du vil installere - -Select installation type: -Velg installasjonstype - -Local -Lokal - -Portable -Portabel (USB) - -recommended -anbefalt - -Save settings to "%APPDATA%\FreeFileSync" -Lagre innstillinger til "%APPDATA%\FreeFileSync" - -Register FreeFileSync file extensions -Registrer FreeFileSync filendelser - -Create Explorer context menu entries -Legg til i høyreklikkmeny - -Save settings in installation directory -Lagre innstillinger i installasjonsmappen - -Do not write to Registry -Ikke skriv til registeret - -Just copy the files -Bare kopier filene - -Choose a directory for installation: -Velg en mappe for installasjon: - -Create shortcuts: -Opprett snarveier: - -Desktop -Skrivebord - -Start menu -Startmeny - -Registering FreeFileSync file extensions -Registrerer FreeFileSync filendelser - -Unregistering FreeFileSync file extensions -Avregistrerer FreeFileSync filendelser - -FreeFileSync Configuration -FreeFileSync konfigurering - -FreeFileSync Batch File -FreeFileSync Batch Fil - -FreeFileSync Synchronization Database -FreeFileSync Synkronisering - -RealtimeSync Configuration -RealtimeSync konfigurering - -Edit with FreeFileSync -Rediger med FreeFileSync - diff --git a/FreeFileSync/Build/Languages/outdated/arabic.lng b/FreeFileSync/Build/Languages/outdated/arabic.lng new file mode 100644 index 00000000..7f0bd890 --- /dev/null +++ b/FreeFileSync/Build/Languages/outdated/arabic.lng @@ -0,0 +1,1790 @@ +
    + العربية + MEinea + ar + flag_arabic.png + 6 + n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5 +
    + +Configuration file %x is incomplete. The missing elements will be set to their default values. + + +The following XML elements could not be read: + + +Cannot copy attributes from %x to %y. + + +Cannot copy permissions from %x to %y. + + +Unable to register device notifications for %x. + + +Copy DACL, SACL, Owner, Group + + +Please enter a target folder. + + + +Copy the following item to another folder? +Copy the following %x items to another folder? + + + +Move down + + +Move up + + +Save as default + + +Remove entry from list + + +Copy to... + + +Copy items + + +SSH File Transfer Protocol + + +&Copy + + +&Overwrite existing files + + +&Keep relative paths + + +Arrange folder pair + + +Directory on server: + + +&Show password + + +Password: + + +User name: + + +Examples: + + +Port: + + +Server name or IP address: + + +Enter your SFTP login details: + + + +- Not supported by all file systems +- Requires and creates database files +- Detection not available for first sync + + + +&Direct + + +&Follow + + +Include &symbolic links: + + +&Ignore time shift (in hours) + + +Select SFTP folder + + +&Preferences + + +The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. + + +The following folders are significantly different. Make sure you have selected the correct folders for synchronization. + + +Data verification error: + + +%x and %y have different content. + + +Time out while searching for folder %x. + + +Failed to connect to SFTP server %x. + + +Cannot determine free disk space for %x. + + +Cannot find device %x. + + +Cannot find %x. + + +Operation not supported for different base folder types. + + + +Unexpected size of data stream. +Expected: %x bytes +Actual: %y bytes + + + +Open configuration for editing without executing it. + + +Cannot find file %x. + + +Both sides have changed since last synchronization. +كلا الجانبين قد تغير منذ المزامنة الأخيرة. + +Cannot determine sync-direction: +لا يمكن تحديد اتجاه المزامنة: + +No change since last synchronization. +لم يطرأ أي تغيير منذ المزامنة الأخيرة. + +The database entry is not in sync considering current settings. +مدخلات قواعد البيانات غير متزامنة حسب إعدادات المزامنة الحالية. + +Setting default synchronization directions: Old files will be overwritten with newer files. +تحديد الاتجاهات الافتراضية للمزامنة: ستتم الكتابة فوق الملفات القديمة بالملفات الأحدث. + +Creating folder %x +إنشاء مجلد %x + +Creating file %x +إنشاء الملف %x + +Creating symbolic link %x +إنشاء ارتباط رمزي %x + +Moving file %x to the recycle bin +نقل الملف %x إلى سلة المهملات + +Moving folder %x to the recycle bin +نقل المجلد %x إلى سلة المهملات + +Moving symbolic link %x to the recycle bin +نقل الارتباط الرمزي %x إلى سلة المهملات + +Deleting file %x +حذف الملف %x + +Deleting folder %x +حذف المجلد %x + +Deleting symbolic link %x +حذف الارتباط الرمزي %x + +Checking recycle bin availability for folder %x... +التحقق من توافر سلة المحذوفات من أجل المجلد %x... + +The recycle bin is not available for the following folders. Files will be deleted permanently instead: +سلة المهملات غير متوفرة للمجلدات التالية. سيتم حذف الملفات بشكل نهائي بدلاً عن ذلك: + +An exception occurred +حدث استثناء + +A directory path is expected after %x. +مسار متوقع بعد %x. + +Syntax error +خطأ في البنية + +File %x does not contain a valid configuration. +لا يحتوي الملف %x تكويناً صحيحاً. + +Unequal number of left and right directories specified. +لم يتم تحديد عدد متساوي من المسارات على الطرفين. + +The config file must not contain settings at directory pair level when directories are set via command line. +يجب أن يحتوي ملف الخيارات الخيارات على مستوى أزواج المسارات عند تحديد المسارات بواسطة سطر الأوامر. + +Directories cannot be set for more than one configuration file. +لا يمكن اختيار المسارات لأكثر من ملف خيارات واحد. + +Command line +سطر الأوامر + +Syntax: +بنية: + +global config file: +ملف الخيارات العام: + +config files: +ملفات الخيارات: + +directory +مسار + +Path to an alternate GlobalSettings.xml file. +تحديد مسار مختلف لملف GlobalSettings.xml. + +Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. +أي عدد من ملفات خيارات FreeFileSyn أو\و _gui and/or .ffs_batch. + +Any number of alternative directory pairs for at most one config file. +أي عدد من أزواج المسارات البديلة من أجل ملف خيارات واحد. + +Cannot find the following folders: +تعذر العثور على المجلدات التالية: + +You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. +بإمكانك إهمال هذا الخطأ لاعتبار كل مجلد على أنه مجلد فارغ. سيتم إنشاء المجلدات تلقائياً خلال المزامنة. + +A folder input field is empty. +حقل إدخال خاص بمجلد فارغ. + +The corresponding folder will be considered as empty. +سيتم اعتبار المجلد الموافق كمجلد فارغ. + +The following folder paths are dependent from each other: +مسارات المجلدات التالية معتمدة على بعضها: + +File %x has an invalid date. +يحتوي الملف %x تاريخ غير صالح. + +Date: +التاريخ: + +Files %x have the same date but a different size. +الملفات %x لها نفس التاريخ ولكن حجم مختلف. + +Size: +الحجم: + +Content comparison was skipped for excluded files %x. +تم تجاهل مقارنة المحتوى للملفات المستثناة %x. + +Items differ in attributes only +العناصر مختلفة في السمات فقط + +Resolving symbolic link %x +جاري حل المسار الرمزي %x + +Comparing content of files %x +مقارنة محتويات الملفات %x + +Generating file list... +إنشاء قائمة الملفات... + +Starting comparison +بدأ عملية المقارنة + +Calculating sync directions... +جاري حساب اتجاهات المزامنة... + +Out of memory. +نفدت الذاكرة. + +Item exists on left side only +العنصر موجود على الجانب الأيمن فقط + +Item exists on right side only +العنصر موجود في الجانب الأيسر فقط + +Left side is newer +الجانب الأيمن أحدث + +Right side is newer +الجانب الأيسر أحدث + +Items have different content +العناصر مختلفة بالمحتوى + +Both sides are equal +كلا الجانبين متماثلان + +Conflict/item cannot be categorized +الاختلاف\العنصر لا يمكن تصنيفه + +Copy new item to left +نسخ عنصر جديد إلى اليمين + +Copy new item to right +نسخ عنصر جديد إلى اليسار + +Delete left item +حذف العنصر الأيمن + +Delete right item +حذف العنصر الأيسر + +Move file on left +نقل ملف على اليمين + +Move file on right +نقل ملف على اليسار + +Update left item +تحديث العنصر اليميني + +Update right item +تحديث العنصر اليساري + +Do nothing +لا تفعل شيئا + +Update attributes on left +تحديث السمات على اليمين + +Update attributes on right +تحديث السمات على اليسار + +Cannot read file %x. +لا يمكن قراءة الملف %x. + +Cannot write permissions of %x. +لا يمكن كتابة أذونات %x. + +Cannot write file %x. +لا يمكن كتابة الملف %x. + +Cannot copy symbolic link %x to %y. +لا يمكن نسخ الرابط الرمزي من %x إلى %y. + +Cannot move file %x to %y. +لا يمكن نقل الملف %x إلى %y. + +Cannot enumerate directory %x. +لا يمكن تعداد المسار %x. + +Cannot read file attributes of %x. +لا يمكن قراءة سمات الملف %x. + +Cannot open file %x. +تعذر فتح الملف %x. + +Cannot create directory %x. +لا يمكن إنشاء المسار %x. + +Cannot delete directory %x. +لا يمكن حذف المسار %x. + +Cannot delete file %x. +لا يمكن حذف الملف %x. + +Cannot write modification time of %x. +لا يمكن كتابة وقت تعديل %x. + +Cannot determine final path for %x. +تعذر تحديد المسار النهائي لـ %x. + +Cannot resolve symbolic link %x. +لا يمكن حل الارتباط الرمزي %x. + +Unable to move %x to the recycle bin. +تعذر نقل %x إلى سلة المحذوفات. + +Cannot open directory %x. +لا يمكن فتح المسار %x. + +Incorrect command line: +سطر أوامر خاطئ: + +Error Code %x: +خطأ رقم %x: + + +1 byte +%x bytes + + +0 byte +1 byte +2 bytes +%x bytes +%x bytes +%x bytes + + +%x MB +%x MB + +%x KB +%x KB + +%x GB +%x GB + +Cannot load file %x. +لا يمكن فتح الملف %x. + +Database file %x is incompatible. +ملف قاعدة البيانات %x غير متوافق. + +Initial synchronization: +المزامنة الأولية: + +Database file %x does not yet exist. +ملف قاعدة البيانات %x غير موجود حتى الآن. + +Database file is corrupt: +ملف قاعدة البيانات معطوب: + +Database files do not share a common session. +ملفات قواعد البيانات لا تشترك في جلسة عمل مشتركة. + +Searching for folder %x... +البحث عن المجلد %x... + +Cannot get process information. +لا يمكن الحصول على معلومات العملية. + +Waiting while directory is locked: +انتظر بينما يتم إنشاء قفل للمسار: + +Lock owner: +صاحب القفل: + + +1 sec +%x sec + + +0 ثانية +1 ثانية واحدة +2 ثانيتين +%x ثواني +%x ثانية +%x ثانية + + +Detecting abandoned lock... +اكتشاف قفل مهمل... + +Saving file %x... +جاري حفظ الملف %x... + +Items processed: +معالجة العناصر: + +Items remaining: +العناصر المتبقية: + +Total time: +مجموع الوقت: + +Error parsing file %x, row %y, column %z. +حدث خطأ أثناء تحليل الملف %x، الصف %y، و العمود %z. + +Cannot set directory lock for %x. +تعذر إنشاء قفل للمسار %x. + + +1 thread +%x threads + + +0 بند +1 بند واحد +2 بندان +%x بنود +%x بنداً +%x بند + + +Scanning: +الفحص: + +/sec +\ثانية + +%x items/sec +%x عنصر\الثانية + +Show in Explorer +إظهار في المستكشف + +Open with default application +فتح باستخدام التطبيق الافتراضي + +Browse directory +تصفح المسار + +Cannot access the Volume Shadow Copy Service. +لا يمكن الوصول إلى خدمة "نسخ الظل لوحدة التخزين". + +Please use FreeFileSync 64-bit version to create shadow copies on this system. +الرجاء استخدام إصدار الـ 64-bit للبرنامج لإنشاء ملفات الظل الاحتياطية على هذا النظام. + +Cannot determine volume name for %x. +تعذر تحديد اسم الوسط %x. + +Volume name %x is not part of file path %y. +اسم وحدة التخزين %x ليس جزءاُ من اسم الملف %y. + +Stop requested: Waiting for current operation to finish... +طلب إحباط المهمة: في انتظار انتهاء المهمة الحالية... + +Unable to create time stamp for versioning: +تعذر إنشاء بصمة زمنية من أجل المفاضلة الزمنية: + +Drag && drop +سحب و إفلات + +Cannot find folder %x. +تعذر العثور على المجلد %x. + +Select a folder +تحديد مجلد + +&Open... +&فتح... + +Save &as... +&حفظ باسم... + +E&xit +&إغلاق + +&File +&ملف + +&View help +إ&ظهار المساعدة + +&About +&حول + +&Help +&تعليمات + +Usage: +الاستخدام: + +1. Select folders to watch. +1. حدد المجلدات للمتابعة. + +2. Enter a command line. +2. إدخال سطر أوامر. + +3. Press 'Start'. +3. اضغط على 'ابدأ'. + +To get started just import a .ffs_batch file. +للبدء قم باستيراد ملف .ffs_batch. + +Folders to watch: +المجلدات للمتابعة: + +Add folder +إضافة مجلد + +Remove folder +إزالة مجلد + +Browse +تصفح + +Idle time (in seconds): +وقت الخمول (بالثانية): + +Idle time between last detected change and execution of command +وقت الخمول بين آخر تغيير تم الكشف عنه وتنفيذ الأوامر + +Command line: +سطر الأوامر: + + +The command is triggered if: +- files or subfolders change +- new folders arrive (e.g. USB stick insert) + + +يتم تشغيل الأمر إذا: +-حدوث تغيير في الملفات أو المجلدات الفرعية +-ظهور مجلدات جديدة (مثال: إدخال USB stick) + + +&Start +&ابدأ + +About +حول + +Build: %x +بناء: %x + +All files +جميع الملفات + +Automated Synchronization +مزامنة تلقائية + +Directory monitoring active +مراقبة المسارات فعالة + +Waiting until all directories are available... +انتظر حتى توفر جميع المسارات... + +Error +خطأ + +&Restore +&استعادة + +&Show error +إ&ظهار الخطأ + +&Quit +إ&نهاء + +&Retry +إ&عادة المحاولة + +File content +محتوى الملف + +File time and size +تاريخ الملف و حجمه + +Two way +بالاتجاهين + +Mirror +انعكاس + +Update +تحديث + +Custom +مخصص + +Multiple... +متعددة... + +Moving file %x to %y +نقل الملف %x إلى %y + +Moving folder %x to %y +نقل المجلد %x إلى %y + +Moving symbolic link %x to %y +نقل الارتباط الرمزي %x إلى %y + +Removing old versions... +إزالة الإصدارات القديمة... + +Updating file %x +جاري تحديث الملف %x + +Updating symbolic link %x +جاري تحديث المسار الرمزي %x + +Verifying file %x +التحقق من الملف %x + +Updating attributes of %x +تحديث سمات %x + +Creating a Volume Shadow Copy for %x... +جاري إنشاء نسخة ظل وسيطة لـ %x... + +Target folder %x already existing. +المجلد الهدف %x موجود سابقاً. + +Target folder input field must not be empty. +يجب أن لا يكون حقل إدخال المجلد الهدف فارغاً. + +Source folder %x not found. +لم يتم العثور على المجلد المصدر %x. + +Please enter a target folder for versioning. +الرجاء تحديد مجلد هدف من أجل الوسم حسب الإصدار. + +The following items have unresolved conflicts and will not be synchronized: +العناصر التالية لم تحل اختلافاتها، و لن يتم مزامنتها: + +Not enough free disk space available in: +المساحة الحرة المتوفرة على القرص غير كافية: + +Required: +مطلوب: + +Available: +متاح: + +Multiple folder pairs write to a common subfolder. Please review your configuration. +عدد من أزواج المجلدات يكتب إلى مجلد فرعي مشترك. رجاءً أعد النظر في خياراتك. + +Synchronizing folder pair: +مزامنة زوج مجلدات: + +Generating database... +إنشاء قاعدة بيانات... + +job name +اسم المهمة + +Synchronization stopped +توقفت عملية المزامنة + +Stopped +توقف + +Synchronization completed with errors +انتهاء عملية المزامنة مع وجود أخطء + +Synchronization completed with warnings +انتهاء عملية المزامنة مع وجود تحذيرات + +Warning +تحذير + +Nothing to synchronize +لا يوجد شيء للمزامنة + +Synchronization completed successfully +تمت المزامنة بنجاح + +Cleaning up old log files... +جاري تنظيف ملفات المتابعة القديمة... + +You can switch to FreeFileSync's main window to resolve this issue. +بإمكانك العودة إلى نافذة FreeFileSync الرئيسية لحل هذه المشكلة. + +&Don't show this warning again +&لا تظهر هذا التنبيه مرة ثانية + +&Ignore +&تجاهل + +&Switch +&تبديل + +Switching to FreeFileSync's main window +العودة إلى نافذة FreeFileSync الرئيسية + + +Automatic retry in 1 second... +Automatic retry in %x seconds... + + +إعادة المحاولة بعد 0 ثانية... +إعادة المحاولة بعد 1 ثانية واحدة... +إعادة المحاولة بعد 2 ثانيتين... +إعادة المحاولة بعد %x ثواني... +إعادة المحاولة بعد %x ثانية... +إعادة المحاولة بعد %x ثانية... + + +&Ignore subsequent errors +&تجاهلا الأخطاء المماثلة + +Retrying operation... +إعادة محاولة العملية... + +Serious Error +خطأ فادح + +Check for Program Updates +تفقد وجود تحديثات للبرنامج + +A new version of FreeFileSync is available: +يتوفر إصدار جديد من FreeFileSync: + +Download now? +تنزيل الآن؟ + +&Download +&تنزيل + +FreeFileSync is up to date. +البرنامج هو الأحدث حتى الآن. + +Unable to connect to www.freefilesync.org. +تعذر الاتصال بـ www.freefilesync.org. + +Cannot find current FreeFileSync version number online. Do you want to check manually? +لم نستطع العثور على على رقم إصدار FreeFileSync على الشبكة. هل تريد التحقق يدوياً؟ + +&Check +&تحقق + +Symlink +ارتباط-رمزي + +Folder +المجلد + +Full path +المسار الكامل + +Name +الاسم + +Relative folder +مجلد نسبي + +Base folder +المجلد الأساسي (القاعدي) + +Size +الحجم + +Date +تاريخ + +Extension +اللاحقة + +Category +الفئة + +Action +التصرف + +Local comparison settings +إعدادات المقارنة المحلية + +Local synchronization settings +إعدادات المزامنة المحلية + +Local filter +فلتر محلي + +Active +مفعل + +None +لا شيء + +Remove local settings +إزالة الإعدادات المحلية + +Clear local filter +إزالة الفلتر المحلي + +Copy +نسخ + +Paste +لصق + +Local Synchronization Settings +إعدادات المزامنة المحلية + +&New +&جديد + +&Save +&حفظ + +Save as &batch job... +&حفظ كمهمة دفعية... + +Start &comparison +بدأ الم&قارنة + +C&omparison settings +&مقارنة + +&Filter settings +إعدادات ال&فلتر + +S&ynchronization settings +إ&عدادات + +Start &synchronization +بدأ الم&زامنة + +&Actions +&مهام + +&Language +الل&غة + +&Find... +&بحث... + +&Reset layout +إعادة ال&تنسيق إلى الإفتراضي + +&Export file list... +&تصدير قائمة الملفات... + +&Tools +أ&دوات + +&Check for new version +ال&تحقق من وجود نسخة جديدة + +&Check now +&تحقق الآن + +Check &automatically once a week +&تحقق أوتوماتيكياً بشكل أسبوعي + +Cancel +إلغاء الأمر + +Compare +قارن + +Synchronize +مزامنة + +Add folder pair +إضافة زوج مجلدات + +Remove folder pair +إزالة زوج مجلدات + +Swap sides +مبادلة الجانبين + +Close search bar +إغلاق شريط البحث + +Find: +بحث: + +Match case +مطابقة حالة الأحرف (Match case) + +New +جديد + +Open... +فتح... + +Save +حفظ + +Save as... +حفظ كـ... + +View type: +عرض النوع: + +Select view: +اختيار نمط العرض: + +Statistics: +إحصائيات: + +Number of files and folders that will be deleted +عدد الملفات و المجلدات التي سيتم حذفها + +Number of files that will be updated +عدد الملفات التي سيتم تحديثها + +Number of files and folders that will be created +عدد الملفات و المجلدات التي سيتم إنشاؤها + +Total bytes to copy +إجمالي عدد الـ bytes التي سيتم نسخها + +Use local settings: +استخدام الإعدادات المحلية: + +Select a variant: +اختيار بديل: + +Identify equal files by comparing modification time and size. +التعرف على الملفات المتساوية عن طريق مقارنة التاريخ و الحجم. + +Identify equal files by comparing the file content. +التعرف على الملفات المتساوية عن طريق مقارنة محتوى الملف. + +Consider file times with specified offset as equal +اعتبار الملفات ذات الفارق الزمني المحدد و كأنها متساوية + +Handle daylight saving time +تعامل مع التوقيت الصيفي + +More information +المزيد من المعلومات + +Local settings: +الإعدادات المحلية: + +Include: +إدخال: + +Exclude: +استثناء: + +Show examples +إظهار أمثلة + +Time span: +المجال الزمني: + +File size: +حجم الملف: + +Minimum: +الحد الأدنى: + +Maximum: +الحد الأقصى: + +Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. +اختيار قوانين فلترة لاستثناء ملفات معينة من المزامنة. أدخل مسارات الملفات منسوبة إلى زوج المجلدات المقابل. + +C&lear +إ&زالة + +Detect moved files +اكتشاف الملفات المنقولة + +Detect synchronization directions with the help of database files +تحديد اتجاه المزامنة بالاستعانة بقواعد بيانات الملفات + +Delete files: +حذف الملفات: + +&Permanent +&دائم + +Delete or overwrite files permanently +حذف أو الكتابة فوق الملفات بشكل دائم + +&Recycle bin +&سلة المهملات + +Back up deleted and overwritten files in the recycle bin +نسخ احتياطي للملفات المحذوفة و المستبدلة في سلة المهملات + +&Versioning +ال&وسم حسب الإصدار + +Move files to a user-defined folder +نقل الملفات إلى المجلد المحدد من قبل المستخدم + +Naming convention: +اصطلاح التسمية: + +Handle errors: +التعامل مع الأخطاء: + +Hide all error and warning messages +إخفاء جميع رسائل الأخطاء و التحذير + +&Pop-up +&منبثق + +Show pop-up on errors or warnings +إظهار إطارات منبثقة عند حصول أخطاء أو تحذيرات + +On completion: +عند الانتهاء: + +OK +موافق + +Start synchronization now? +بدأ المزامنة الآن؟ + +Variant: +بديل: + +&Don't show this dialog again +&لا تظهر نافذة الحوار هذه مرة ثانية + +Items found: +العناصر التي تم العثور عليها: + +Time remaining: +الوقت المتبقي: + +Time elapsed: +الوقت المنقضي: + +Synchronizing... +مزامنة... + +Minimize to notification area +تصغير إلى منطقة التنبيهات + +Bytes copied: +Bytes المنسوخة: + +Close +إغلاق + +&Pause +إ&يقاف مؤقت + +Stop +توقف + +Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x +إنشاء ملف دفعي من أجل عمليات المزامنة غير المحضورة. للبدأ, انقر نقراً مزدوجاً على الملف أو المهمة المجدولة في منظم المهام: %x + +&Stop +&توقف + +Stop synchronization at first error +إحباط المزامنة عند أول خطأ + +Run minimized +تشغيل بوضع التصغير + +Save log: +حفظ السجل: + +Limit: +حدود: + +Limit maximum number of log files +تقييد الحد الأقصى لعدد ملفات السجل + +How can I schedule a batch job? +كيف يمكنني جدولة مهمة دفعية؟ + +The following settings are used for all synchronization jobs. +هذه الإعدادات مستخدمة لجميع مهمات المزامنة. + +Fail-safe file copy +نسخ ملفات آمن من الفشل + + +Copy to a temporary file (*.ffs_tmp) before overwriting target. +This guarantees a consistent state even in case of a serious error. + + +قم بالنسخ إلى ملف مؤقت (*.ffs_tmp) قبل استبدال الملف الهدف. +هذه العملية تضمن حالة مستقرة حتى في حال حدوث خطأ فادح. + + +(recommended) +(موصى به) + +Copy locked files +نسخ الملفات المقفلة + +Copy shared or locked files using the Volume Shadow Copy Service. +نسخ الملفات المشتركة مع مستخدمين آخرين أو المقفولة باستخدام خدمة نسخ الظل الوسيط. + +(requires administrator rights) +(بحاجة امتيازات المدير) + +Copy file access permissions +نسخ أذونات الوصول إلى الملف + +Transfer file and folder permissions. +نقل أذونات الملفات و المجلدات. + +Automatic retry on error: +إعادة المحاولة بشكل تلقائي عند حصول خطأ: + +Retry count: +تعداد محاولات الإعادة: + +Delay (in seconds): +التأخير (بالثواني): + +Customize context menu: +تخصيص القائمة المحلية: + +Description +الوصف + +Show hidden dialogs again +إظهار التنبهات و نوافذ الحوار المخفية + +Show all permanently hidden dialogs and warning messages again +إعادة إظهار جميع التنبهات و نوافذ الحوار التي تم إخفاؤها + +&Default +الا&فتراضي + +Source code written in C++ using: +الرماز المصدري مكتوب بلغة C++ باستخدام: + +If you like FreeFileSync: +إذا أعجبك FreeFileSync: + +Donate with PayPal +تبرع باستخدام PayPal + +Feedback and suggestions are welcome +التعليقات و الاقتراحات موضع ترحيب + +Homepage +الصفحة الرئيسية + +Email +البريد الإلكتروني + +Published under the GNU General Public License +نشر تحت رخصة GNU General Public License + +Many thanks for localization: +شكرا جزيلا للترجمة: + +Save as Batch Job +حفظ كمهمة دفعية + +Delete Items +حذف العناصر + +Options +خيارات + +Select Time Span +اختيار المطال الزمني + +&Options +&خيارات + +Main Bar +الشريط الرئيسي + +Folder Pairs +أزواج المجلدات + +Find +بحث + +View Settings +عرض الإعدادات + +Configuration +التكوين + +Overview +نظرة عامة + +Confirm +تأكيد + + +Do you really want to execute the command %y for one item? +Do you really want to execute the command %y for %x items? + + +هل تريد حقاً تنفيذ العملية %y من أجل عنصر 0 +هل تريد حقاً تنفيذ العملية %y من أجل عنصر وحيد 1 +هل تريد حقاً تنفيذ العملية %y من أجل عنصرين اثنين 2 +هل تريد حقاً تنفيذ العملية %y من أجل %x عناصر +هل تريد حقاً تنفيذ العملية %y من أجل %x عنصراً +هل تريد حقاً تنفيذ العملية %y من أجل %x عنصر + + +&Execute +&تنفيذ + + +1 directory +%x directories + + +0 مسار +1 مسار واحد +2 مساران +%x مسارات +%x مساراً +%x مسار + + + +1 file +%x files + + +0 ملف +1 ملف واحد +2 ملفان +%x ملفات +%x ملفاً +%x ملف + + + +Showing %y of 1 row +Showing %y of %x rows + + +الظاهر %y من أصل سطر 0 +الظاهر %y من أصل سطر وحيد 1 +الظاهر %y من أصل سطرين اثنين 2 +الظاهر %y من أصل %x سطور +الظاهر %y من أصل %x سطراً +الظاهر %y من أصل %x سطر + + +Set direction: +تحديد الاتجاه: + +multiple selection +تحديد متعدد + +Include via filter: +تضمن عن طريق فلتر: + +Exclude via filter: +استبعاد باستخدام عامل الفلترة: + +Include temporarily +شمول مؤقتاً + +Exclude temporarily +استبعاد مؤقتاً + +Delete +حذف + +Include all +شمول الكل + +Exclude all +استبعاد الكل + +Show icons: +إظهار الأيقونات: + +Small +صغيرة + +Medium +متوسطة + +Large +كبيرة + +Select time span... +حدد المجال الزمني... + +Show "%x" +إظهار "%x" + +Last session +مصدر الجلسة + +Folder Comparison and Synchronization +مقارنة و مزامنة المجلد + +Configuration saved +تم حفظ التكوين + +FreeFileSync batch +دفعة FreeFileSync + +Do you want to save changes to %x? +هل تريد حفظ التغييرات إلى %x؟ + +Never save &changes +&لا تقم بحفظ التغيرات + +Do&n't save +&لا تحفظ + +Synchronization Settings +إعدادات المزامنة + +Clear filter +إزالة الفلاتر الحالية + +Show files that exist on left side only +إظهار الملفات الموجودة في الجانب الأيمن فقط + +Show files that exist on right side only +إظهار الملفات الموجودة في الجانب الأيسر فقط + +Show files that are newer on left +إظهار الملفات الأحدث في اليمين + +Show files that are newer on right +إظهار الملفات الأحدث في اليسار + +Show files that are equal +إظهار الملفات المتماثلة على الطرفين + +Show files that are different +إظهار الملفات المختلفة على الطرفين + +Show conflicts +إظهار الاختلافات + +Show files that will be created on the left side +إظهار الملفات التي سيتم إنشاؤها في الجانب الأيمن + +Show files that will be created on the right side +إظهار الملفات التي سيتم إنشاؤها في الجانب الأيسر + +Show files that will be deleted on the left side +إظهار الملفات التي سيتم حذفها من من الجانب الأيمن + +Show files that will be deleted on the right side +إظهار الملفات التي سيتم حذفها من الجانب الأيسر + +Show files that will be updated on the left side +إظهار الملفات التي سيتم تحديثها في الجانب الأيسر + +Show files that will be updated on the right side +إظهار الملفات التي سيتم تحديثها في الجانب الأيمن + +Show files that won't be copied +إظهار الملفات التي لن يتم نسخها + +Show filtered or temporarily excluded files +إظهار الملفات التي تم فلترتها أو استبعادها بشكل مؤقت + +Filter +عامل الفلترة + +All files are in sync +جميع الملفات في تزامن كامل + +Cannot find %x +لا يمكن العثور على %x + +Comma-separated values +قائمة قيم مفصولة بفواصل + +File list exported +تم تصدير قائمة الملفات + +Searching for program updates... +جاري البحث عن تحديثات للبرنامج... + +Close progress dialog +إنهاء نافذة حوار تقدم العملية + +Log off +تسجيل الخروج + +Standby +وضع الاستعداد + +Shut down +إيقاف التشغيل + +Scanning... +جاري الفحص... + +Comparing content... +مقارنة المحتوى... + +Info +معلومات + +Select all +اختيار الجميع + +Paused +تم الإيقاف مؤقتاً + +Initializing... +التجهيز للبدأ... + +Completed +انتهت العملية + +&Continue +&مواصلة + +Progress +التقدم + +Log +السجل + + +Do you really want to move the following item to the recycle bin? +Do you really want to move the following %x items to the recycle bin? + + +هل تريد حقاً نقل 0 ملف إلى سلة المهملات ؟ +هل تريد حقاً نقل هذا الملف الوحيد 1 إلى سلة المهملات ؟ +هل تريد حقاً نقل هذين الملفبن 2 إلى سلة المهملات ؟ +هل تريد حقاً نقل %x ملفات إلى سلة المهملات ؟ +هل تريد حقاً نقل %x ملفاً إلى سلة المهملات ؟ +هل تريد حقاً نقل %x ملف إلى سلة المهملات ؟ + + +Move +نقل + + +Do you really want to delete the following item? +Do you really want to delete the following %x items? + + +هل تريد حقاً حذف 0 ملف التالي ؟ +هل تريد حقاً حذف الملف 1 التالي ؟ +هل تريد حقاً حذف الملفين 2 التاليين ؟ +هل تريد حقاً حذف الـ %x ملفات التالية ؟ +هل تريد حقاً حذف الـ %x ملفاً التالية ؟ +هل تريد حقاً حذف الـ %x ملف التالية ؟ + + +Integrate external applications into context menu. The following macros are available: +دمج تطبيقات خارجية في قائمة السياق. تتوفر وحدات الماكرو التالية: + +- full file or folder name +- اسم الملف أو المجلد كاملاً + +- folder part only +- جزء مجلد فقط + +- Other side's counterpart to %item_path% +- النظير للجانب الآخر لـ %item_path% + +- Other side's counterpart to %item_folder% +- االنظير للجانب الآخر لـ %item_folder% + +Show hidden dialogs and warning messages again? +إظهار التنبيهات و نوافذ الحوار المخفية مرة ثانية؟ + +&Show +&إظهار + +Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. +تحديد التغيرات و مواكبتها على الجانبين. عمليات الحذف, النقل و المشاكل المكتشفة باستخدام قواعد البيانات. + +Create a mirror backup of the left folder by adapting the right folder to match. +إنشاء نسخة احتياطية من الجانب الأيمن عن طريق تعديل الطرف الأيسر ليطابق الأيمن. + +Copy new and updated files to the right folder. +نسخ الملفات المحدثة إلى المجلد المناسب. + +Configure your own synchronization rules. +تحديد قواعد المزامنة الخاصة بك. + +Today +اليوم + +This week +هذا الأسبوع + +This month +هذا الشهر + +This year +هذه السنة + +Last x days +الأيام x الماضية + +Byte +Byte + +KB +KB + +MB +MB + +Replace +استبدال + +Move files and replace if existing +نقل الملفات و استبدال الموجودة بها إن وجدت + +Time stamp +البصمة الزمنية + +Append a time stamp to each file name +إلحاق ختم زمني بكل اسم ملف + +Comparison +المقارنة + +Synchronization +المزامنة + +Leave as unresolved conflict +ترك كاختلافات من دون حل + +File +ملف + +YYYY-MM-DD hhmmss +YYYY-MM-DD hhmmss + +Files +ملفات + +Items +عناصر + +Percentage +النسبة المئوية + +Unable to register to receive system messages. +تعذر التسجيل لاستقبال رسائل النظام. + +Cannot monitor directory %x. +لا يمكن مراقبة المسار %x. + +The file is locked by another process: +الملف مقفول من قبل عملية أخرى: + +Cannot write file attributes of %x. +لا يمكن كتابة سمات الملف %x. + +Cannot read security context of %x. +لا يمكن قراءة سياق الأمان %x. + +Cannot write security context of %x. +لا يمكن كتابة سياق الأمان %x. + +Cannot read permissions of %x. +لا يمكن قراءة أذونات %x. + +Cannot find system function %x. +لا يمكن العثور على وظيفة نظام %x. + +Cannot copy file %x to %y. +لا يمكن نسخ الملف %x إلى %y. + +Type of item %x is not supported: +نوع العنصر %x غير مدعوم: + +%x TB +%x TB + +%x PB +%x PB + + +1 min +%x min + + +0 دقيقة +1 دقيقة واحدة +2 دقيقتان +%x دقائق +%x دقيقة +%x دقيقة + + + +1 hour +%x hours + + +0 ساعة +1 ساعة واحدة +2 ساعتين +%x ساعات +%x ساعة +%x ساعة + + + +1 day +%x days + + +0 يوم +1 يوم واحد +2 يومان +%x أيام +%x يوماً +%x يوم + + +Cannot set privilege %x. +لا يمكن تعيين امتيازات %x. + +Unable to suspend system sleep mode. +تعذر تعليق وضع النوم للنظام. + +Cannot change process I/O priorities. +تعذر تغيير أولويات I/O للعملية. + +Checking recycle bin failed for folder %x. +فشل تصفح سلة المهملات من أجل الملف %x. + +Prepare installation +الاستعداد للتثبيت + +Choose which components you want to install. +اختر المكونات التي تريد تنصيبها. + +Select installation type: +اختيار نوع التنصيب: + +Local +محلي + +Portable +متنقل + +recommended +‏منصوح به‏ + +Save settings to "%APPDATA%\FreeFileSync" +حفظ الإعدادات إلى ‏‪"%APPDATA%\FreeFileSync" + +Register FreeFileSync file extensions +تسجيل لاحقةالملفات + +Create Explorer context menu entries +إنشاء مدخلات القوائم المحلية في متصفح الملفات + +Save settings in installation directory +احفظ إعدادات التثبيت في مسار التثبيت + +Do not write to Registry +لا تسجل في ملفات الرجيستري + +Just copy the files +انسخ الملفات فقط + +Choose a directory for installation: +اختيار مسار التثبيت: + +Create shortcuts: +إنشاء اختصار: + +Desktop +سطح المكتب + +Start menu +قائمة إبدأ + +Registering FreeFileSync file extensions +تسجيل لاحقة الملفات + +Unregistering FreeFileSync file extensions +إلغاء تسجيل لاحقةالملفات + +FreeFileSync Configuration +تضبيطات FreeFileSync + +FreeFileSync Batch File +الملف الدفعي الخاص بـ FreeFileSync + +FreeFileSync Synchronization Database +قاعدة بيانات المزامنة الخاصة بـ FreeFileSync + +RealtimeSync Configuration +تضبيطات RealtimeSync + +Edit with FreeFileSync +تعديل بواسطة FreeFileSync + diff --git a/FreeFileSync/Build/Languages/outdated/norwegian.lng b/FreeFileSync/Build/Languages/outdated/norwegian.lng new file mode 100644 index 00000000..e02ec59f --- /dev/null +++ b/FreeFileSync/Build/Languages/outdated/norwegian.lng @@ -0,0 +1,1713 @@ +
    + Norsk + enter your name here + nb_NO + flag_norway.png + 2 + n == 1 ? 0 : 1 +
    + +Both sides have changed since last synchronization. +Begge sider er endret siden siste synkronisering. + +Cannot determine sync-direction: +Kan ikke bestemme retning: + +No change since last synchronization. +Ingen endringer siden siste synkronisering. + +The database entry is not in sync considering current settings. +Databaseemnet er ikke i synkronisering med de aktuelle innstillinger. + +Setting default synchronization directions: Old files will be overwritten with newer files. +Setter standardretning: Gamle filer overskrives med nyere. + +Checking recycle bin availability for folder %x... +Sjekker papirkurvens tilgjengelighet for mappen %x... + +Moving file %x to the recycle bin +Flytter filen %x til papirkurv + +Moving folder %x to the recycle bin +Flytter mappen %x til papirkurv + +Moving symbolic link %x to the recycle bin +Flytter symbolsk link %x til papirkurv + +Deleting file %x +Sletter filen %x + +Deleting folder %x +Sletter mappen %x + +Deleting symbolic link %x +Sletter symlink %x + +The recycle bin is not available for the following folders. Files will be deleted permanently instead: +Papirkurven kan ikke brukes til følgende mapper. Filene slettes permanent: + +An exception occurred +Unntagelse oppstod + +A directory path is expected after %x. +Det forventes en mappestil etter %x. + +Syntax error +Syntaksfeil + +Cannot find file %x. + + +File %x does not contain a valid configuration. +Filen %x inneholder ikke gyldige innstillinger. + +Unequal number of left and right directories specified. +Det er angitt et ulikt antall høyre og venstre mapper. + +The config file must not contain settings at directory pair level when directories are set via command line. +Instillingsfilen må ikke indeholde innstillinger på mappepar nivå når mapper er satt via kommando. + +Directories cannot be set for more than one configuration file. +Mapper kan ikke settes til mere enn en innstillingsfil. + +Command line +Kommando + +Syntax: +Syntaks: + +global config file: +Global konfigureringsfil: + +config files: +Konfigurer filer: + +directory +mappe + +Path to an alternate GlobalSettings.xml file. +Sti til en alternativ GlobalSettings.xml fil. + +Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. +Vilkårlig antall FreeFileSync .ffs_gui og/eller .ffs_batch indstillingsfiler. + +Any number of alternative directory pairs for at most one config file. +Et ubegrenset antall alternative kataloger for maksimalt én konfigurasjonsfil + +Open configuration for editing without executing it. + + +Cannot find the following folders: +Kan ikke finne følgende mapper: + +You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. +Ignorer denne fil for at betrakte hver mappe som tom. Mapperne blir så automatisk opprettet ved synkronisering. + +A folder input field is empty. +Der er ikke valgt noen mapper. + +The corresponding folder will be considered as empty. +Den tilsvarende mappe betraktes som tom. + +The following folder paths are dependent from each other: +De følgende mappebaner er avhengige av hverandre: + +File %x has an invalid date. +Filen %x har en ugyldig dato. + +Date: +Dato: + +Files %x have the same date but a different size. +Filene %x har den samme dato men forskjellig størrelse. + +Size: +Størrelse: + +Content comparison was skipped for excluded files %x. +Innholdsanalyse er utelatt for ekskluderte filer %x + +Items differ in attributes only +Enhetene har kun forskjellige attributter + +Resolving symbolic link %x +Løser symbolsk link %x + +Comparing content of files %x +Sammenligner innhold av filer %x + +Generating file list... +Oppretter filliste... + +Starting comparison +Starter analyse + +Calculating sync directions... +Forbereder synkronisering... + +Out of memory. +Ikke nok minne. + +Item exists on left side only +Mappen finnes kun på venstre side + +Item exists on right side only +Mappen finnes kun på høyre side + +Left side is newer +Venstre er nyest + +Right side is newer +Høyre er nyest + +Items have different content +Emnene har forskjellig innhold + +Both sides are equal +Begge sider er like + +Conflict/item cannot be categorized +Konflikt/ukjent mappe + +Copy new item to left +Kopier ny mappe mot venstre + +Copy new item to right +Kopier ny mappe mot høyre + +Delete left item +Slett venstre mappe + +Delete right item +Slett høyre mappe + +Move file on left +Flytt filen til venstre + +Move file on right +Flytt filen til høyre + +Update left item +Oppdater fil til venstre + +Update right item +Oppdater fil til høyre + +Do nothing +Ikke gjør noe + +Update attributes on left +Oppdater attributter til venstre + +Update attributes on right +Oppdater attributter til høyre + +Cannot read file %x. +Kan ikke lese filen %x. + + +Unexpected size of data stream. +Expected: %x bytes +Actual: %y bytes + + + +Cannot write permissions of %x. +Kan ikke skrive tillatelsene til %x. + +Operation not supported for different base folder types. + + +Cannot write file %x. +Kan ikke opprette filen %x. + +Cannot copy symbolic link %x to %y. +Kan ikke kopiere symolsk link %x til %y + +Cannot move file %x to %y. +Kan ikke flytte filen %x til %y. + +Cannot enumerate directory %x. +Kan ikke telle mappen %x. + +Cannot read file attributes of %x. +Kan ikke lese filattributterne på %x. + +Cannot find %x. + + +Cannot open file %x. +Filen %x kan ikke åpnes. + +Cannot delete directory %x. +Kan ikke slette mappen %x. + +Cannot delete file %x. +Kan ikke slette filen %x. + +Cannot find device %x. + + +Cannot determine free disk space for %x. + + +Cannot create directory %x. +Kan ikke opprette mappen %x. + +Cannot write modification time of %x. +Kan ikke oppdatere tidsendring på %x. + +Cannot determine final path for %x. +Kan ikke bestemme endelig sti for %x + +Cannot resolve symbolic link %x. +Kan ikke følge symlinken %x. + +Unable to move %x to the recycle bin. +Kunne ikke flytte %x til papirkurv. + +Cannot open directory %x. +Kan ikke åpne mappen %x. + +Incorrect command line: +Ugyldig kommando: + +Error Code %x: +Feilkode %x: + +Failed to connect to SFTP server %x. + + + +1 byte +%x bytes + + +1 byte +%x byte + + +%x MB +%x MB + +%x KB +%x KB + +%x GB +%x GB + +Cannot load file %x. +Kan ikke lese filen %x. + +Database file %x is incompatible. +Databasefilen %x er inkompatibel. + +Initial synchronization: +Forbereder synkronisering: + +Database file %x does not yet exist. +Databasefilen %x finnes ikke. + +Database file is corrupt: +Databasefilen er ødelagt: + +Database files do not share a common session. +Databasefiler kan ikke dele handling. + +Searching for folder %x... +Søker etter mappen %x... + +Time out while searching for folder %x. + + +Cannot get process information. +Kan ikke hente prosessinformasjon. + +Waiting while directory is locked: +Venter mens mappe låses: + +Lock owner: +Låsens eier + + +1 sec +%x sec + + +1 sek +%x sek + + +Detecting abandoned lock... +Finner etterlatt lås... + +Creating file %x +Oppretter filen %x + +Saving file %x... +Lagrer fil %x... + +Items processed: +Mapper behandlet: + +Items remaining: +Gjenstående mapper: + +Total time: +Samlet tid: + +Error parsing file %x, row %y, column %z. +Behandlingsfeil i filen %x, rekke %y, kolonne %z. + +Cannot set directory lock for %x. +Kan ikke låse mappen %x. + +Scanning: +Skanner: + + +1 thread +%x threads + + +1 tråd +%x tråder + + +/sec +/sek + +%x items/sec +%x mapper/sek + +Show in Explorer +Åpne filplassering + +Open with default application +Åpne med standardprogram + +Browse directory +Gjennomse mappe + +Cannot access the Volume Shadow Copy Service. +VSS tjenesten er ikke tilgjengelig + +Please use FreeFileSync 64-bit version to create shadow copies on this system. +Bruk FreeFileSync 64-bit til å lage VSS kopier på dette system. + +Cannot determine volume name for %x. +Kan ikke bestemme volumnavn for %x. + +Volume name %x is not part of file path %y. +Volumnavnet %x er ikke en del av filstien %y. + +Stop requested: Waiting for current operation to finish... +Avbryter: Venter til aktuell oppgave avsluttes... + +Unable to create time stamp for versioning: +Kan ikke opprette tidsstempel til versionering: + +Drag && drop +Trekk mapper hit + +Cannot find folder %x. +Finner ikke mappen %x. + +Select a folder +Velg en mappe + +&Open... +&Åpne... + +Save &as... +Lagre &som... + +E&xit +A&vslutt + +&File +&Fil + +&View help +&Åpne hjelp + +&About +&Om + +&Help +&Hjelp + +Usage: +Gjør slik: + +1. Select folders to watch. +1. Velg mapper til jobben. + +2. Enter a command line. +2. Angi en kommando. + +3. Press 'Start'. +3. Klikk 'Start'. + +To get started just import a .ffs_batch file. +Importer en .ffs_batchfil (Filer > Åpne...) for å komme igang. + +Folders to watch: +Jobbens mapper: + +Add folder +Tilføy mappe + +Remove folder +Fjern mappe + +Browse + + +Idle time (in seconds): +PC ikke brukt i (sek) + +Idle time between last detected change and execution of command +Tid mellom sist funnet endring og utførelse + +Command line: +Kommando: + + +The command is triggered if: +- files or subfolders change +- new folders arrive (e.g. USB stick insert) + + +Kommandoen utføres hvis: +- filer eller undermapper endres +- nye mapper finnes (f.eks USB nøkkel) + + +&Start +&Start + +About +Om + +Build: %x +Utgitt: %x + +All files +Alle filer + +Automated Synchronization +Automatisk synkronisering + +Directory monitoring active +Mappeovervåkning aktiv + +Waiting until all directories are available... +Venter til alle mapper er tilgjengelige... + +Error +Feil + +&Restore +&Vis vinduer + +&Show error +&Vis feil + +&Quit +&Avslutt + +&Retry +&Prøv igjen + +File content +Innhold + +File time and size +Størrelse og tid + +Two way +Toveis + +Mirror +Speiling + +Update +Oppdater + +Custom +Tilpasset + +Multiple... +Flere... + +Moving file %x to %y +Flytter filen %x til %y + +Moving folder %x to %y +Flytter mappen %x til %y + +Moving symbolic link %x to %y +Flytter symlinken %x til %y + +Removing old versions... +Fjerner gamle utgaver... + +Creating symbolic link %x +Oppretter symlinken %x + +Creating folder %x +Oppretter mappen %x + +Updating file %x +Oppdaterer fil %x + +Updating symbolic link %x +Oppdaterer symbolsk link %x + +Verifying file %x +Verifiserer filen %x + +Updating attributes of %x +Oppdaterer attributter for %x + +%x and %y have different content. + + +Data verification error: + + +Creating a Volume Shadow Copy for %x... +Oppretter VSS kopi for %x... + +Target folder %x already existing. +Destinasjonsmappen %x finnes allerede. + +Target folder input field must not be empty. +Destinasjonsmappen skal angis. + +Source folder %x not found. +Kildemappen %x ble ikke funnet. + +Please enter a target folder for versioning. +Angi mappe til versionering. + +The following items have unresolved conflicts and will not be synchronized: +Følgende mapper har uløste konflikter og synkroniseres ikke: + +The following folders are significantly different. Make sure you have selected the correct folders for synchronization. + + +Not enough free disk space available in: +Ikke nok ledig diskplass på: + +Required: +Krav: + +Available: +Tilgjengelig: + +Multiple folder pairs write to a common subfolder. Please review your configuration. +Flere mappepar til er skrevet til en felles undermappe. Se konfigureringen. + +Synchronizing folder pair: +Synkroniserer mappepar: + +Generating database... +Oppretter database... + +job name +Jobbnavn + +Synchronization stopped +Synkronisering avbrudt + +Stopped +Avbrutt + +Synchronization completed with errors +Synkronisering gjennomført med feil + +Synchronization completed with warnings +Synkronisering gjennomført med advarsel + +Warning +Advarsel + +Nothing to synchronize +Alt er synkronisert + +Synchronization completed successfully +Synkronisering gjennomført + +Cleaning up old log files... +Fjerner gamle loggfiler + +You can switch to FreeFileSync's main window to resolve this issue. +Skift til FreeFileSyncs hovedvindu for at løse problemet. + +&Don't show this warning again +&Vis ikke igen + +&Ignore +&Ignorer + +&Switch +&Skift + +Switching to FreeFileSync's main window +Skifter til hovedvinduet + + +Automatic retry in 1 second... +Automatic retry in %x seconds... + + +Prøver igjen om 1 sekund... +Prøver igjen om %x sekunder... + + +&Ignore subsequent errors +&Ignorer etterfølgende feil + +Retrying operation... +Prøver igen... + +Serious Error +Kritisk feil + +Check for Program Updates +Søk etter oppdatering + +A new version of FreeFileSync is available: +Oppdatering tilgjengelig: + +Download now? +Last ned nå? + +&Download +&Last ned + +FreeFileSync is up to date. +FreeFileSync er oppdatert. + +Unable to connect to www.freefilesync.org. +Kan ikke koble til www.freefilesync.org + +Cannot find current FreeFileSync version number online. Do you want to check manually? +Kunne ikke finne FreeFileSync's versjonsnummer online. Vil du kontrollere manuelt? + +&Check +&Kontroller + +Symlink +Symlink + +Folder +Mappe + +Full path +Full sti + +Name +Navn + +Relative folder +Relativ mappe + +Base folder +Hovedmappe + +Size +Størrelse + +Date +Dato + +Extension +Filtype + +Category +Status + +Action +Handling + +Local comparison settings +Lokale sammenlignings-instillinger + +Local synchronization settings +Lokale synkroniserings-instillinger + +Local filter +Lokalt filter + +Active +Aktiv + +None +Ingen + +Remove local settings +Fjern lokale instillinger + +Clear local filter +Slett lokalt filter + +Copy +Kopiér + +Paste +Lim inn + +Local Synchronization Settings +Lokale synkroniseringsinstillinger + +The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. + + +&New +&Ny + +&Save +&Lagre + +Save as &batch job... +Lagre som &batchfil + +Start &comparison +Start &sammenligning + +C&omparison settings +S&ammenligner instillinger + +&Filter settings +&Filtrer instillinger + +S&ynchronization settings +S&ynkroniserings-instillinger + +Start &synchronization +Start &synkronisering + +&Actions +&Handling + +&Options +&Valg + +&Language +&Språk + +&Find... +&Søk + +&Reset layout +&Reset layout + +&Export file list... +&Eksporter filliste... + +&Tools +&Verktøy + +&Check for new version +&Søk etter oppdatering + +&Check now +&Søk nå + +Check &automatically once a week +Søk &automatisk en gang i uken + +Cancel +Avbryt + +Compare +Analysér + +Synchronize +Synkronisér + +Add folder pair +Tilføy mappepar + +Remove folder pair +Fjern mappepar + +Select SFTP folder + + +Swap sides +Bytt side + +Close search bar +Lukk søkelinje + +Find: +Søk: + +Match case +Treffølsomhet (a/A) + +New +Ny + +Open... +Åpne... + +Save +Lagre + +Save as... +Lagre som + +View type: +Visning: + +Select view: +Velg visning: + +Statistics: +Statistikk: + +Number of files and folders that will be deleted +Antall filer og mapper som slettes + +Number of files that will be updated +Antall filer som vil bli oppdatert + +Number of files and folders that will be created +Antall filer og mapper som vil bli opprettet + +Total bytes to copy +Antal bytes som kopieres + +Use local settings: +Bruk lokale instillinger + +Select a variant: +Velg metode: + +Identify equal files by comparing modification time and size. +Gjennkjenn like filer etter filtid og størrelse. + +Identify equal files by comparing the file content. +Gjennkjenn like filer etter innhold. + +&Ignore time shift (in hours) + + +Consider file times with specified offset as equal +Vurder filtidspunkt med spesifisert oppstilling som like + +Handle daylight saving time +Behandle sommertid + +Include &symbolic links: + + +&Follow + + +&Direct + + +More information +Mer informasjon + +Local settings: +Lokale instillinger + +Include: +Inkludér: + +Exclude: +Ekskludér: + +Show examples +Vis eksempler + +Time span: +Intervall: + +File size: +Filstørrelse: + +Minimum: +Minimum: + +Maximum: +Maksimum: + +Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. +Angi filterregler til ekskludering av bestemte filer fra synkroniseringen. Filstier skal relatere til kildemappene. + +C&lear +F&jern + +Detect moved files +Gjennkjenn flyttede filer + + +- Not supported by all file systems +- Requires and creates database files +- Detection not available for first sync + + + +Detect synchronization directions with the help of database files +Gjennkjenn synkretninger ved hjelp av databasefiler + +Delete files: +Slett filer: + +&Permanent +&Permanent + +Delete or overwrite files permanently +Slett eller overskriv filer permanent + +&Recycle bin +&Papirkurv + +Back up deleted and overwritten files in the recycle bin +Backup slettede og overskrevne filer i papirkurven + +&Versioning +&Versjonering + +Move files to a user-defined folder +Flytt filer til brukerdefinert mappe + +Naming convention: +Navneregler: + +Handle errors: +Feilhåndtering: + +Hide all error and warning messages +Skjul feilmeldinger og advarsler + +&Pop-up +&Pop-up + +Show pop-up on errors or warnings +Vis feilmeldinger og advarsler + +On completion: +Når gjennomført: + +OK +OK + +Enter your SFTP login details: + + +Server name or IP address: + + +Examples: + + +User name: + + +Password: + + +&Show password + + +Directory on server: + + + + +Start synchronization now? +Synkroniser nå? + +Variant: +Jobbtype: + +&Don't show this dialog again +&Ikke vis igjen + +Arrange folder pair + + +Items found: +Mapper funnet: + +Time remaining: +Resterende tid: + +Time elapsed: +Brukt tid: + +Synchronizing... +Synkroniserer... + +Minimize to notification area +Minimér til systemfeltet + +Bytes copied: +Byte kopiert + +Close +Lukk + +&Pause +&Pause + +Stop +Stopp + +Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x +Oppret batchfil til automatisk synkronisering. Start ved aå dobbeltklikke på filen eller planlegg via oppgaveplanlegger: %x + +&Stop +&Stopp + +Stop synchronization at first error +Stopp synkronisering ved første feil + +Run minimized +Kjør minimert + +Save log: +Lagre logg: + +Limit: +Grense: + +Limit maximum number of log files +Begrens antall rapporter + +How can I schedule a batch job? +Hvordan opprettes en batchfil? + +The following settings are used for all synchronization jobs. +Disse innstillinger gjelder alle synkroniseringer. + +Fail-safe file copy +Sikker filkopiering + + +Copy to a temporary file (*.ffs_tmp) before overwriting target. +This guarantees a consistent state even in case of a serious error. + +Kopiér til midlertidig fil (*.ffs_tmp) før overskriving. Sikrer prosessen ved alvorlige feil. + +(recommended) +(anbefalt) + +Copy locked files +Kopier låste filer + +Copy shared or locked files using the Volume Shadow Copy Service. +Kopiér delte eller låste filer med VSS kopiering. + +(requires administrator rights) +(administrator) + +Copy file access permissions +Kopier adgangstillatelser + +Transfer file and folder permissions. +Overfør fil og mappetillatelser. + +Automatic retry on error: +Antall forsøk ved feil: + +Retry count: +Antall forsøk: + +Delay (in seconds): +Forsinkelse (sek): + +Customize context menu: +Tilpass kontekstmeny: + +Description +Beskrivelse + +Show hidden dialogs again +Vis skjulte vinduer + +Show all permanently hidden dialogs and warning messages again +Vis alle vinduer og advarsler igjen + +&Default +&Standard + +Source code written in C++ using: +Kildekoden er skrevet i C++ med hjelp fra: + +If you like FreeFileSync: +Hvis du liker FreeFileSync: + +Donate with PayPal +Donér med PayPal + +Feedback and suggestions are welcome +Kritikk og forslag er ønsket + +Homepage +Hjemmeside + +Email +Email + +Published under the GNU General Public License +Utgitt under GNU General Public Licence + +Many thanks for localization: +Takk for oversettelse: + +SSH File Transfer Protocol + + +Save as Batch Job +Lagre som batchfil + +Delete Items +Slett mapperr + +Options +Valg + +Select Time Span +Velg tidsintervall + +&Preferences + + +Main Bar +Hovedlinje + +Folder Pairs +Mappepar + +Find +Søk + +View Settings +Visninger + +Configuration +Innstilling + +Overview +Oversikt + +Confirm +Bekreft + + +Do you really want to execute the command %y for one item? +Do you really want to execute the command %y for %x items? + + +Vil du kjøre kommandoen %y for 1 mappe? +Vil du kjøre kommandoen %y for %x mapper? + + +&Execute +&Utfør + + +1 directory +%x directories + + +1 mappe +%x mapper + + + +1 file +%x files + + +1 fil +%x filer + + + +Showing %y of 1 row +Showing %y of %x rows + + +Viser %y av 1 rekke +Viser %y av %x rekker + + +Set direction: +Retning: + +multiple selection +velg flere + +Include via filter: +Inkludér via filter: + +Exclude via filter: +Ekskluder m. filter: + +Include temporarily +Inkluder midlertidig + +Exclude temporarily +Ekskluder midlertidig + +Delete +Slett + +Include all +Velg alle + +Exclude all +Ekskluder alle + +Show icons: +Vis ikoner: + +Small +Små + +Medium +Medium + +Large +Store + +Select time span... +Velg tidsinterval... + +Show "%x" +Vis "%x" + +Last session +Siste oppgave + +Folder Comparison and Synchronization +Mappeanalyse og synkronisering + +Configuration saved +Lagrede instillinger + +FreeFileSync batch +FreeFileSync batchfil + +Do you want to save changes to %x? +Vil du lagre endringer i %x? + +Never save &changes +&Aldri lagre endringer + +Do&n't save +&Ikke lagre + +Remove entry from list + + +Synchronization Settings +Synkroniseringsinnstillinger + +Clear filter +Slett filter + +Show files that exist on left side only +Vis filer som kun finnes på venstre side + +Show files that exist on right side only +Vis filer som kun finnes på høyre side + +Show files that are newer on left +Vis nyere filer på venstre side + +Show files that are newer on right +Vis nyere filer på høyre side + +Show files that are equal +Vis like filer + +Show files that are different +Vis ulike filer + +Show conflicts +Vis konflikter + +Show files that will be created on the left side +Vis filer som opprettes på venstre side + +Show files that will be created on the right side +Vis filer som opprettes på høyre side + +Show files that will be deleted on the left side +Vis filer som slettes på venstre side + +Show files that will be deleted on the right side +Vis filer som slettes på høyre side + +Show files that will be updated on the left side +Vis filer som vil bli oppdaters på venstre side + +Show files that will be updated on the right side +Vis filer som vil bli oppdatert på høyre side + +Show files that won't be copied +Vis filer som ikke kopieres + +Show filtered or temporarily excluded files +Vis filtrerte eller midlertidig ekskluderte filer + +Save as default + + +Filter +Filter + +All files are in sync +Alt er synkronisert + +Cannot find %x +Kan ikke finne %x + +Move up + + +Move down + + +Comma-separated values +Kommaoppdelte verdier + +File list exported +Fillisten ble eksportert + +Searching for program updates... +Søker etter oppdatering... + +Close progress dialog +Lukk dialogen + +Log off +Logg av + +Standby +Standby + +Shut down +Avslutt + +Scanning... +Skanner... + +Comparing content... +Analyserer innhold... + +Info +Info + +Select all +Velg alt + +Paused +Pauset + +Initializing... +Forbereder... + +Completed +Gjennomført + +&Continue +&Fortsett + +Progress +Fremskritt + +Log +Logg + + +Do you really want to move the following item to the recycle bin? +Do you really want to move the following %x items to the recycle bin? + + +Vil du flytte følgende mappe til papirkurven? +Vil du flytte følgende %x mapper til papirkurven? + + +Move +Flytt + + +Do you really want to delete the following item? +Do you really want to delete the following %x items? + + +Vil du slette følgende mappe? +Vil du slette følgende %x mapper? + + +Preferences +Egenskaper + +Copy DACL, SACL, Owner, Group + + +Integrate external applications into context menu. The following macros are available: +Integrer eksterne programmer i kontekstmeny. Bruk følgende makroer: + +- full file or folder name +Komplett fil- eller mappenavn + +- folder part only +Kun mappedelen + +- Other side's counterpart to %item_path% +Motsatt sides motstykke til %item_path% + +- Other side's counterpart to %item_folder% +Motsatt sides motstykke til %item_folder% + +Show hidden dialogs and warning messages again? +Vis gjemte vinduer og advarsler igjen? + +&Show +&Vis + +Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. +Finn og fordel endringer på begge sider. Slettede filer, omdøpninger og konflikter finnes automatisk i en database. + +Create a mirror backup of the left folder by adapting the right folder to match. +Oppret speiling av venstre mappe ved å tilpasse den høyre mappe + +Copy new and updated files to the right folder. +Kopier nye og oppdaterte filer til høyre mappe. + +Configure your own synchronization rules. +Oppret dine egne synkroniseringsregler. + +Today +I dag + +This week +Denne uke + +This month +Denne måned + +This year +Dette år + +Last x days +Siste x dager + +Byte +Byte + +KB +KB + +MB +MB + +Replace +Erstat + +Move files and replace if existing +Flytt fil og erstatt eventuelt eksisterende + +Time stamp +Tidsstempel + +Append a time stamp to each file name +Legg til tidsstempel til hvert filnavn + +Comparison +Sammenligning + +Synchronization +Synkronisering + +Leave as unresolved conflict +Etterlat som uløst konflikt + +File +Fil + +YYYY-MM-DD hhmmss +YYYY-MM-DD hhmmss + +Files +Filer + +Items +Mapper + +Percentage +Prosent + +Unable to register to receive system messages. +Kunne ikke registrere mottakelse av systembesjkeder. + +Unable to register device notifications for %x. + + +Cannot monitor directory %x. +Kan ikke overvåke mappen %x. + +The file is locked by another process: +Filen er låst av en annen prosess: + +Cannot write file attributes of %x. +Kan ikke skrive filattributter til %x. + +Cannot read security context of %x. +Kan ikke lese sikkerhetsinnstillinger på %x. + +Cannot write security context of %x. +Kan ikke skrive sikkerhetsinnstillinger til %x. + +Cannot read permissions of %x. +Kan ikke lese tillatelsene på %x. + +Cannot copy permissions from %x to %y. + + +Cannot find system function %x. +Kan ikke finne systemfunksjonen %x. + +Cannot copy attributes from %x to %y. + + +Cannot copy file %x to %y. +Kan ikke kopiere filen %x til %y. + +Type of item %x is not supported: +Filtypen %x støttes ikke: + +%x TB +%x TB + +%x PB +%x PB + + +1 min +%x min + + +1 min +%x min + + + +1 hour +%x hours + + +1 time +%x timer + + + +1 day +%x days + + +1 dag +%x dager + + +Cannot set privilege %x. +Kan ikke sette %x privilegier. + +Unable to suspend system sleep mode. +Kunne ikke oppheve standby. + +Cannot change process I/O priorities. +Kan ikke endre I/O prioriteter. + +Checking recycle bin failed for folder %x. +Sjekk papirkurv-feil for mappen %x + +The following XML elements could not be read: + + +Configuration file %x is incomplete. The missing elements will be set to their default values. + + +Prepare installation +Forbered installering + +Choose which components you want to install. +Velg hva du vil installere + +Select installation type: +Velg installasjonstype + +Local +Lokal + +Portable +Portabel (USB) + +recommended +anbefalt + +Save settings to "%APPDATA%\FreeFileSync" +Lagre innstillinger til "%APPDATA%\FreeFileSync" + +Register FreeFileSync file extensions +Registrer FreeFileSync filendelser + +Create Explorer context menu entries +Legg til i høyreklikkmeny + +Save settings in installation directory +Lagre innstillinger i installasjonsmappen + +Do not write to Registry +Ikke skriv til registeret + +Just copy the files +Bare kopier filene + +Choose a directory for installation: +Velg en mappe for installasjon: + +Create shortcuts: +Opprett snarveier: + +Desktop +Skrivebord + +Start menu +Startmeny + +Registering FreeFileSync file extensions +Registrerer FreeFileSync filendelser + +Unregistering FreeFileSync file extensions +Avregistrerer FreeFileSync filendelser + +FreeFileSync Configuration +FreeFileSync konfigurering + +FreeFileSync Batch File +FreeFileSync Batch Fil + +FreeFileSync Synchronization Database +FreeFileSync Synkronisering + +RealtimeSync Configuration +RealtimeSync konfigurering + +Edit with FreeFileSync +Rediger med FreeFileSync + diff --git a/FreeFileSync/Build/Languages/outdated/portuguese.lng b/FreeFileSync/Build/Languages/outdated/portuguese.lng new file mode 100644 index 00000000..c4e33b9b --- /dev/null +++ b/FreeFileSync/Build/Languages/outdated/portuguese.lng @@ -0,0 +1,1716 @@ +
    + Português + Miguel Balseiro + pt_PT + flag_portugal.png + 2 + n == 1 ? 0 : 1 +
    + +Both sides have changed since last synchronization. +Ambos os lados tiveram alterações desde a última sincronização. + +Cannot determine sync-direction: +Não é possível saber a direção de sincronização: + +No change since last synchronization. +Não há alterações desde a última sincronização. + +The database entry is not in sync considering current settings. +A base de dados não está sincronizada com as definições correntes. + +Setting default synchronization directions: Old files will be overwritten with newer files. +Escolher direcção de sincronização por defeito: Os ficheiros antigos serão substituídos pelos novos. + +Checking recycle bin availability for folder %x... +A verificar a disponibilidade da reciclagem para a pasta %x... + +Moving file %x to the recycle bin +Mover ficheiro %x para a reciclagem + +Moving folder %x to the recycle bin +Mover pasta %x para a reciclagem + +Moving symbolic link %x to the recycle bin +Mover link simbólico %x para a reciclagem + +Deleting file %x +Eliminar ficheiro %x + +Deleting folder %x +Eliminar pasta %x + +Deleting symbolic link %x +Eliminar link simbólico %x + +The recycle bin is not available for the following folders. Files will be deleted permanently instead: +A reciclagem não está disponível para as seguintes pastas. Os ficheiros serão, em alternativa, eliminados permanentemente: + +An exception occurred +Ocorreu uma excepção + +A directory path is expected after %x. +É esperado um caminho de directório após %x. + +Syntax error +Erro de sintaxe + +Cannot find file %x. + + +File %x does not contain a valid configuration. +Ficheiro %x não tem uma configuração válida. + +Unequal number of left and right directories specified. +Número desigual de directórios à esquerda e à direita. + +The config file must not contain settings at directory pair level when directories are set via command line. +O ficheiro de configuração não deve conter configurações ao nível de par-directório quando os directórios são definidos pela linha de comandos. + +Directories cannot be set for more than one configuration file. +Os directórios não podem ser definidos em mais do que um ficheiro de configuração. + +Command line +Linha de comandos + +Syntax: +Sintaxe: + +global config file: +ficheiro configuração global: + +config files: +ficheiros configuração: + +directory +directório + +Path to an alternate GlobalSettings.xml file. +Caminho para o ficheiro GlobalSettings.xml alternativo. + +Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. +Qualquer número de ficheiros de configuração .ffs_gui e/ou .ffs_batch do FreeFileSync. + +Any number of alternative directory pairs for at most one config file. +Qualquer número de pares de directórios alternativos para apenas um ficheiro de configuração. + +Open configuration for editing without executing it. + + +Cannot find the following folders: +Não é possível encontrar as seguintes pastas: + +You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. +Pode ignorar este erro para considerar cada pasta como vazia. As pastas necessárias serão criadas automaticamente durante a sincronização. + +A folder input field is empty. +Um dos campos de directório para comparar está vazio. + +The corresponding folder will be considered as empty. +A pasta correspondente será considerada como vazia. + +The following folder paths are dependent from each other: +Os seguintes pares de pastas são dependentes: + +File %x has an invalid date. +Ficheiro %x tem data inválida. + +Date: +Data: + +Files %x have the same date but a different size. +Os ficheiros %x têm a mesma data, mas tamanho diferente. + +Size: +Tamanho: + +Content comparison was skipped for excluded files %x. +Comparação por conteúdo foi ignorada para o ficheiro excluído %x. + +Items differ in attributes only +Itens diferem apenas nos atributos + +Resolving symbolic link %x +Resolver link simbólico %x + +Comparing content of files %x +A comparar o conteúdo do ficheiro %x + +Generating file list... +A gerar lista ficheiros... + +Starting comparison +A iniciar a comparação + +Calculating sync directions... +A calcular a direcção de sincronização... + +Out of memory. +Sem memória disponível. + +Item exists on left side only +Item existe apenas à esquerda + +Item exists on right side only +Item existe apenas à direita + +Left side is newer +Esquerda é mais recente + +Right side is newer +Direita é mais recente + +Items have different content +Itens tem conteúdo diferente + +Both sides are equal +Ambos os lados iguais + +Conflict/item cannot be categorized +Conflito/item não pode ser categorizado + +Copy new item to left +Copiar novo item para a esquerda + +Copy new item to right +Copiar novo item para a direita + +Delete left item +Apagar item esquerdo + +Delete right item +Apagar item direito + +Move file on left +Mover ficheiro à esquerda + +Move file on right +Mover ficheiro à direita + +Update left item +Atualizar item esquerdo + +Update right item +Atualizar item direito + +Do nothing +Não fazer nada + +Update attributes on left +Actualizar atributos à esquerda + +Update attributes on right +Actualizar atributos à direita + +Cannot read file %x. +Não é possível ler o ficheiro %x. + + +Unexpected size of data stream. +Expected: %x bytes +Actual: %y bytes + + + +Cannot write permissions of %x. +Não é possível escrever as permissões de %x. + +Operation not supported for different base folder types. + + +Cannot write file %x. +Não é possível escrever o ficheiro %x. + +Cannot copy symbolic link %x to %y. +Não é possível criar o link simbólico de %x para %y. + +Cannot move file %x to %y. +Não é possível mover o ficheiro %x para %y. + +Cannot enumerate directory %x. +Não é possível enumerar o directório %x. + +Cannot read file attributes of %x. +Não é possível ler os atributos do ficheiro %x. + +Cannot find %x. + + +Cannot open file %x. +Não é possível abrir o ficheiro %x. + +Cannot delete directory %x. +Não é possível eliminar o directório %x. + +Cannot delete file %x. +Não é possível eliminar o ficheiro %x. + +Cannot find device %x. + + +Cannot determine free disk space for %x. + + +Cannot create directory %x. +Não é possível criar o directório %x. + +Cannot write modification time of %x. +Não é possível alterar a data de modificação a %x. + +Cannot determine final path for %x. +Não é possível determinar o caminho final de %x. + +Cannot resolve symbolic link %x. +Não é possível resolver o link simbólico %x. + +Unable to move %x to the recycle bin. +Não é possível mover %x para a reciclagem. + +Cannot open directory %x. +Não é possível abrir o directório %x. + +Incorrect command line: +Linha de comandos incorrecta: + +Error Code %x: +Código de erro %x: + +Failed to connect to SFTP server %x. + + + +1 byte +%x bytes + + +1 byte +%x bytes + + +%x MB +%x MB + +%x KB +%x KB + +%x GB +%x GB + +Cannot load file %x. +Não é possível carregar o ficheiro %x. + +Database file %x is incompatible. +Base de dados %x não é compatível. + +Initial synchronization: +Sincronização inicial: + +Database file %x does not yet exist. +Base de dados %x não existe. + +Database file is corrupt: +Ficheiro de base de dados está corrompido: + +Database files do not share a common session. +As bases de dados são de sessões diferentes. + +Searching for folder %x... +À procura da pasta %x... + +Time out while searching for folder %x. + + +Cannot get process information. +Não é possível obter informação sobre o processo. + +Waiting while directory is locked: +À espera do bloqueio do directório: + +Lock owner: +Dono do bloqueio: + + +1 sec +%x sec + + +1 seg +%x segs + + +Detecting abandoned lock... +Detectado bloqueio abandonado... + +Creating file %x +Criar ficheiro %x + +Saving file %x... +Guardar ficheiro %x... + +Items processed: +Elementos processados: + +Items remaining: +Elementos restantes: + +Total time: +Tempo total: + +Error parsing file %x, row %y, column %z. +Erro ao analisar ficheiro %x, linha %y, coluna %z. + +Cannot set directory lock for %x. +Não é possível colocar o bloqueio de directório para %x. + +Scanning: +A pesquisar: + + +1 thread +%x threads + + +1 thread +%x threads + + +/sec +/seg + +%x items/sec +%x itens/seg + +Show in Explorer +Mostrar no Explorer + +Open with default application +Abrir com a aplicação associada + +Browse directory +Procurar directório + +Cannot access the Volume Shadow Copy Service. +Não é possível aceder ao serviço Volume Shadow Copy. + +Please use FreeFileSync 64-bit version to create shadow copies on this system. +Utilize a versão 64-bit do FreeFileSync para criar cópias sombra neste sistema. + +Cannot determine volume name for %x. +Não é possível determinar o nome do volume para %x. + +Volume name %x is not part of file path %y. +Nome de volume %x não faz parte do caminho do ficheiro %y. + +Stop requested: Waiting for current operation to finish... +Paragem solicitada: À espera que termine a operação actual... + +Unable to create time stamp for versioning: +Não é possível criar data/hora para controlo de versões: + +Drag && drop +Arrastar && Largar + +Cannot find folder %x. +Não é possível encontrar a pasta %x. + +Select a folder +Selecione uma pasta + +&Open... +&Abrir... + +Save &as... +Guardar &como... + +E&xit +S&air + +&File +&Ficheiro + +&View help +&Ver ajuda + +&About +So&bre + +&Help +A&juda + +Usage: +Uso: + +1. Select folders to watch. +1. Selecionar pastas para observar. + +2. Enter a command line. +2. Inserir a linha de comando. + +3. Press 'Start'. +3. Pressionar 'Iniciar'. + +To get started just import a .ffs_batch file. +Para começar basta importar um ficheiro .ffs_batch. + +Folders to watch: +Pastas a verificar: + +Add folder +Adicionar pasta + +Remove folder +Remover pasta(s) + +Browse +Procurar + +Idle time (in seconds): +Tempo de espera (em segundos): + +Idle time between last detected change and execution of command +Tempo de espera entre a última alteração detetada e a execução do comando + +Command line: +Linha de comandos: + + +The command is triggered if: +- files or subfolders change +- new folders arrive (e.g. USB stick insert) + + +O comando é executado se: +- ficheiros ou subpastas forem alterados +- forem detetadas novas pastas (p.e. pen USB) + + +&Start +&Início + +About +Sobre + +Build: %x +Build: %x + +All files +Todos os ficheiros + +Automated Synchronization +Sincronização Automática + +Directory monitoring active +Monitorização de directório activa + +Waiting until all directories are available... +A aguardar que todos os directórios fiquem disponíveis... + +Error +Erro + +&Restore +&Restaurar + +&Show error +Mostrar &erro + +&Quit +&Sair + +&Retry +&Tentar de Novo + +File content +Conteúdo do ficheiro + +File time and size +Data e tamanho do ficheiro + +Two way +Duas vias + +Mirror +Espelhar + +Update +Actualizar + +Custom +Personalizado + +Multiple... +Multiplo... + +Moving file %x to %y +Mover ficheiro %x para %y + +Moving folder %x to %y +Mover pasta %x para %y + +Moving symbolic link %x to %y +Mover link simbólico %x para %y + +Removing old versions... +A remover versões antigas... + +Creating symbolic link %x +Criar link simbólico %x + +Creating folder %x +Criar pasta %x + +Updating file %x +Atualizar ficheiro %x + +Updating symbolic link %x +Atualizar link simbólico %x + +Verifying file %x +A verificar ficheiro %x + +Updating attributes of %x +Actualizar atributos de %x + +%x and %y have different content. + + +Data verification error: + + +Creating a Volume Shadow Copy for %x... +A criar Volume Shadow Copy para %x... + +Target folder %x already existing. +Directório de destino %x já existe. + +Target folder input field must not be empty. +Campo de directório de destino não deve estar vazio. + +Source folder %x not found. +Directório %x não encontrado. + +Please enter a target folder for versioning. +Introduza uma pasta de destino para o controlo de versões. + +The following items have unresolved conflicts and will not be synchronized: +Os seguintes itens têm conflitos não resolvidos, e não serão sincronizados: + +The following folders are significantly different. Make sure you have selected the correct folders for synchronization. + + +Not enough free disk space available in: +Não há espaço livre suficiente em: + +Required: +Requirido: + +Available: +Disponível: + +Multiple folder pairs write to a common subfolder. Please review your configuration. +Vários pares de pastas escrevem para uma subpasta comum. Por favor, revise a sua configuração. + +Synchronizing folder pair: +Sincronizar o par de pastas: + +Generating database... +A gerar base de dados... + +job name +nome da tarefa + +Synchronization stopped +Sincronização parada + +Stopped +Parado + +Synchronization completed with errors +Sincronização completa com erros + +Synchronization completed with warnings +Sincronização completa com avisos + +Warning +Atenção + +Nothing to synchronize +Nada a sincronizar + +Synchronization completed successfully +Sincronização completa com sucesso + +Cleaning up old log files... +A limpar ficheiros log antigos... + +You can switch to FreeFileSync's main window to resolve this issue. +Pode mudar para a janela principal do FreeFileSync para resovler este problema. + +&Don't show this warning again +&Não mostrar este aviso novamente + +&Ignore +&Ignorar + +&Switch +&Trocar + +Switching to FreeFileSync's main window +A mudar para a janela principal do FreeFileSync + + +Automatic retry in 1 second... +Automatic retry in %x seconds... + + +Repetir automaticamente dentro de 1 segundo... +Repetir automaticamente dentro de %x segundos... + + +&Ignore subsequent errors +&Ignorar erros subsequentes + +Retrying operation... +A repetir a operação... + +Serious Error +Erro Grave + +Check for Program Updates +Procurar actualizações do programa + +A new version of FreeFileSync is available: +Uma nova versão do FreeFileSync está disponível: + +Download now? +Fazer download agora? + +&Download +&Download + +FreeFileSync is up to date. +FreeFileSync está actualizado. + +Unable to connect to www.freefilesync.org. +Não é possível ligar a www.freefilesync.org. + +Cannot find current FreeFileSync version number online. Do you want to check manually? +Não é possível encontrar a última versão do FreeFileSync online. Deseja verificar manualmente? + +&Check +&Verificar + +Symlink +Link Simbólico + +Folder +Pasta + +Full path +Caminho completo + +Name +Nome + +Relative folder +Pasta relativa + +Base folder +Pasta principal + +Size +Tamanho + +Date +Data + +Extension +Extensão + +Category +Categoria + +Action +Ação + +Local comparison settings +Opções locais de comparação + +Local synchronization settings +Opções locais de sincronização + +Local filter +Filtro local + +Active +Activo + +None +Nenhum + +Remove local settings +Apagar opções locais + +Clear local filter +Limpar filtro local + +Copy +Copiar + +Paste +Colar + +Local Synchronization Settings +Opções Locais Sincronização + +The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. + + +&New +&Novo + +&Save +G&uardar + +Save as &batch job... +Guardar como &batch... + +Start &comparison +Iniciar &comparaçao + +C&omparison settings +Opções de c&omparação + +&Filter settings +Opções de &filtros + +S&ynchronization settings +Opções de s&incronização + +Start &synchronization +Iniciar &sincronização + +&Actions +&Acções + +&Options +&Opções + +&Language +&Idioma + +&Find... +&Procurar... + +&Reset layout +&Restaurar esquema + +&Export file list... +&Exportar lista de ficheiros... + +&Tools +&Ferramentas + +&Check for new version +&Procurar por actualizações + +&Check now +&Verificar agora + +Check &automatically once a week +Verificar &automaticamente uma vez por semana + +Cancel +Cancelar + +Compare +Comparar + +Synchronize +Sincronizar + +Add folder pair +Adicionar um par de pastas + +Remove folder pair +Remover o par de pastas + +Select SFTP folder + + +Swap sides +Trocar lados + +Close search bar +Fechar barra de pesquisa + +Find: +Procurar: + +Match case +Correspondência + +New +Novo + +Open... +Abrir... + +Save +Guardar + +Save as... +Guardar como... + +View type: +Tipo de vista: + +Select view: +Seleccionar vista: + +Statistics: +Estatísticas: + +Number of files and folders that will be deleted +Número de ficheiros e pastas a ser eliminados + +Number of files that will be updated +Número de ficheiros a ser atualizados + +Number of files and folders that will be created +Número de ficheiros e pastas a ser criados + +Total bytes to copy +Total em bytes a copiar + +Use local settings: +Usar opções locais: + +Select a variant: +Seleccionar uma variante: + +Identify equal files by comparing modification time and size. +Identificar ficheiros iguais ao comparar hora de modificação e tamanho. + +Identify equal files by comparing the file content. +Identificar ficheiros iguais ao comparar o conteúdo. + +&Ignore time shift (in hours) + + +Consider file times with specified offset as equal +Considerar ficheiros com o desvio de tempo especificado como iguais + +Handle daylight saving time +Lidar com horário de verão + +Include &symbolic links: + + +&Follow + + +&Direct + + +More information +Mais informação + +Local settings: +Opções locais: + +Include: +Incluir: + +Exclude: +Excluir: + +Show examples +Mostrar exemplos + +Time span: +Intervalo de tempo: + +File size: +Tamanho ficheiro: + +Minimum: +Mínimo: + +Maximum: +Máximo + +Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. +Seleccionar regras de filtro para excluir certos ficheiros da sincronização. Insira os caminhos relativos ao par de directórios correspondente. + +C&lear +&Limpar + +Detect moved files +Detectar ficheiros movidos + + +- Not supported by all file systems +- Requires and creates database files +- Detection not available for first sync + + + +Detect synchronization directions with the help of database files +Detectar a direcção de sincronização com a ajuda de base de dados + +Delete files: +Eliminar ficheiros: + +&Permanent +&Permanente + +Delete or overwrite files permanently +Apagar ou substituir ficheiros permanentemente + +&Recycle bin +&Reciclagem + +Back up deleted and overwritten files in the recycle bin +Fazer backup dos ficheiros apagados e substituidos na reciclagem + +&Versioning +Controlo &Versões + +Move files to a user-defined folder +Mover ficheiros para uma pasta definida pelo utilizador + +Naming convention: +Convenção de nomes: + +Handle errors: +Tratar erros: + +Hide all error and warning messages +Ocultar todas as mensagens de erro/aviso + +&Pop-up +&Popup + +Show pop-up on errors or warnings +Mostrar popup em caso de erros ou avisos + +On completion: +Ao completar: + +OK +OK + +Enter your SFTP login details: + + +Server name or IP address: + + +Examples: + + +User name: + + +Password: + + +&Show password + + +Directory on server: + + + + +Start synchronization now? +Iniciar sincronização agora? + +Variant: +Variante: + +&Don't show this dialog again +&Não mostrar este diálogo novamente + +Arrange folder pair + + +Items found: +Elementos encontrados: + +Time remaining: +Tempo restante: + +Time elapsed: +Tempo decorrido + +Synchronizing... +A sincronizar... + +Minimize to notification area +Minimizar para a área de notificação + +Bytes copied: +Bytes copiados: + +Close +Fechar + +&Pause +&Pausa + +Stop +Parar + +Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x +Criar ficheiro batch para sincronização automática. Para iniciar, fazer duplo clique no ficheiro ou acrescentar ao planeador de tarefas: %x + +&Stop +&Parar + +Stop synchronization at first error +Para sincronização ao primeiro erro + +Run minimized +Correr minimizado + +Save log: +Guardar registo: + +Limit: +Limitar: + +Limit maximum number of log files +Limitar o número máximo de ficheiros log + +How can I schedule a batch job? +Como posso agendar um trabalho batch? + +The following settings are used for all synchronization jobs. +As seguintes definições são usadas para todas as sincronizações. + +Fail-safe file copy +Cópia à prova de falhas + + +Copy to a temporary file (*.ffs_tmp) before overwriting target. +This guarantees a consistent state even in case of a serious error. + + +Copiar para um ficheiro temporário (*.ffs_tmp) antes de substituir. +Isto garante um estado consistente mesmo em caso de falha grave. + + +(recommended) +(recomendado) + +Copy locked files +Copiar ficheiros bloqueados + +Copy shared or locked files using the Volume Shadow Copy Service. +Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy. + +(requires administrator rights) +(requer permissões de administrador) + +Copy file access permissions +Copiar permissões de acesso do ficheiro + +Transfer file and folder permissions. +Transferir permissões de pasta e ficheiro. + +Automatic retry on error: +Retentar automaticamente em caso de erro: + +Retry count: +Nº de tentativas: + +Delay (in seconds): +Atraso (em segundos): + +Customize context menu: +Personalizar menu de contexto: + +Description +Descrição + +Show hidden dialogs again +Mostrar diálogos ocultos novamente + +Show all permanently hidden dialogs and warning messages again +Mostrar todos os diálogos escondidos permanentemente e mensagens de aviso novamente + +&Default +&Config. Iniciais + +Source code written in C++ using: +Código fonte escrito em C++ utilizando: + +If you like FreeFileSync: +Se gosta do FreeFileSync: + +Donate with PayPal +Doar usando PayPal + +Feedback and suggestions are welcome +Comentários e sugestões são apreciados + +Homepage +Site + +Email +Email + +Published under the GNU General Public License +Publicado sobre GNU General Public License + +Many thanks for localization: +Muito obrigado pela localização: + +SSH File Transfer Protocol + + +Save as Batch Job +Guardar como Ficheiro Batch + +Delete Items +Eliminar Itens + +Options +Opções + +Select Time Span +Seleccionar Intervalo de Tempo + +&Preferences + + +Main Bar +Barra principal + +Folder Pairs +Par de Pastas + +Find +Procurar + +View Settings +Ver Opções + +Configuration +Configuração + +Overview +Vista + +Confirm +Confirmar + + +Do you really want to execute the command %y for one item? +Do you really want to execute the command %y for %x items? + + +Deseja mesmo executar o comando %y para um item? +Deseja mesmo executar o comando %y para %x itens? + + +&Execute +&Executar + + +1 directory +%x directories + + +1 directório +%x directórios + + + +1 file +%x files + + +1 ficheiro +%x ficheiros + + + +Showing %y of 1 row +Showing %y of %x rows + + +A mostrar %y de 1 linha +A mostrar %y de %x linhas + + +Set direction: +Escolher direcção: + +multiple selection +seleção múltipla + +Include via filter: +Incluir via filtro: + +Exclude via filter: +Excluir por filtro: + +Include temporarily +Incluir temporariamente + +Exclude temporarily +Excluir temporariamente + +Delete +Eliminar + +Include all +Incluir tudo + +Exclude all +Excluir tudo + +Show icons: +Mostrar ícones: + +Small +Pequeno + +Medium +Médio + +Large +Grande + +Select time span... +Selecione intervalo de tempo... + +Show "%x" +Mostrar "%x" + +Last session +Última Sessão + +Folder Comparison and Synchronization +Comparação e Sincronização de Pastas + +Configuration saved +Configuração guardada + +FreeFileSync batch +FreeFileSync batch + +Do you want to save changes to %x? +Deseja guardar as alterações a %x? + +Never save &changes +Nunca guardar &alterações + +Do&n't save +Não g&uardar + +Remove entry from list + + +Synchronization Settings +Definições de Sincronização + +Clear filter +Limpar filtro + +Show files that exist on left side only +Mostrar ficheiros existentes somente à esquerda + +Show files that exist on right side only +Mostrar ficheiros existentes somente à direita + +Show files that are newer on left +Mostrar ficheiros mais recentes à esquerda + +Show files that are newer on right +Mostrar ficheiros mais recentes à direita + +Show files that are equal +Mostrar ficheiros iguais + +Show files that are different +Mostrar ficheiros diferentes + +Show conflicts +Mostrar conflitos + +Show files that will be created on the left side +Mostrar ficheiros a ser criados à esquerda + +Show files that will be created on the right side +Mostrar ficheiros a ser criados à direita + +Show files that will be deleted on the left side +Mostrar ficheiros a ser apagados à esquerda + +Show files that will be deleted on the right side +Mostrar ficheiros a ser apagados à direita + +Show files that will be updated on the left side +Mostrar ficheiros a ser atualizados à esquerda + +Show files that will be updated on the right side +Mostrar ficheiros a ser atualizados à direita + +Show files that won't be copied +Mostrar ficheiros que não serão copiados + +Show filtered or temporarily excluded files +Mostrar ficheiros filtrados ou temporariamente excluidos + +Save as default + + +Filter +Filtro + +All files are in sync +Todos os ficheiros estão sincronizados + +Cannot find %x +Não é possível descobrir %x + +Move up + + +Move down + + +Comma-separated values +Valores separados por virgula + +File list exported +Lista dos ficheiros exportada + +Searching for program updates... +A procurar actualizações do programa... + +Close progress dialog +Fechar diálogo de progresso + +Log off +Terminar sessão + +Standby +Standby + +Shut down +Desligar + +Scanning... +A pesquisar... + +Comparing content... +A comparar... + +Info +Info + +Select all +Seleccionar tudo + +Paused +Em pausa + +Initializing... +A iniciar... + +Completed +Terminado + +&Continue +&Continuar + +Progress +Progresso + +Log +Registo + + +Do you really want to move the following item to the recycle bin? +Do you really want to move the following %x items to the recycle bin? + + +Deseja mesmo mover o seguinte item para a reciclagem? +Deseja mesmo mover os seguintes %x itens para a reciclagem? + + +Move +Mover + + +Do you really want to delete the following item? +Do you really want to delete the following %x items? + + +Deseja mesmo eliminar o seguinte item? +Deseja mesmo eliminar os seguintes %x itens? + + +Preferences +Preferências + +Copy DACL, SACL, Owner, Group + + +Integrate external applications into context menu. The following macros are available: +Integrar aplicações externas no menu de contexto. As seguintes macros estão disponíveis: + +- full file or folder name +- nome completo de ficheiro ou pasta + +- folder part only +- nome da pasta parcial + +- Other side's counterpart to %item_path% +- Contrapartida de %item_path% + +- Other side's counterpart to %item_folder% +- Contrapartida de %item_folder% + +Show hidden dialogs and warning messages again? +Mostrar diálogos ocultos e mensagens de erro novamente? + +&Show +&Mostrar + +Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. +Identificar e propagar mudanças nos dois lados. Eliminações, cópias e conflitos são detectados automaticamente usando base de dados. + +Create a mirror backup of the left folder by adapting the right folder to match. +Criar uma cópia exacta da pasta à esquerda, adaptando a da direita para coincidir. + +Copy new and updated files to the right folder. +Copiar ficheiros novos e actualizados para a pasta à direita. + +Configure your own synchronization rules. +Configure as suas regras de sincronização. + +Today +Hoje + +This week +Esta semana + +This month +Este mês + +This year +Este ano + +Last x days +Últimos x dias + +Byte +Byte + +KB +KB + +MB +MB + +Replace +Substituir + +Move files and replace if existing +Mover ficheiros e substituir se existirem + +Time stamp +Selo temporal + +Append a time stamp to each file name +Adicione data/hora ao nome de cada ficheiro + +Comparison +Comparação + +Synchronization +Sincronização + +Leave as unresolved conflict +Deixar como conflito + +File +Ficheiro + +YYYY-MM-DD hhmmss +AAAA-MM-DD hhmmss + +Files +Ficheiros + +Items +Itens + +Percentage +Percentagem + +Unable to register to receive system messages. +Não foi possível registar para receber mensagens do sistema. + +Unable to register device notifications for %x. + + +Cannot monitor directory %x. +Não é possível monitorizar o directório %x. + +The file is locked by another process: +O ficheiro está bloqueado por outro processo: + +Cannot write file attributes of %x. +Não é possível escrever os atributos de %x. + +Cannot read security context of %x. +Não é possível ler o contexto de segurança %x. + +Cannot write security context of %x. +Não é possível escrever o contexto de segurança %x. + +Cannot read permissions of %x. +Não é possível ler as permissões de %x. + +Cannot copy permissions from %x to %y. + + +Cannot find system function %x. +Não é possível encontrar a função do sistema %x. + +Cannot copy attributes from %x to %y. + + +Cannot copy file %x to %y. +Não é possível copiar o ficheiro %x para %y. + +Type of item %x is not supported: +Tipo de item %x não é suportado: + +%x TB +%x TB + +%x PB +%x PB + + +1 min +%x min + + +1 min +%x mins + + + +1 hour +%x hours + + +1 hora +%x horas + + + +1 day +%x days + + +1 dia +%x dias + + +Cannot set privilege %x. +Não é possível definir o privilégio %x. + +Unable to suspend system sleep mode. +Não é possível retornar do modo de suspensão do sistema. + +Cannot change process I/O priorities. +Não é possível alterar as prioridades de E / S do processo. + +Checking recycle bin failed for folder %x. +Verificar a reciclagem falhou no directório %x. + +The following XML elements could not be read: + + +Configuration file %x is incomplete. The missing elements will be set to their default values. + + +Prepare installation +A preparar a instalação + +Choose which components you want to install. +Escolha os componentes a instalar. + +Select installation type: +Selecionar tipo de instalação: + +Local +Local + +Portable +Portátil + +recommended +recomendada + +Save settings to "%APPDATA%\FreeFileSync" +Guardar as definições em "%APPDATA%\FreeFileSync" + +Register FreeFileSync file extensions +Registar as extensões do FreeFileSync + +Create Explorer context menu entries +Criar entradas de menu de contexto no Explorer + +Save settings in installation directory +Guardar as definições no directório da instalação + +Do not write to Registry +Não escrever no Registo + +Just copy the files +Copiar apenas os ficheiros + +Choose a directory for installation: +Escolha um directório para a instalação: + +Create shortcuts: +Criar atalhos: + +Desktop +Área de trabalho + +Start menu +Menu Iniciar + +Registering FreeFileSync file extensions +A registar as extensões do FreeFileSync + +Unregistering FreeFileSync file extensions +A apagar o registo das extensões do FreeFileSync + +FreeFileSync Configuration +Configuração do FreeFileSync + +FreeFileSync Batch File +Ficheiro Batch FreeFileSync + +FreeFileSync Synchronization Database +Base de Dados de Sincronização FreeFileSync + +RealtimeSync Configuration +Configuração do RealtimeSync + +Edit with FreeFileSync +Editar com FreeFileSync + diff --git a/FreeFileSync/Build/Languages/portuguese.lng b/FreeFileSync/Build/Languages/portuguese.lng deleted file mode 100644 index c4e33b9b..00000000 --- a/FreeFileSync/Build/Languages/portuguese.lng +++ /dev/null @@ -1,1716 +0,0 @@ -
    - Português - Miguel Balseiro - pt_PT - flag_portugal.png - 2 - n == 1 ? 0 : 1 -
    - -Both sides have changed since last synchronization. -Ambos os lados tiveram alterações desde a última sincronização. - -Cannot determine sync-direction: -Não é possível saber a direção de sincronização: - -No change since last synchronization. -Não há alterações desde a última sincronização. - -The database entry is not in sync considering current settings. -A base de dados não está sincronizada com as definições correntes. - -Setting default synchronization directions: Old files will be overwritten with newer files. -Escolher direcção de sincronização por defeito: Os ficheiros antigos serão substituídos pelos novos. - -Checking recycle bin availability for folder %x... -A verificar a disponibilidade da reciclagem para a pasta %x... - -Moving file %x to the recycle bin -Mover ficheiro %x para a reciclagem - -Moving folder %x to the recycle bin -Mover pasta %x para a reciclagem - -Moving symbolic link %x to the recycle bin -Mover link simbólico %x para a reciclagem - -Deleting file %x -Eliminar ficheiro %x - -Deleting folder %x -Eliminar pasta %x - -Deleting symbolic link %x -Eliminar link simbólico %x - -The recycle bin is not available for the following folders. Files will be deleted permanently instead: -A reciclagem não está disponível para as seguintes pastas. Os ficheiros serão, em alternativa, eliminados permanentemente: - -An exception occurred -Ocorreu uma excepção - -A directory path is expected after %x. -É esperado um caminho de directório após %x. - -Syntax error -Erro de sintaxe - -Cannot find file %x. - - -File %x does not contain a valid configuration. -Ficheiro %x não tem uma configuração válida. - -Unequal number of left and right directories specified. -Número desigual de directórios à esquerda e à direita. - -The config file must not contain settings at directory pair level when directories are set via command line. -O ficheiro de configuração não deve conter configurações ao nível de par-directório quando os directórios são definidos pela linha de comandos. - -Directories cannot be set for more than one configuration file. -Os directórios não podem ser definidos em mais do que um ficheiro de configuração. - -Command line -Linha de comandos - -Syntax: -Sintaxe: - -global config file: -ficheiro configuração global: - -config files: -ficheiros configuração: - -directory -directório - -Path to an alternate GlobalSettings.xml file. -Caminho para o ficheiro GlobalSettings.xml alternativo. - -Any number of FreeFileSync .ffs_gui and/or .ffs_batch configuration files. -Qualquer número de ficheiros de configuração .ffs_gui e/ou .ffs_batch do FreeFileSync. - -Any number of alternative directory pairs for at most one config file. -Qualquer número de pares de directórios alternativos para apenas um ficheiro de configuração. - -Open configuration for editing without executing it. - - -Cannot find the following folders: -Não é possível encontrar as seguintes pastas: - -You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. -Pode ignorar este erro para considerar cada pasta como vazia. As pastas necessárias serão criadas automaticamente durante a sincronização. - -A folder input field is empty. -Um dos campos de directório para comparar está vazio. - -The corresponding folder will be considered as empty. -A pasta correspondente será considerada como vazia. - -The following folder paths are dependent from each other: -Os seguintes pares de pastas são dependentes: - -File %x has an invalid date. -Ficheiro %x tem data inválida. - -Date: -Data: - -Files %x have the same date but a different size. -Os ficheiros %x têm a mesma data, mas tamanho diferente. - -Size: -Tamanho: - -Content comparison was skipped for excluded files %x. -Comparação por conteúdo foi ignorada para o ficheiro excluído %x. - -Items differ in attributes only -Itens diferem apenas nos atributos - -Resolving symbolic link %x -Resolver link simbólico %x - -Comparing content of files %x -A comparar o conteúdo do ficheiro %x - -Generating file list... -A gerar lista ficheiros... - -Starting comparison -A iniciar a comparação - -Calculating sync directions... -A calcular a direcção de sincronização... - -Out of memory. -Sem memória disponível. - -Item exists on left side only -Item existe apenas à esquerda - -Item exists on right side only -Item existe apenas à direita - -Left side is newer -Esquerda é mais recente - -Right side is newer -Direita é mais recente - -Items have different content -Itens tem conteúdo diferente - -Both sides are equal -Ambos os lados iguais - -Conflict/item cannot be categorized -Conflito/item não pode ser categorizado - -Copy new item to left -Copiar novo item para a esquerda - -Copy new item to right -Copiar novo item para a direita - -Delete left item -Apagar item esquerdo - -Delete right item -Apagar item direito - -Move file on left -Mover ficheiro à esquerda - -Move file on right -Mover ficheiro à direita - -Update left item -Atualizar item esquerdo - -Update right item -Atualizar item direito - -Do nothing -Não fazer nada - -Update attributes on left -Actualizar atributos à esquerda - -Update attributes on right -Actualizar atributos à direita - -Cannot read file %x. -Não é possível ler o ficheiro %x. - - -Unexpected size of data stream. -Expected: %x bytes -Actual: %y bytes - - - -Cannot write permissions of %x. -Não é possível escrever as permissões de %x. - -Operation not supported for different base folder types. - - -Cannot write file %x. -Não é possível escrever o ficheiro %x. - -Cannot copy symbolic link %x to %y. -Não é possível criar o link simbólico de %x para %y. - -Cannot move file %x to %y. -Não é possível mover o ficheiro %x para %y. - -Cannot enumerate directory %x. -Não é possível enumerar o directório %x. - -Cannot read file attributes of %x. -Não é possível ler os atributos do ficheiro %x. - -Cannot find %x. - - -Cannot open file %x. -Não é possível abrir o ficheiro %x. - -Cannot delete directory %x. -Não é possível eliminar o directório %x. - -Cannot delete file %x. -Não é possível eliminar o ficheiro %x. - -Cannot find device %x. - - -Cannot determine free disk space for %x. - - -Cannot create directory %x. -Não é possível criar o directório %x. - -Cannot write modification time of %x. -Não é possível alterar a data de modificação a %x. - -Cannot determine final path for %x. -Não é possível determinar o caminho final de %x. - -Cannot resolve symbolic link %x. -Não é possível resolver o link simbólico %x. - -Unable to move %x to the recycle bin. -Não é possível mover %x para a reciclagem. - -Cannot open directory %x. -Não é possível abrir o directório %x. - -Incorrect command line: -Linha de comandos incorrecta: - -Error Code %x: -Código de erro %x: - -Failed to connect to SFTP server %x. - - - -1 byte -%x bytes - - -1 byte -%x bytes - - -%x MB -%x MB - -%x KB -%x KB - -%x GB -%x GB - -Cannot load file %x. -Não é possível carregar o ficheiro %x. - -Database file %x is incompatible. -Base de dados %x não é compatível. - -Initial synchronization: -Sincronização inicial: - -Database file %x does not yet exist. -Base de dados %x não existe. - -Database file is corrupt: -Ficheiro de base de dados está corrompido: - -Database files do not share a common session. -As bases de dados são de sessões diferentes. - -Searching for folder %x... -À procura da pasta %x... - -Time out while searching for folder %x. - - -Cannot get process information. -Não é possível obter informação sobre o processo. - -Waiting while directory is locked: -À espera do bloqueio do directório: - -Lock owner: -Dono do bloqueio: - - -1 sec -%x sec - - -1 seg -%x segs - - -Detecting abandoned lock... -Detectado bloqueio abandonado... - -Creating file %x -Criar ficheiro %x - -Saving file %x... -Guardar ficheiro %x... - -Items processed: -Elementos processados: - -Items remaining: -Elementos restantes: - -Total time: -Tempo total: - -Error parsing file %x, row %y, column %z. -Erro ao analisar ficheiro %x, linha %y, coluna %z. - -Cannot set directory lock for %x. -Não é possível colocar o bloqueio de directório para %x. - -Scanning: -A pesquisar: - - -1 thread -%x threads - - -1 thread -%x threads - - -/sec -/seg - -%x items/sec -%x itens/seg - -Show in Explorer -Mostrar no Explorer - -Open with default application -Abrir com a aplicação associada - -Browse directory -Procurar directório - -Cannot access the Volume Shadow Copy Service. -Não é possível aceder ao serviço Volume Shadow Copy. - -Please use FreeFileSync 64-bit version to create shadow copies on this system. -Utilize a versão 64-bit do FreeFileSync para criar cópias sombra neste sistema. - -Cannot determine volume name for %x. -Não é possível determinar o nome do volume para %x. - -Volume name %x is not part of file path %y. -Nome de volume %x não faz parte do caminho do ficheiro %y. - -Stop requested: Waiting for current operation to finish... -Paragem solicitada: À espera que termine a operação actual... - -Unable to create time stamp for versioning: -Não é possível criar data/hora para controlo de versões: - -Drag && drop -Arrastar && Largar - -Cannot find folder %x. -Não é possível encontrar a pasta %x. - -Select a folder -Selecione uma pasta - -&Open... -&Abrir... - -Save &as... -Guardar &como... - -E&xit -S&air - -&File -&Ficheiro - -&View help -&Ver ajuda - -&About -So&bre - -&Help -A&juda - -Usage: -Uso: - -1. Select folders to watch. -1. Selecionar pastas para observar. - -2. Enter a command line. -2. Inserir a linha de comando. - -3. Press 'Start'. -3. Pressionar 'Iniciar'. - -To get started just import a .ffs_batch file. -Para começar basta importar um ficheiro .ffs_batch. - -Folders to watch: -Pastas a verificar: - -Add folder -Adicionar pasta - -Remove folder -Remover pasta(s) - -Browse -Procurar - -Idle time (in seconds): -Tempo de espera (em segundos): - -Idle time between last detected change and execution of command -Tempo de espera entre a última alteração detetada e a execução do comando - -Command line: -Linha de comandos: - - -The command is triggered if: -- files or subfolders change -- new folders arrive (e.g. USB stick insert) - - -O comando é executado se: -- ficheiros ou subpastas forem alterados -- forem detetadas novas pastas (p.e. pen USB) - - -&Start -&Início - -About -Sobre - -Build: %x -Build: %x - -All files -Todos os ficheiros - -Automated Synchronization -Sincronização Automática - -Directory monitoring active -Monitorização de directório activa - -Waiting until all directories are available... -A aguardar que todos os directórios fiquem disponíveis... - -Error -Erro - -&Restore -&Restaurar - -&Show error -Mostrar &erro - -&Quit -&Sair - -&Retry -&Tentar de Novo - -File content -Conteúdo do ficheiro - -File time and size -Data e tamanho do ficheiro - -Two way -Duas vias - -Mirror -Espelhar - -Update -Actualizar - -Custom -Personalizado - -Multiple... -Multiplo... - -Moving file %x to %y -Mover ficheiro %x para %y - -Moving folder %x to %y -Mover pasta %x para %y - -Moving symbolic link %x to %y -Mover link simbólico %x para %y - -Removing old versions... -A remover versões antigas... - -Creating symbolic link %x -Criar link simbólico %x - -Creating folder %x -Criar pasta %x - -Updating file %x -Atualizar ficheiro %x - -Updating symbolic link %x -Atualizar link simbólico %x - -Verifying file %x -A verificar ficheiro %x - -Updating attributes of %x -Actualizar atributos de %x - -%x and %y have different content. - - -Data verification error: - - -Creating a Volume Shadow Copy for %x... -A criar Volume Shadow Copy para %x... - -Target folder %x already existing. -Directório de destino %x já existe. - -Target folder input field must not be empty. -Campo de directório de destino não deve estar vazio. - -Source folder %x not found. -Directório %x não encontrado. - -Please enter a target folder for versioning. -Introduza uma pasta de destino para o controlo de versões. - -The following items have unresolved conflicts and will not be synchronized: -Os seguintes itens têm conflitos não resolvidos, e não serão sincronizados: - -The following folders are significantly different. Make sure you have selected the correct folders for synchronization. - - -Not enough free disk space available in: -Não há espaço livre suficiente em: - -Required: -Requirido: - -Available: -Disponível: - -Multiple folder pairs write to a common subfolder. Please review your configuration. -Vários pares de pastas escrevem para uma subpasta comum. Por favor, revise a sua configuração. - -Synchronizing folder pair: -Sincronizar o par de pastas: - -Generating database... -A gerar base de dados... - -job name -nome da tarefa - -Synchronization stopped -Sincronização parada - -Stopped -Parado - -Synchronization completed with errors -Sincronização completa com erros - -Synchronization completed with warnings -Sincronização completa com avisos - -Warning -Atenção - -Nothing to synchronize -Nada a sincronizar - -Synchronization completed successfully -Sincronização completa com sucesso - -Cleaning up old log files... -A limpar ficheiros log antigos... - -You can switch to FreeFileSync's main window to resolve this issue. -Pode mudar para a janela principal do FreeFileSync para resovler este problema. - -&Don't show this warning again -&Não mostrar este aviso novamente - -&Ignore -&Ignorar - -&Switch -&Trocar - -Switching to FreeFileSync's main window -A mudar para a janela principal do FreeFileSync - - -Automatic retry in 1 second... -Automatic retry in %x seconds... - - -Repetir automaticamente dentro de 1 segundo... -Repetir automaticamente dentro de %x segundos... - - -&Ignore subsequent errors -&Ignorar erros subsequentes - -Retrying operation... -A repetir a operação... - -Serious Error -Erro Grave - -Check for Program Updates -Procurar actualizações do programa - -A new version of FreeFileSync is available: -Uma nova versão do FreeFileSync está disponível: - -Download now? -Fazer download agora? - -&Download -&Download - -FreeFileSync is up to date. -FreeFileSync está actualizado. - -Unable to connect to www.freefilesync.org. -Não é possível ligar a www.freefilesync.org. - -Cannot find current FreeFileSync version number online. Do you want to check manually? -Não é possível encontrar a última versão do FreeFileSync online. Deseja verificar manualmente? - -&Check -&Verificar - -Symlink -Link Simbólico - -Folder -Pasta - -Full path -Caminho completo - -Name -Nome - -Relative folder -Pasta relativa - -Base folder -Pasta principal - -Size -Tamanho - -Date -Data - -Extension -Extensão - -Category -Categoria - -Action -Ação - -Local comparison settings -Opções locais de comparação - -Local synchronization settings -Opções locais de sincronização - -Local filter -Filtro local - -Active -Activo - -None -Nenhum - -Remove local settings -Apagar opções locais - -Clear local filter -Limpar filtro local - -Copy -Copiar - -Paste -Colar - -Local Synchronization Settings -Opções Locais Sincronização - -The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. - - -&New -&Novo - -&Save -G&uardar - -Save as &batch job... -Guardar como &batch... - -Start &comparison -Iniciar &comparaçao - -C&omparison settings -Opções de c&omparação - -&Filter settings -Opções de &filtros - -S&ynchronization settings -Opções de s&incronização - -Start &synchronization -Iniciar &sincronização - -&Actions -&Acções - -&Options -&Opções - -&Language -&Idioma - -&Find... -&Procurar... - -&Reset layout -&Restaurar esquema - -&Export file list... -&Exportar lista de ficheiros... - -&Tools -&Ferramentas - -&Check for new version -&Procurar por actualizações - -&Check now -&Verificar agora - -Check &automatically once a week -Verificar &automaticamente uma vez por semana - -Cancel -Cancelar - -Compare -Comparar - -Synchronize -Sincronizar - -Add folder pair -Adicionar um par de pastas - -Remove folder pair -Remover o par de pastas - -Select SFTP folder - - -Swap sides -Trocar lados - -Close search bar -Fechar barra de pesquisa - -Find: -Procurar: - -Match case -Correspondência - -New -Novo - -Open... -Abrir... - -Save -Guardar - -Save as... -Guardar como... - -View type: -Tipo de vista: - -Select view: -Seleccionar vista: - -Statistics: -Estatísticas: - -Number of files and folders that will be deleted -Número de ficheiros e pastas a ser eliminados - -Number of files that will be updated -Número de ficheiros a ser atualizados - -Number of files and folders that will be created -Número de ficheiros e pastas a ser criados - -Total bytes to copy -Total em bytes a copiar - -Use local settings: -Usar opções locais: - -Select a variant: -Seleccionar uma variante: - -Identify equal files by comparing modification time and size. -Identificar ficheiros iguais ao comparar hora de modificação e tamanho. - -Identify equal files by comparing the file content. -Identificar ficheiros iguais ao comparar o conteúdo. - -&Ignore time shift (in hours) - - -Consider file times with specified offset as equal -Considerar ficheiros com o desvio de tempo especificado como iguais - -Handle daylight saving time -Lidar com horário de verão - -Include &symbolic links: - - -&Follow - - -&Direct - - -More information -Mais informação - -Local settings: -Opções locais: - -Include: -Incluir: - -Exclude: -Excluir: - -Show examples -Mostrar exemplos - -Time span: -Intervalo de tempo: - -File size: -Tamanho ficheiro: - -Minimum: -Mínimo: - -Maximum: -Máximo - -Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. -Seleccionar regras de filtro para excluir certos ficheiros da sincronização. Insira os caminhos relativos ao par de directórios correspondente. - -C&lear -&Limpar - -Detect moved files -Detectar ficheiros movidos - - -- Not supported by all file systems -- Requires and creates database files -- Detection not available for first sync - - - -Detect synchronization directions with the help of database files -Detectar a direcção de sincronização com a ajuda de base de dados - -Delete files: -Eliminar ficheiros: - -&Permanent -&Permanente - -Delete or overwrite files permanently -Apagar ou substituir ficheiros permanentemente - -&Recycle bin -&Reciclagem - -Back up deleted and overwritten files in the recycle bin -Fazer backup dos ficheiros apagados e substituidos na reciclagem - -&Versioning -Controlo &Versões - -Move files to a user-defined folder -Mover ficheiros para uma pasta definida pelo utilizador - -Naming convention: -Convenção de nomes: - -Handle errors: -Tratar erros: - -Hide all error and warning messages -Ocultar todas as mensagens de erro/aviso - -&Pop-up -&Popup - -Show pop-up on errors or warnings -Mostrar popup em caso de erros ou avisos - -On completion: -Ao completar: - -OK -OK - -Enter your SFTP login details: - - -Server name or IP address: - - -Examples: - - -User name: - - -Password: - - -&Show password - - -Directory on server: - - - - -Start synchronization now? -Iniciar sincronização agora? - -Variant: -Variante: - -&Don't show this dialog again -&Não mostrar este diálogo novamente - -Arrange folder pair - - -Items found: -Elementos encontrados: - -Time remaining: -Tempo restante: - -Time elapsed: -Tempo decorrido - -Synchronizing... -A sincronizar... - -Minimize to notification area -Minimizar para a área de notificação - -Bytes copied: -Bytes copiados: - -Close -Fechar - -&Pause -&Pausa - -Stop -Parar - -Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x -Criar ficheiro batch para sincronização automática. Para iniciar, fazer duplo clique no ficheiro ou acrescentar ao planeador de tarefas: %x - -&Stop -&Parar - -Stop synchronization at first error -Para sincronização ao primeiro erro - -Run minimized -Correr minimizado - -Save log: -Guardar registo: - -Limit: -Limitar: - -Limit maximum number of log files -Limitar o número máximo de ficheiros log - -How can I schedule a batch job? -Como posso agendar um trabalho batch? - -The following settings are used for all synchronization jobs. -As seguintes definições são usadas para todas as sincronizações. - -Fail-safe file copy -Cópia à prova de falhas - - -Copy to a temporary file (*.ffs_tmp) before overwriting target. -This guarantees a consistent state even in case of a serious error. - - -Copiar para um ficheiro temporário (*.ffs_tmp) antes de substituir. -Isto garante um estado consistente mesmo em caso de falha grave. - - -(recommended) -(recomendado) - -Copy locked files -Copiar ficheiros bloqueados - -Copy shared or locked files using the Volume Shadow Copy Service. -Copiar ficheiros partilhados ou bloqueados usando o serviço Volume Shadow Copy. - -(requires administrator rights) -(requer permissões de administrador) - -Copy file access permissions -Copiar permissões de acesso do ficheiro - -Transfer file and folder permissions. -Transferir permissões de pasta e ficheiro. - -Automatic retry on error: -Retentar automaticamente em caso de erro: - -Retry count: -Nº de tentativas: - -Delay (in seconds): -Atraso (em segundos): - -Customize context menu: -Personalizar menu de contexto: - -Description -Descrição - -Show hidden dialogs again -Mostrar diálogos ocultos novamente - -Show all permanently hidden dialogs and warning messages again -Mostrar todos os diálogos escondidos permanentemente e mensagens de aviso novamente - -&Default -&Config. Iniciais - -Source code written in C++ using: -Código fonte escrito em C++ utilizando: - -If you like FreeFileSync: -Se gosta do FreeFileSync: - -Donate with PayPal -Doar usando PayPal - -Feedback and suggestions are welcome -Comentários e sugestões são apreciados - -Homepage -Site - -Email -Email - -Published under the GNU General Public License -Publicado sobre GNU General Public License - -Many thanks for localization: -Muito obrigado pela localização: - -SSH File Transfer Protocol - - -Save as Batch Job -Guardar como Ficheiro Batch - -Delete Items -Eliminar Itens - -Options -Opções - -Select Time Span -Seleccionar Intervalo de Tempo - -&Preferences - - -Main Bar -Barra principal - -Folder Pairs -Par de Pastas - -Find -Procurar - -View Settings -Ver Opções - -Configuration -Configuração - -Overview -Vista - -Confirm -Confirmar - - -Do you really want to execute the command %y for one item? -Do you really want to execute the command %y for %x items? - - -Deseja mesmo executar o comando %y para um item? -Deseja mesmo executar o comando %y para %x itens? - - -&Execute -&Executar - - -1 directory -%x directories - - -1 directório -%x directórios - - - -1 file -%x files - - -1 ficheiro -%x ficheiros - - - -Showing %y of 1 row -Showing %y of %x rows - - -A mostrar %y de 1 linha -A mostrar %y de %x linhas - - -Set direction: -Escolher direcção: - -multiple selection -seleção múltipla - -Include via filter: -Incluir via filtro: - -Exclude via filter: -Excluir por filtro: - -Include temporarily -Incluir temporariamente - -Exclude temporarily -Excluir temporariamente - -Delete -Eliminar - -Include all -Incluir tudo - -Exclude all -Excluir tudo - -Show icons: -Mostrar ícones: - -Small -Pequeno - -Medium -Médio - -Large -Grande - -Select time span... -Selecione intervalo de tempo... - -Show "%x" -Mostrar "%x" - -Last session -Última Sessão - -Folder Comparison and Synchronization -Comparação e Sincronização de Pastas - -Configuration saved -Configuração guardada - -FreeFileSync batch -FreeFileSync batch - -Do you want to save changes to %x? -Deseja guardar as alterações a %x? - -Never save &changes -Nunca guardar &alterações - -Do&n't save -Não g&uardar - -Remove entry from list - - -Synchronization Settings -Definições de Sincronização - -Clear filter -Limpar filtro - -Show files that exist on left side only -Mostrar ficheiros existentes somente à esquerda - -Show files that exist on right side only -Mostrar ficheiros existentes somente à direita - -Show files that are newer on left -Mostrar ficheiros mais recentes à esquerda - -Show files that are newer on right -Mostrar ficheiros mais recentes à direita - -Show files that are equal -Mostrar ficheiros iguais - -Show files that are different -Mostrar ficheiros diferentes - -Show conflicts -Mostrar conflitos - -Show files that will be created on the left side -Mostrar ficheiros a ser criados à esquerda - -Show files that will be created on the right side -Mostrar ficheiros a ser criados à direita - -Show files that will be deleted on the left side -Mostrar ficheiros a ser apagados à esquerda - -Show files that will be deleted on the right side -Mostrar ficheiros a ser apagados à direita - -Show files that will be updated on the left side -Mostrar ficheiros a ser atualizados à esquerda - -Show files that will be updated on the right side -Mostrar ficheiros a ser atualizados à direita - -Show files that won't be copied -Mostrar ficheiros que não serão copiados - -Show filtered or temporarily excluded files -Mostrar ficheiros filtrados ou temporariamente excluidos - -Save as default - - -Filter -Filtro - -All files are in sync -Todos os ficheiros estão sincronizados - -Cannot find %x -Não é possível descobrir %x - -Move up - - -Move down - - -Comma-separated values -Valores separados por virgula - -File list exported -Lista dos ficheiros exportada - -Searching for program updates... -A procurar actualizações do programa... - -Close progress dialog -Fechar diálogo de progresso - -Log off -Terminar sessão - -Standby -Standby - -Shut down -Desligar - -Scanning... -A pesquisar... - -Comparing content... -A comparar... - -Info -Info - -Select all -Seleccionar tudo - -Paused -Em pausa - -Initializing... -A iniciar... - -Completed -Terminado - -&Continue -&Continuar - -Progress -Progresso - -Log -Registo - - -Do you really want to move the following item to the recycle bin? -Do you really want to move the following %x items to the recycle bin? - - -Deseja mesmo mover o seguinte item para a reciclagem? -Deseja mesmo mover os seguintes %x itens para a reciclagem? - - -Move -Mover - - -Do you really want to delete the following item? -Do you really want to delete the following %x items? - - -Deseja mesmo eliminar o seguinte item? -Deseja mesmo eliminar os seguintes %x itens? - - -Preferences -Preferências - -Copy DACL, SACL, Owner, Group - - -Integrate external applications into context menu. The following macros are available: -Integrar aplicações externas no menu de contexto. As seguintes macros estão disponíveis: - -- full file or folder name -- nome completo de ficheiro ou pasta - -- folder part only -- nome da pasta parcial - -- Other side's counterpart to %item_path% -- Contrapartida de %item_path% - -- Other side's counterpart to %item_folder% -- Contrapartida de %item_folder% - -Show hidden dialogs and warning messages again? -Mostrar diálogos ocultos e mensagens de erro novamente? - -&Show -&Mostrar - -Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. -Identificar e propagar mudanças nos dois lados. Eliminações, cópias e conflitos são detectados automaticamente usando base de dados. - -Create a mirror backup of the left folder by adapting the right folder to match. -Criar uma cópia exacta da pasta à esquerda, adaptando a da direita para coincidir. - -Copy new and updated files to the right folder. -Copiar ficheiros novos e actualizados para a pasta à direita. - -Configure your own synchronization rules. -Configure as suas regras de sincronização. - -Today -Hoje - -This week -Esta semana - -This month -Este mês - -This year -Este ano - -Last x days -Últimos x dias - -Byte -Byte - -KB -KB - -MB -MB - -Replace -Substituir - -Move files and replace if existing -Mover ficheiros e substituir se existirem - -Time stamp -Selo temporal - -Append a time stamp to each file name -Adicione data/hora ao nome de cada ficheiro - -Comparison -Comparação - -Synchronization -Sincronização - -Leave as unresolved conflict -Deixar como conflito - -File -Ficheiro - -YYYY-MM-DD hhmmss -AAAA-MM-DD hhmmss - -Files -Ficheiros - -Items -Itens - -Percentage -Percentagem - -Unable to register to receive system messages. -Não foi possível registar para receber mensagens do sistema. - -Unable to register device notifications for %x. - - -Cannot monitor directory %x. -Não é possível monitorizar o directório %x. - -The file is locked by another process: -O ficheiro está bloqueado por outro processo: - -Cannot write file attributes of %x. -Não é possível escrever os atributos de %x. - -Cannot read security context of %x. -Não é possível ler o contexto de segurança %x. - -Cannot write security context of %x. -Não é possível escrever o contexto de segurança %x. - -Cannot read permissions of %x. -Não é possível ler as permissões de %x. - -Cannot copy permissions from %x to %y. - - -Cannot find system function %x. -Não é possível encontrar a função do sistema %x. - -Cannot copy attributes from %x to %y. - - -Cannot copy file %x to %y. -Não é possível copiar o ficheiro %x para %y. - -Type of item %x is not supported: -Tipo de item %x não é suportado: - -%x TB -%x TB - -%x PB -%x PB - - -1 min -%x min - - -1 min -%x mins - - - -1 hour -%x hours - - -1 hora -%x horas - - - -1 day -%x days - - -1 dia -%x dias - - -Cannot set privilege %x. -Não é possível definir o privilégio %x. - -Unable to suspend system sleep mode. -Não é possível retornar do modo de suspensão do sistema. - -Cannot change process I/O priorities. -Não é possível alterar as prioridades de E / S do processo. - -Checking recycle bin failed for folder %x. -Verificar a reciclagem falhou no directório %x. - -The following XML elements could not be read: - - -Configuration file %x is incomplete. The missing elements will be set to their default values. - - -Prepare installation -A preparar a instalação - -Choose which components you want to install. -Escolha os componentes a instalar. - -Select installation type: -Selecionar tipo de instalação: - -Local -Local - -Portable -Portátil - -recommended -recomendada - -Save settings to "%APPDATA%\FreeFileSync" -Guardar as definições em "%APPDATA%\FreeFileSync" - -Register FreeFileSync file extensions -Registar as extensões do FreeFileSync - -Create Explorer context menu entries -Criar entradas de menu de contexto no Explorer - -Save settings in installation directory -Guardar as definições no directório da instalação - -Do not write to Registry -Não escrever no Registo - -Just copy the files -Copiar apenas os ficheiros - -Choose a directory for installation: -Escolha um directório para a instalação: - -Create shortcuts: -Criar atalhos: - -Desktop -Área de trabalho - -Start menu -Menu Iniciar - -Registering FreeFileSync file extensions -A registar as extensões do FreeFileSync - -Unregistering FreeFileSync file extensions -A apagar o registo das extensões do FreeFileSync - -FreeFileSync Configuration -Configuração do FreeFileSync - -FreeFileSync Batch File -Ficheiro Batch FreeFileSync - -FreeFileSync Synchronization Database -Base de Dados de Sincronização FreeFileSync - -RealtimeSync Configuration -Configuração do RealtimeSync - -Edit with FreeFileSync -Editar com FreeFileSync - diff --git a/FreeFileSync/Build/Languages/turkish.lng b/FreeFileSync/Build/Languages/turkish.lng index 1ecec53a..4fa90ea2 100644 --- a/FreeFileSync/Build/Languages/turkish.lng +++ b/FreeFileSync/Build/Languages/turkish.lng @@ -8,19 +8,19 @@ Both sides have changed since last synchronization. -Son eşleştirmeden bu yana iki tarafın da içeriği değişmiş. +Son eşitlemeden bu yana iki tarafın da içeriği değişmiş. Cannot determine sync-direction: -Eşleştirme yönü belirlenemedi: +Eşitleme yönü belirlenemedi: No change since last synchronization. -Son eşleştirmeden bu yana bir değişiklik olmamış. +Son eşilemeden bu yana bir değişiklik olmamış. The database entry is not in sync considering current settings. Geçerli kayıtlar ile veritabanı kaydı aynı değil. Setting default synchronization directions: Old files will be overwritten with newer files. -Varsayılan eşleştirme yönleri ayarlanıyor: Yeni dosyalar eski dosyaların üzerine yazılacak. +Varsayılan eşitleme yönleri ayarlanıyor: Yeni dosyalar eski dosyaların üzerine yazılacak. Checking recycle bin availability for folder %x... %x klasörü için Geri Dönüşüm Kutusu kullanılabilir mi diye bakılıyor... @@ -56,7 +56,7 @@ Yazım hatası Cannot find file %x. - +%x dosyası bulunamadı. File %x does not contain a valid configuration. %x dosyası geçerli ayar bilgilerini içermiyor. @@ -92,16 +92,16 @@ FreeFileSync .ffs_gui ya da .ffs_batch ayar dosyalarının sayısı. Any number of alternative directory pairs for at most one config file. -Bir ayar dosyasındaki en fazla alternatif klasör çifti sayısı. +En fazla bir ayar dosyası için herhangi sayıda alternatif klasör çifti. Open configuration for editing without executing it. - +Ayarları yürütmeden düzenleme için açın. Cannot find the following folders: Aşağıdaki klasörler bulunamadı: You can ignore this error to consider each folder as empty. The folders then will be created automatically during synchronization. -Bu hatayı yok sayarak karşıdaki klasörleri boş kabul edebilirsiniz. Bu klasörler eşleştirme sırasında kendiliğinden oluşturulur. +Bu hatayı yok sayarak karşıdaki klasörleri boş kabul edebilirsiniz. Bu klasörler eşitleme sırasında kendiliğinden oluşturulur. A folder input field is empty. Bir klasör giriş alanı boş. @@ -110,7 +110,7 @@ Karşıdaki klasör boş olarak kabul edilecek. The following folder paths are dependent from each other: -Aşağıdaki klasör yolları birbirine bağlı: +Şu klasörler birbirine bağlı: File %x has an invalid date. %x dosyasının tarihi geçersiz. @@ -125,7 +125,7 @@ Boyut: Content comparison was skipped for excluded files %x. -Katılmayan %x dosyaları için içerik karşılaştırması atlandı. +%x katılmayan dosya için içerik karşılaştırması atlandı. Items differ in attributes only Yalnız öznitelikleri farklı ögeler @@ -143,7 +143,7 @@ Karşılaştırmaya başlanıyor Calculating sync directions... -Eşleştirme yönleri hesaplanıyor... +Eşitleme yönleri hesaplanıyor... Out of memory. Bellek yetersiz. @@ -197,7 +197,7 @@ Hiçbir işlem yapılmasın Update attributes on left -Soldaki öznitelikleri güncelle +Soldaki öznitelikleri güncellensin Update attributes on right Sağdaki öznitelikler güncellensin @@ -210,73 +210,77 @@ Unexpected size of data stream. Expected: %x bytes Actual: %y bytes - + +Veri akışının boyutu beklenenden farklı. +Beklenen: %x bayt +Gerçekleşen: %y bayt + Cannot write permissions of %x. %x izinleri yazılamadı. Operation not supported for different base folder types. - +Farklı temel klasör tipleri üzerindeki işlemler desteklenmiyor. Cannot write file %x. %x dosyası yazılamadı. Cannot copy symbolic link %x to %y. -%x sembolik bağlantısı %y olarak kopyalanamıyor. +%x sembolik bağlantısı %y hedefine kopyalanamadı. Cannot move file %x to %y. -%x dosyası %y üzerine taşınamadı. +%x dosyası %y hedefine taşınamadı. Cannot enumerate directory %x. -%x klasörü sayılamadı. +%x klasörü hesaplanamadı. Cannot read file attributes of %x. -%x dosyasının özellikleri okunamadı. +%x dosyasının öznitelikleri okunamadı. Cannot find %x. - +%x bulunamadı. Cannot open file %x. -%x dosyası açılamıyor. - -Cannot delete directory %x. -%x klasörü silinemedi. - -Cannot delete file %x. -%x dosyası silinemiyor. +%x dosyası açılamadı. Cannot find device %x. - +%x aygıtı bulunamadı. Cannot determine free disk space for %x. - +%x için boş disk alanı belirlenemedi. Cannot create directory %x. -%x klasörü eklenemedi. +%x klasörü oluşturulamadı. + +Cannot delete directory %x. +%x klasörü silinemedi. + +Cannot delete file %x. +%x dosyası silinemedi. Cannot write modification time of %x. -%x son değişiklik zamanı yazılamadı. +%x dosyasının değişiklik tarihi yazılamadı. Cannot determine final path for %x. -Son %x yolu belirlenemedi. +%x dosyasının son yolu belirlenemedi. Cannot resolve symbolic link %x. -%x simge bağlantısı çözümlenemedi +%x sembolik bağlantısı çözümlenemedi. Unable to move %x to the recycle bin. -%x Geri Dönüşüm Kutusuna atılamıyor. +%x çöp kutusuna atılamadı. Cannot open directory %x. %x klasörü açılamadı. Incorrect command line: -Geçersiz komut satırı: +Satırdaki komut geçersiz: Error Code %x: Hata Kodu %x: Failed to connect to SFTP server %x. - +%x SFTP sunucusuna bağlanılamadı. 1 byte @@ -300,10 +304,10 @@ Actual: %y bytes %x dosyası yüklenemedi. Database file %x is incompatible. -%x veritabanı dosyası uyumsuz +%x veritabanı dosyası uyumsuz. Initial synchronization: -Başlangıç eşleştirmesi: +Başlangıç eşitlemesi: Database file %x does not yet exist. %x veritabanı dosyası henüz yok. @@ -318,7 +322,7 @@ Actual: %y bytes %x klasörü aranıyor... Time out while searching for folder %x. - +%x klasörünü araştırma işlemi zaman aşımına uğradı. Cannot get process information. İşlem bilgisi alınamadı. @@ -342,7 +346,7 @@ Actual: %y bytes Kaldırılmış kilit algılanıyor... Creating file %x -%x dosyası ekleniyor +%x dosyası oluşturuluyor Saving file %x... %x dosyası kaydediliyor... @@ -360,7 +364,7 @@ Actual: %y bytes %x dosyası işlenirken hata, satır %y, sütun %z. Cannot set directory lock for %x. -%x için klasör kilidi uygulanamıyor. +%x için klasör kilidi uygulanamadı. Scanning: Taranıyor: @@ -405,10 +409,10 @@ Actual: %y bytes Durdurulması istendi: Yürürlükteki işlemin bitmesi bekleniyor... Unable to create time stamp for versioning: -Sürüm izlemesi için zaman damgası oluşturulamadı: +Sürümlendirme için zaman damgası oluşturulamadı: Drag && drop -Dosyaları sürükleyip buraya bırakabilirsiniz +Dosyaları sürükleyip buraya bırakın Cannot find folder %x. %x klasörü bulunamadı. @@ -417,10 +421,10 @@ Actual: %y bytes Bir klasör seçin &Open... -&Açın... +&Aç... Save &as... -F&arklı kaydedin... +F&arklı kaydet... E&xit Çı&kış @@ -429,7 +433,7 @@ Actual: %y bytes &Dosya &View help -&Yardıma bakın +&Yardım konuları &About H&akkında @@ -441,7 +445,7 @@ Actual: %y bytes Kullanım: 1. Select folders to watch. -1. İzlenecek klasörleri seçin +1. İzlenecek klasörleri seçin. 2. Enter a command line. 2. Bir komut satırı yazın. @@ -485,7 +489,7 @@ Komut şu durumlarda yürütülür:
    &Start -&Başlayın +&Başlatın About Hakkında @@ -497,7 +501,7 @@ Komut şu durumlarda yürütülür: Tüm dosyalar Automated Synchronization -Kendiliğinden Eşleştirme +Kendiliğinden Eşitleme Directory monitoring active Klasör izleme kullanılıyor @@ -554,10 +558,10 @@ Komut şu durumlarda yürütülür: Eski sürümler siliniyor... Creating symbolic link %x -%x sembolik bağlantısı ekleniyor +%x sembolik bağlantısı oluşturuluyor Creating folder %x -%x klasörü ekleniyor +%x klasörü oluşturuluyor Updating file %x %x dosyası güncelleniyor @@ -572,10 +576,10 @@ Komut şu durumlarda yürütülür: %x öznitelikleri güncelleniyor %x and %y have different content. - +%x ve %y farklı içeriklere sahip. Data verification error: - +Veri doğrulama hatası: Creating a Volume Shadow Copy for %x... %x için Birim Gölge Hizmeti oluşturuluyor... @@ -593,10 +597,10 @@ Komut şu durumlarda yürütülür: Sürüm izlemesinde kullanılacak bir hedef klasör yazın. The following items have unresolved conflicts and will not be synchronized: -Uyuşmazlığı çözülmemiş şu ögeler eşleştirilmeyecek: +Uyuşmazlığı çözülmemiş şu ögeler eşitlenmeyecek: The following folders are significantly different. Make sure you have selected the correct folders for synchronization. - +Şu klasörler arasında oldukça büyük farklar var. Eşitleme için doğru klasörleri seçtiğinize emin olun. Not enough free disk space available in: Şurada yeterli disk alanı yok : @@ -608,10 +612,10 @@ Komut şu durumlarda yürütülür: Kullanılabilir: Multiple folder pairs write to a common subfolder. Please review your configuration. -Birden çok klasör çifti aynı alt klasöre yazıyor. Lütfen ayarlarınızı gözden geçirin. +Çoklu klasör çiftleri ortak bir klasöre yazılır. Lütfen ayarlarınızı gözden geçirin. Synchronizing folder pair: -Eşleştirilen klasör çifti: +Eşitlenen klasör çifti: Generating database... Veri tabanı oluşturuluyor... @@ -620,25 +624,25 @@ Komut şu durumlarda yürütülür: iş adı Synchronization stopped -Eşleştirme durduruldu +Eşitleme durduruldu Stopped Durduruldu Synchronization completed with errors -Eşleştirme bazı hatalarla tamamlandı +Eşitleme bazı hatalarla tamamlandı Synchronization completed with warnings -Eşleştirme işlemi bazı uyarılarla tamamlandı +Eşitleme bazı uyarılar ile tamamlandı Warning Uyarı Nothing to synchronize -Eşleştirilecek bir şey yok +Eşitlenecek bir şey yok Synchronization completed successfully -Eşleştirme tamamlandı +Eşitleme tamamlandı Cleaning up old log files... Eski günlük dosyaları temizleniyor... @@ -650,7 +654,7 @@ Komut şu durumlarda yürütülür: Bu &uyarı bir daha görüntülenmesin &Ignore -&Yoksayın +&Yoksay &Switch &Değiştirin @@ -695,7 +699,7 @@ Komut şu durumlarda yürütülür: www.freefilesync.org sitesine bağlanılamadı. Cannot find current FreeFileSync version number online. Do you want to check manually? -Geçerli FreeFileSync sürüm numarası çevrimiçi olarak bulunamıyor. El ile denetlemek ister misiniz? +Geçerli FreeFileSync sürüm numarası çevrimiçi olarak bulunamadı. El ile denetlemek ister misiniz? &Check &Denetleyin @@ -737,7 +741,7 @@ Komut şu durumlarda yürütülür: Yerel karşılaştırma ayarları Local synchronization settings -Yerel eşleştirme ayarları +Yerel eşitleme ayarları Local filter Yerel süzgeç @@ -761,61 +765,61 @@ Komut şu durumlarda yürütülür: Yapıştırın Local Synchronization Settings -Yerel Eşleştirme Ayarları +Yerel Eşitleme Ayarları The selected folder %x cannot be used with FreeFileSync. Please select a folder on a local file system, network or an MTP device. - +Seçilmiş %x klasörü FreeFileSync tarafından kullanılamıyor. Lütfen yerel dosya sistemin, ağ ya da MTP aygıtı üzerinde bulunan bir klasör seçin. &New -Ye&ni +&Yeni &Save -&Kaydedin +&Kaydet Save as &batch job... -&Toplu iş olarak kaydedin... +&Toplu iş olarak kaydet... Start &comparison -&Karşılaştırmayı başlatın +&Karşılaştırmayı başlat C&omparison settings -Ka&rşılaştırma ayarları +K&arşılaştırma ayarları &Filter settings &Süzme ayarları S&ynchronization settings -Eşleştirme a&yarları +Eşi&tleme ayarları Start &synchronization -&Eşleştirmeyi başlatın +&Eşitlemeyi başlat &Actions İş&lemler &Options -A&yarlar +&Ayarlar &Language -Di&l +&Dil &Find... -A&rayın... +A&rama... &Reset layout -Düzeni sıfı&rlayın +Görünümü &sıfırla &Export file list... -Dosya list&esini verin... +&Dosya listesini ver... &Tools -A&raçlar +&Araçlar &Check for new version -Yeni &sürümü denetleyin +&Güncelleme denetimi &Check now -&Sürümü Denetleyin +Şimdi &Denetleyin Check &automatically once a week &Haftada bir kendiliğinden denetlensin @@ -824,10 +828,10 @@ Komut şu durumlarda yürütülür: İptal Compare -Karşılaştırın +Karşılaştır Synchronize -Eşleştirin +Eşitle Add folder pair Klasör çifti ekleyin @@ -836,7 +840,7 @@ Komut şu durumlarda yürütülür: Klasör çiftini silin Select SFTP folder - +SFTP klasörünü seçin Swap sides Sağ ve sol tarafları değiştirin @@ -845,28 +849,28 @@ Komut şu durumlarda yürütülür: Arama çubuğunu kapatın Find: -Bulun: +Aranacak ifade: Match case -Büyük-küçük harf uysun +Büyük küçük harf uyumu göz önüne alınsın New -Ekleyin +Yeni Open... -Açın... +Aç... Save -Kaydedin +Kaydet Save as... -Farklı kaydedin... +Farklı kaydet... View type: Görünüm tipi: Select view: -Görünüm seçin: +Görüntülenecek ögeler: Statistics: İstatistikler: @@ -890,40 +894,40 @@ Komut şu durumlarda yürütülür: İşlem tipini seçin: Identify equal files by comparing modification time and size. -Dosyaların aynı olup olmadığı, son değişiklik zamanı ve boyuta göre belirlensin. +Dosyaların aynı olup olmadığı, son değişiklik zamanı ve boyuta göre belirlenir. Identify equal files by comparing the file content. -Dosyaların aynı olup olmadığı, içeriklerine göre belirlensin. +Dosyaların aynı olup olmadığı, içeriklerine göre belirlenir. &Ignore time shift (in hours) - +Zaman farkı &yoksayılsın (saat) Consider file times with specified offset as equal -Belirtilen saat kadar zaman farkı yoksayılır +Belirtilen zaman farkı içindeki dosyalar eşit olarak algılansın Handle daylight saving time -Yaz saati uygulamasına bakın +Yaz saati bilgilerine bakın Include &symbolic links: - +&Sembolik bağlantılar katılsın: &Follow - +İ&zlensin &Direct - +&Yönlendirilsin More information -Ek bilgilere bakın +Ayrıntılı bilgilere bakın Local settings: Yerel ayarlar: Include: -Katılacak ögeler: +Katılacak: Exclude: -Katılmayacak ögeler +Katılmayacak: Show examples Örneklere bakın @@ -941,7 +945,7 @@ Komut şu durumlarda yürütülür: En büyük: Select filter rules to exclude certain files from synchronization. Enter file paths relative to their corresponding folder pair. -Eşleştirilmeyecek dosyaları süzecek kuralları belirleyin. Dosya yollarını bulundukları klasör çiftine göre yazın. +Eşitlenmeyecek dosyaların süzülme kurallarını belirleyin. Dosya yollarını bulundukları klasör çiftine göre yazın. C&lear &Temizleyin @@ -954,28 +958,32 @@ Komut şu durumlarda yürütülür: - Requires and creates database files - Detection not available for first sync - + +- Tüm dosya sistemleri tarafından desteklenmez +- Veritabanı dosyalarının kullanılması gerekir +- Algılama, ilk eşitleme sırasında kullanılamaz + Detect synchronization directions with the help of database files -Eşleştirme yönü, veritabanı dosyaları yardımı ile belirlensin +Eşitleme yönleri veritabanı dosyalarının yardımı ile algılanır Delete files: Dosya silme işlemi: &Permanent -&Kalıcı +&Kalıcı olarak silinsin Delete or overwrite files permanently Dosyalar kalıcı olarak silinir ya da üzerine yazılır &Recycle bin -Ge&ri Dönüşüm Kutusu +Ge&ri Dönüşüm Kutusuna atılsın Back up deleted and overwritten files in the recycle bin Silinen ya da üzerine yazılan dosyalar geri dönüşüm kutusuna gönderilir &Versioning -&Sürümleme +Eski &sürüm olarak saklansın Move files to a user-defined folder Dosyalar kullanıcı tarafından belirtilen bir klasöre taşınır @@ -990,42 +998,43 @@ Komut şu durumlarda yürütülür: Hiçbir hata ve uyarı iletisi görüntülenmez &Pop-up -Açılan &Pencere +&Görüntüle Show pop-up on errors or warnings Hata ya da uyarılar açılır pencerede görüntülenir On completion: -Eşleştirme tamamlandığında: +Tamamlandığında: OK Tamam Enter your SFTP login details: - +SFTP oturum açma bilgilerinizi yazın: Server name or IP address: - +Sunucu adı / IP adresi: + +Port: +Kapı: Examples: - +Örnekler: User name: - +Kullanıcı adı: Password: - +Parola: &Show password - +Parola &görüntülensin Directory on server: - - - +Sunucudaki klasör: Start synchronization now? -Eşleştirme başlatılsın mı? +Eşitleme başlatılsın mı? Variant: İşlem tipi: @@ -1034,7 +1043,7 @@ Komut şu durumlarda yürütülür: Bu pencere bir daha &görüntülenmesin Arrange folder pair - +Klasör çiftini belirleyin Items found: Bulunan öge: @@ -1046,7 +1055,7 @@ Komut şu durumlarda yürütülür: Geçen süre: Synchronizing... -Eşleştiriliyor... +Eşitleniyor... Minimize to notification area Bildirim alanına küçültün @@ -1064,19 +1073,19 @@ Komut şu durumlarda yürütülür: Durdurulsun Create a batch file for unattended synchronization. To start, double-click this file or schedule in a task planner: %x -Hiç bir soru sorulmadan eşleştirme yapılması için bir toplu iş dosyası oluşturun. İşlemi başlatmak için bu dosyaya çift tıklayın ya da bir görev zamanlayıcıya şu şekilde ekleyin: %x +Hiç bir soru sorulmadan eşitleme yapılması için bir toplu iş dosyası oluşturun. İşlemi başlatmak için bu dosyaya çift tıklayın ya da bir görev zamanlayıcıya şu şekilde ekleyin: %x &Stop -&Durdurun +&Durdur Stop synchronization at first error -Oluşacak ilk hatada eşleştirme durdurulur +Oluşacak ilk hatada eşitleme durdurulur Run minimized -Küçültülmüş olarak çalışsın +Küçülterek çalıştır Save log: -Günlüğe kaydedilsin: +Günlük kaydet: Limit: Sınır: @@ -1088,7 +1097,7 @@ Komut şu durumlarda yürütülür: Bir toplu işlem nasıl zamanlanır? The following settings are used for all synchronization jobs. -Aşağıdaki ayarlar tüm eşleştirme işlemleri için geçerlidir. +Aşağıdaki ayarlar tüm eşitleme işlemleri için geçerlidir. Fail-safe file copy Dosyalar hatasız kopyalansın @@ -1136,10 +1145,10 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Açıklama Show hidden dialogs again -Gizlenen iletiler yeniden görüntülensin +Gizlenmiş pencereler yeniden görüntülensin Show all permanently hidden dialogs and warning messages again -Gizlenen tüm ileti ve uyarılar yeniden görüntülensin +Kalıcı olarak gizlenmiş tüm ileti ve uyarılar yeniden görüntülenir &Default &Varsayılan @@ -1148,7 +1157,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Kaynak kodu C++ kullanılarak yazılmıştır: If you like FreeFileSync: -FreeFileSync’i beğendiyseniz: +FreeFileSync hoşunuza gittiyse: Donate with PayPal PayPal üzerinden bağış yapın @@ -1169,10 +1178,10 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Çeviriler için çok teşekkürler: SSH File Transfer Protocol - +SSH Dosya Aktarımı İletişim Kuralı Save as Batch Job -Toplu İş Olarak Kaydedin +Toplu İş Olarak Kaydet Delete Items Ögeleri Silin @@ -1184,7 +1193,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Zaman Aralığı &Preferences - +&Ayarlar Main Bar Ana Çubuk @@ -1193,7 +1202,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Klasör Çiftleri Find -Arayın +Arama View Settings Görünüm Ayarları @@ -1295,7 +1304,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Önceki oturum Folder Comparison and Synchronization -Klasör Karşılaştırma ve Eşleştirme +Klasör Karşılaştırma ve Eşitleme Configuration saved Ayarlar kaydedildi @@ -1313,13 +1322,13 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Kaydedilmesi&n Remove entry from list - +Kaydı listeden silin Synchronization Settings -Eşleştirme Ayarları +Eşitleme ayarları Clear filter -Süzgeci temizleyin +Süzgeci temizle Show files that exist on left side only Yalnız sol tarafta bulunan dosyaları görüntüler ya da gizler @@ -1343,46 +1352,46 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Uyuşmazlıkları görüntüler ya da gizler Show files that will be created on the left side -Sol tarafa eklenecek dosyalar görüntülensin +Sol tarafa eklenecek dosyaları görüntüler ya da gizler Show files that will be created on the right side -Sağ tarafa eklenecek dosyalar görüntülensin +Sağ tarafa eklenecek dosyaları görüntüler ya da gizler Show files that will be deleted on the left side -Sol tarafta silinecek dosyalar görüntülensin +Sol tarafta silinecek dosyaları görüntüler ya da gizler Show files that will be deleted on the right side -Sağ tarafta silinecek dosyalar görüntülensin +Sağ tarafta silinecek dosyaları görüntüler ya da gizler Show files that will be updated on the left side -Sol tarafta güncellenecek dosyalar görüntülensin +Sol tarafta güncellenecek dosyaları görüntüler ya da gizler Show files that will be updated on the right side -Sağ tarafta güncellenecek dosyalar görüntülensin +Sağ tarafta güncellenecek dosyaları görüntüler ya da gizler Show files that won't be copied -Kopyalanmayacak dosyalar görüntülensin +Kopyalanmayacak dosyaları görüntüler ya da gizler Show filtered or temporarily excluded files -Süzülmüş ya da geçici olarak katılmayan dosyalar görüntülensin +Süzülmüş ya da geçici olarak katılmayan dosyaları görüntüler ya da gizler Save as default - +Varsayılan olarak kaydedin Filter -Süzgeç +Süzme All files are in sync -Tüm dosyalar eşleştirildi +Tüm dosyalar eşitlendi Cannot find %x %x bulunamadı Move up - +Yukarı taşıyın Move down - +Aşağı taşıyın Comma-separated values Virgül ile ayrılmış değerler @@ -1457,10 +1466,10 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya
    Preferences -Tercihler +Ayarlar Copy DACL, SACL, Owner, Group - +DACL, SACL, Sahip, Grup kopyalansın Integrate external applications into context menu. The following macros are available: Sağ tık menüsüne dış uygulamalar eklenebilir. Şu etiketler kullanılabilir: @@ -1478,22 +1487,22 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya %item_folder% ögesinin diğer taraftaki karşılığı Show hidden dialogs and warning messages again? -Gizlenen tüm ileti ve uyarılar yeniden görüntülensin mi? +Gizlenmiş ileti ve uyarılar yeniden görüntülensin mi? &Show &Görüntülensin Identify and propagate changes on both sides. Deletions, moves and conflicts are detected automatically using a database. -İki tarafta da değişikliklere bakılır ve karşılıklı kopyalanır. Silinmiş, taşınmış ve çakışan ögeler, veritabanı kullanılarak kendiliğinden algılanır. +İki taraftaki değişiklikler belirlenir ve kopyalanır. Silinme, taşınma ve çakışmalar, veritabanı kullanılarak kendiliğinden algılanır. Create a mirror backup of the left folder by adapting the right folder to match. -Sağ klasör, sola uyacak şekilde güncellenerek, sol klasörün yansı yedeği oluşturulur. +Sağ klasör, sola uyacak şekilde değiştirilerek, sol klasörün yansı yedeği oluşturulur. Copy new and updated files to the right folder. -Sol taraftaki yeni ya da güncellenmiş ögeler sağ tarafa kopyalanır. +Sol taraftaki yeni ya da güncellenmiş dosyalar sağ tarafa kopyalanır. Configure your own synchronization rules. -Eşleştirme kuralları kullanıcının isteğine göre belirlenir. +Eşitleme kuralları kullanıcının isteğine göre belirlenir. Today Bugün @@ -1520,22 +1529,22 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya MB Replace -Değiştirin +Ad değiştirilsin Move files and replace if existing -Dosyalar taşınsın ve varsa üzerine yazılsın +Dosyalar taşınır ve varsa üzerine yazılır Time stamp Zaman damgası Append a time stamp to each file name -Her bir dosya adına bir zaman damgası eklensin +Dosya adlarına zaman damgası eklensin Comparison Karşılaştırma Synchronization -Eşleştirme +Eşitleme Leave as unresolved conflict Uyuşmazlık çözülmeden bırakılsın @@ -1550,7 +1559,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Dosyalar Items -Ögeler +Öge Percentage Yüzde @@ -1559,7 +1568,7 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Sistem iletilerini alabilmek için gerekli kayıt eklenemedi. Unable to register device notifications for %x. - +%x aygıtının bildirimleri için gerekli kayıt eklenemedi. Cannot monitor directory %x. %x klasörü izlenemiyor. @@ -1580,13 +1589,13 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya %x izinleri okunamadı. Cannot copy permissions from %x to %y. - +İzinler %x üzerinden %y üzerine kopyalanamadı. Cannot find system function %x. %x sistem işlevi bulunamadı. Cannot copy attributes from %x to %y. - +Öznitelikler %x üzerinden %y üzerine kopyalanamadı. Cannot copy file %x to %y. %x dosyası %y olarak kopyalanamadı. @@ -1634,22 +1643,22 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Sistem uyku kipine geçirilemedi. Cannot change process I/O priorities. -Giriş/Çıkış işlemi öncelikleri değiştirilemedi +Giriş/Çıkış işlemi öncelikleri değiştirilemedi. Checking recycle bin failed for folder %x. -%x klasörü için geri dönüşüm kutusu denetlenemedi. +%x klasörü için Geri Dönüşüm Kutusu denetlenemedi. The following XML elements could not be read: - +Şu XML bileşenleri okunamadı: Configuration file %x is incomplete. The missing elements will be set to their default values. - +%x ayar dosyası tam değil. Eksik bileşenler için varsayılan değerler kullanılacak. Prepare installation Yüklemeye hazırlanılıyor Choose which components you want to install. -Yüklenecek bileşenleri seçin. +Yüklemek istediğiniz bileşenleri seçin. Select installation type: Yükleme tipini seçin: @@ -1658,46 +1667,46 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya Yerel Portable -Portable +Taşınabilir recommended -önerilir +önerilen Save settings to "%APPDATA%\FreeFileSync" -Ayarlar "%APPDATA%\FreeFileSync" klasörüne kaydedilir +Ayarlar "%APPDATA%\FreeFileSync" kalsörüne kaydedilsin Register FreeFileSync file extensions -Kayıt defterine FreeFileSync dosya eklentileri eklenir +FreeFileSync dosya uzantıları ilişkilendirilsin Create Explorer context menu entries -Dosya yöneticisi sağ tık menü kayıtları eklensin +Windows Gezgini sağ tık menü kayıtları eklensin Save settings in installation directory -Ayarlar yükleme klasörüne kaydedilir +Ayarlar yükleme klasörüne kaydedilsin Do not write to Registry -Kayıt defterine herhangi bir bilgi eklenmez +Kayıt Defterine yazılmasın Just copy the files -Yalnızca dosyalar kopyalanır +Yalnız dosyalar kopyalansın Choose a directory for installation: -Yükleme klasörünü seçin: +Yüklenecek klasörü seçin: Create shortcuts: -Şuralarda kısayollar oluşturulsun: +Kısayollar oluşturulsun: Desktop Masaüstü Start menu -Başlat menüsü +Başlat Menüsü Registering FreeFileSync file extensions -FreeFileSync eklentileri kayıt defterine ekleniyor +FreeFileSync dosya uzantıları kayıt defterine ekleniyor Unregistering FreeFileSync file extensions -FreeFileSync eklentileri kayıt defterinden siliniyor +FreeFileSync dosya uzantıları kayıt defterinden siliniyor FreeFileSync Configuration FreeFileSync Ayarları @@ -1706,11 +1715,11 @@ Bu yöntem, ciddi bir hata oluşması durumunda bile işlemin tutarlı olarak ya FreeFileSync Toplu İşlem Dosyası FreeFileSync Synchronization Database -FreeFileSync Eşleştirme Veritabanı +FreeFileSync Eşitleme Veritabanı RealtimeSync Configuration -Gerçek Zamanlı Eşleştirme Ayarları +Gerçek Zamanlı Eşitleme Ayarları Edit with FreeFileSync -FreeFileSync ile düzenleyin +FreeFileSync ile düzenlensin diff --git a/FreeFileSync/Build/Resources.zip b/FreeFileSync/Build/Resources.zip index c660cc0e..5a5a7344 100644 Binary files a/FreeFileSync/Build/Resources.zip and b/FreeFileSync/Build/Resources.zip differ diff --git a/FreeFileSync/Source/RealtimeSync/application.cpp b/FreeFileSync/Source/RealtimeSync/application.cpp index 5dd5fe91..90dd8b99 100644 --- a/FreeFileSync/Source/RealtimeSync/application.cpp +++ b/FreeFileSync/Source/RealtimeSync/application.cpp @@ -38,20 +38,6 @@ IMPLEMENT_APP(Application); namespace { -/* -boost::thread::id mainThreadId = boost::this_thread::get_id(); - -void onTerminationRequested() -{ -std::wstring msg = boost::this_thread::get_id() == mainThreadId ? - L"Termination requested in main thread!\n\n" : - L"Termination requested in worker thread!\n\n"; -msg += L"Please file a bug report at: http://sourceforge.net/projects/freefilesync"; - -wxSafeShowMessage(_("An exception occurred"), msg); -std::abort(); -} -*/ #ifdef _MSC_VER void crtInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) { assert(false); } #endif @@ -62,8 +48,6 @@ const wxEventType EVENT_ENTER_EVENT_LOOP = wxNewEventType(); bool Application::OnInit() { - //std::set_terminate(onTerminationRequested); //unlike wxWidgets uncaught exception handling, this works for all worker threads - #ifdef ZEN_WIN #ifdef _MSC_VER _set_invalid_parameter_handler(crtInvalidParameterHandler); //see comment in diff --git a/FreeFileSync/Source/RealtimeSync/folder_selector2.cpp b/FreeFileSync/Source/RealtimeSync/folder_selector2.cpp index be9f505a..7bbed861 100644 --- a/FreeFileSync/Source/RealtimeSync/folder_selector2.cpp +++ b/FreeFileSync/Source/RealtimeSync/folder_selector2.cpp @@ -27,13 +27,13 @@ void setFolderPath(const Zstring& dirpath, wxTextCtrl* txtCtrl, wxWindow& toolti if (txtCtrl) txtCtrl->ChangeValue(toWx(dirpath)); - const Zstring displayPath = getResolvedDirectoryPath(dirpath); //may block when resolving [] + const Zstring folderPathFmt = getResolvedDirectoryPath(dirpath); //may block when resolving [] tooltipWnd.SetToolTip(nullptr); //workaround wxComboBox bug http://trac.wxwidgets.org/ticket/10512 / http://trac.wxwidgets.org/ticket/12659 - tooltipWnd.SetToolTip(toWx(displayPath)); //who knows when the real bugfix reaches mere mortals via an official release... + tooltipWnd.SetToolTip(toWx(folderPathFmt)); //who knows when the real bugfix reaches mere mortals via an official release... if (staticText) //change static box label only if there is a real difference to what is shown in wxTextCtrl anyway - staticText->SetLabel(EqualFilePath()(appendSeparator(trimCpy(dirpath)), appendSeparator(displayPath)) ? wxString(_("Drag && drop")) : toWx(displayPath)); + staticText->SetLabel(EqualFilePath()(appendSeparator(trimCpy(dirpath)), appendSeparator(folderPathFmt)) ? wxString(_("Drag && drop")) : toWx(folderPathFmt)); } } @@ -41,11 +41,11 @@ void setFolderPath(const Zstring& dirpath, wxTextCtrl* txtCtrl, wxWindow& toolti FolderSelector2::FolderSelector2(wxWindow& dropWindow, wxButton& selectButton, - wxTextCtrl& dirpath, + wxTextCtrl& folderPathCtrl, wxStaticText* staticText) : dropWindow_(dropWindow), selectButton_(selectButton), - dirpath_(dirpath), + folderPathCtrl_(folderPathCtrl), staticText_(staticText) { //prepare drag & drop @@ -53,9 +53,9 @@ FolderSelector2::FolderSelector2(wxWindow& dropWindow, dropWindow_.Connect(EVENT_DROP_FILE, FileDropEventHandler(FolderSelector2::onFilesDropped), nullptr, this); //keep dirPicker and dirpath synchronous - dirpath_ .Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector2::onMouseWheel ), nullptr, this); - dirpath_ .Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector2::onWriteDirManually), nullptr, this); - selectButton_.Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector2::onSelectDir ), nullptr, this); + folderPathCtrl_.Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector2::onMouseWheel ), nullptr, this); + folderPathCtrl_.Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector2::onEditFolderPath), nullptr, this); + selectButton_ .Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector2::onSelectDir ), nullptr, this); } @@ -63,9 +63,9 @@ FolderSelector2::~FolderSelector2() { dropWindow_.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(FolderSelector2::onFilesDropped), nullptr, this); - dirpath_ .Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector2::onMouseWheel ), nullptr, this); - dirpath_ .Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector2::onWriteDirManually), nullptr, this); - selectButton_.Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector2::onSelectDir ), nullptr, this); + folderPathCtrl_.Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector2::onMouseWheel ), nullptr, this); + folderPathCtrl_.Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector2::onEditFolderPath), nullptr, this); + selectButton_ .Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector2::onSelectDir ), nullptr, this); } @@ -75,7 +75,7 @@ void FolderSelector2::onMouseWheel(wxMouseEvent& event) //additionally this will delete manual entries, although all the users wanted is scroll the parent window! //redirect to parent scrolled window! - wxWindow* wnd = &dirpath_; + wxWindow* wnd = &folderPathCtrl_; while ((wnd = wnd->GetParent()) != nullptr) //silence MSVC warning if (dynamic_cast(wnd) != nullptr) if (wxEvtHandler* evtHandler = wnd->GetEventHandler()) @@ -89,32 +89,31 @@ void FolderSelector2::onMouseWheel(wxMouseEvent& event) void FolderSelector2::onFilesDropped(FileDropEvent& event) { - const auto& files = event.getFiles(); - if (files.empty()) + const auto& itemPaths = event.getPaths(); + if (itemPaths.empty()) return; - const Zstring filePath = files[0]; - if (dirExists(filePath)) - setFolderPath(filePath, &dirpath_, dirpath_, staticText_); - else + Zstring itemPath = itemPaths[0]; + if (!dirExists(itemPath)) { - Zstring parentName = beforeLast(filePath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); + Zstring parentPath = beforeLast(itemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); #ifdef ZEN_WIN - if (endsWith(parentName, L":")) //volume root - parentName += FILE_NAME_SEPARATOR; + if (endsWith(parentPath, L":")) //volume root + parentPath += FILE_NAME_SEPARATOR; #endif - if (dirExists(parentName)) - setFolderPath(parentName, &dirpath_, dirpath_, staticText_); - else //set original name unconditionally: usecase: inactive mapped network shares - setFolderPath(filePath, &dirpath_, dirpath_, staticText_); + if (dirExists(parentPath)) + itemPath = parentPath; + //else: keep original name unconditionally: usecase: inactive mapped network shares } + setPath(itemPath); + //event.Skip(); } -void FolderSelector2::onWriteDirManually(wxCommandEvent& event) +void FolderSelector2::onEditFolderPath(wxCommandEvent& event) { - setFolderPath(toZ(event.GetString()), nullptr, dirpath_, staticText_); + setFolderPath(toZ(event.GetString()), nullptr, folderPathCtrl_, staticText_); event.Skip(); } @@ -143,7 +142,7 @@ void FolderSelector2::onSelectDir(wxCommandEvent& event) { auto ft = runAsync([folderPath] { return dirExists(folderPath); }); - if (ft.wait_for(boost::chrono::milliseconds(200)) == boost::future_status::ready && ft.get()) //potentially slow network access: wait 200ms at most + if (ft.wait_for(std::chrono::milliseconds(200)) == std::future_status::ready && ft.get()) //potentially slow network access: wait 200ms at most defaultFolderPath = folderPath; } } @@ -168,17 +167,17 @@ void FolderSelector2::onSelectDir(wxCommandEvent& event) const Zstring newFolder = toZ(dirPicker.GetPath()); #endif - setFolderPath(newFolder, &dirpath_, dirpath_, staticText_); + setFolderPath(newFolder, &folderPathCtrl_, folderPathCtrl_, staticText_); } Zstring FolderSelector2::getPath() const { - return toZ(dirpath_.GetValue()); + return toZ(folderPathCtrl_.GetValue()); } void FolderSelector2::setPath(const Zstring& dirpath) { - setFolderPath(dirpath, &dirpath_, dirpath_, staticText_); + setFolderPath(dirpath, &folderPathCtrl_, folderPathCtrl_, staticText_); } diff --git a/FreeFileSync/Source/RealtimeSync/folder_selector2.h b/FreeFileSync/Source/RealtimeSync/folder_selector2.h index 14093117..fb748197 100644 --- a/FreeFileSync/Source/RealtimeSync/folder_selector2.h +++ b/FreeFileSync/Source/RealtimeSync/folder_selector2.h @@ -22,8 +22,8 @@ class FolderSelector2 : public wxEvtHandler public: FolderSelector2(wxWindow& dropWindow, wxButton& selectButton, - wxTextCtrl& dirpath, - wxStaticText* staticText = nullptr); //optional + wxTextCtrl& folderPathCtrl, + wxStaticText* staticText); //optional ~FolderSelector2(); @@ -31,15 +31,15 @@ public: void setPath(const Zstring& dirpath); private: - void onMouseWheel (wxMouseEvent& event); - void onFilesDropped (FileDropEvent& event); - void onWriteDirManually(wxCommandEvent& event); - void onSelectDir (wxCommandEvent& event); + void onMouseWheel (wxMouseEvent& event); + void onFilesDropped (FileDropEvent& event); + void onEditFolderPath(wxCommandEvent& event); + void onSelectDir (wxCommandEvent& event); wxWindow& dropWindow_; wxButton& selectButton_; - wxTextCtrl& dirpath_; - wxStaticText* staticText_; //optional + wxTextCtrl& folderPathCtrl_; + wxStaticText* staticText_ = nullptr; //optional }; } diff --git a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp index 1472a301..e51e6f73 100644 --- a/FreeFileSync/Source/RealtimeSync/main_dlg.cpp +++ b/FreeFileSync/Source/RealtimeSync/main_dlg.cpp @@ -39,7 +39,7 @@ class DirectoryPanel : public FolderGenerated public: DirectoryPanel(wxWindow* parent) : FolderGenerated(parent), - dirpath_(*this, *m_buttonSelectDir, *m_txtCtrlDirectory) + folderSelector_(*this, *m_buttonSelectDir, *m_txtCtrlDirectory, nullptr /*staticText*/) { #ifdef ZEN_LINUX //file drag and drop directly into the text control unhelpfully inserts in format "file://.."; see folder_history_box.cpp @@ -48,11 +48,11 @@ public: #endif } - void setPath(const Zstring& dirpath) { dirpath_.setPath(dirpath); } - Zstring getPath() const { return dirpath_.getPath(); } + void setPath(const Zstring& dirpath) { folderSelector_.setPath(dirpath); } + Zstring getPath() const { return folderSelector_.getPath(); } private: - zen::FolderSelector2 dirpath_; + zen::FolderSelector2 folderSelector_; }; @@ -339,9 +339,9 @@ void MainDialog::OnConfigLoad(wxCommandEvent& event) void MainDialog::onFilesDropped(FileDropEvent& event) { - const auto& files = event.getFiles(); - if (!files.empty()) - loadConfig(utfCvrtTo(files[0])); + const auto& filePaths = event.getPaths(); + if (!filePaths.empty()) + loadConfig(utfCvrtTo(filePaths[0])); } diff --git a/FreeFileSync/Source/RealtimeSync/monitor.cpp b/FreeFileSync/Source/RealtimeSync/monitor.cpp index 42e74eef..b196f7bd 100644 --- a/FreeFileSync/Source/RealtimeSync/monitor.cpp +++ b/FreeFileSync/Source/RealtimeSync/monitor.cpp @@ -25,14 +25,14 @@ namespace const int CHECK_DIR_INTERVAL = 1; //unit: [s] -std::vector getFormattedDirs(const std::vector& dirpathPhrases) //throw FileError +std::vector getFormattedDirs(const std::vector& folderPathPhrases) //throw FileError { - std::set dirpaths; //make unique - for (const Zstring& phrase : std::set(dirpathPhrases.begin(), dirpathPhrases.end())) + std::set folderPaths; //make unique + for (const Zstring& phrase : std::set(folderPathPhrases.begin(), folderPathPhrases.end())) //make unique: no need to resolve duplicate phrases more than once! (consider "[volume name]" syntax) -> shouldn't this be already buffered by OS? - dirpaths.insert(getResolvedDirectoryPath(phrase)); + folderPaths.insert(getResolvedDirectoryPath(phrase)); - return std::vector(dirpaths.begin(), dirpaths.end()); + return std::vector(folderPaths.begin(), folderPaths.end()); } @@ -46,42 +46,42 @@ struct WaitResult }; WaitResult(const zen::DirWatcher::Entry& changedItem) : type(CHANGE_DETECTED), changedItem_(changedItem) {} - WaitResult(const Zstring& dirpath) : type(CHANGE_DIR_MISSING), dirpath_(dirpath) {} + WaitResult(const Zstring& folderPath) : type(CHANGE_DIR_MISSING), folderPath_(folderPath) {} ChangeType type; zen::DirWatcher::Entry changedItem_; //for type == CHANGE_DETECTED: file or directory - Zstring dirpath_; //for type == CHANGE_DIR_MISSING + Zstring folderPath_; //for type == CHANGE_DIR_MISSING }; -WaitResult waitForChanges(const std::vector& dirpathPhrases, //throw FileError +WaitResult waitForChanges(const std::vector& folderPathPhrases, //throw FileError const std::function& onRefreshGui) { - const std::vector dirpathsFmt = getFormattedDirs(dirpathPhrases); //throw FileError - if (dirpathsFmt.empty()) //pathological case, but we have to check else this function will wait endlessly + const std::vector folderPathsFmt = getFormattedDirs(folderPathPhrases); //throw FileError + if (folderPathsFmt.empty()) //pathological case, but we have to check else this function will wait endlessly throw zen::FileError(_("A folder input field is empty.")); //should have been checked by caller! //detect when volumes are removed/are not available anymore std::vector>> watches; - for (const Zstring& dirpathFmt : dirpathsFmt) + for (const Zstring& folderPathFmt : folderPathsFmt) { try { //a non-existent network path may block, so check existence asynchronously! - auto ftDirExists = runAsync([=] { return zen::dirExists(dirpathFmt); }); + auto ftDirExists = runAsync([=] { return zen::dirExists(folderPathFmt); }); //we need to check dirExists(), not somethingExists(): it's not clear if DirWatcher detects a type clash (file instead of directory!) - while (ftDirExists.wait_for(boost::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)) != boost::future_status::ready) + while (ftDirExists.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)) != std::future_status::ready) onRefreshGui(false); //may throw! if (!ftDirExists.get()) - return WaitResult(dirpathFmt); + return WaitResult(folderPathFmt); - watches.emplace_back(dirpathFmt, std::make_shared(dirpathFmt)); //throw FileError + watches.emplace_back(folderPathFmt, std::make_shared(folderPathFmt)); //throw FileError } catch (FileError&) { - if (!somethingExists(dirpathFmt)) //a benign(?) race condition with FileError - return WaitResult(dirpathFmt); + if (!somethingExists(folderPathFmt)) //a benign(?) race condition with FileError + return WaitResult(folderPathFmt); throw; } } @@ -104,13 +104,13 @@ WaitResult waitForChanges(const std::vector& dirpathPhrases, //throw Fi for (auto it = watches.begin(); it != watches.end(); ++it) { - const Zstring& dirpath = it->first; + const Zstring& folderPath = it->first; DirWatcher& watcher = *(it->second); //IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories! if (checkDirExistNow) - if (!dirExists(dirpath)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED -> somethingExists() is NOT sufficient here! - return WaitResult(dirpath); + if (!dirExists(folderPath)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED -> somethingExists() is NOT sufficient here! + return WaitResult(folderPath); try { std::vector changedItems = watcher.getChanges([&] { onRefreshGui(false); /*may throw!*/ }); //throw FileError @@ -133,39 +133,39 @@ WaitResult waitForChanges(const std::vector& dirpathPhrases, //throw Fi } catch (FileError&) { - if (!somethingExists(dirpath)) //a benign(?) race condition with FileError - return WaitResult(dirpath); + if (!somethingExists(folderPath)) //a benign(?) race condition with FileError + return WaitResult(folderPath); throw; } } - boost::this_thread::sleep_for(boost::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)); onRefreshGui(true); //throw ?: may start sync at this presumably idle time } } //wait until all directories become available (again) + logs in network share -void waitForMissingDirs(const std::vector& dirpathPhrases, //throw FileError - const std::function& onRefreshGui) +void waitForMissingDirs(const std::vector& folderPathPhrases, //throw FileError + const std::function& onRefreshGui) { for (;;) { bool allExisting = true; //support specifying volume by name => call getResolvedDirectoryPath() repeatedly - for (const Zstring& dirpathFmt : getFormattedDirs(dirpathPhrases)) //throw FileError + for (const Zstring& folderPathFmt : getFormattedDirs(folderPathPhrases)) //throw FileError { auto ftDirExisting = runAsync([=]() -> bool { #ifdef ZEN_WIN //1. login to network share, if necessary -> we probably do NOT want multiple concurrent runs: GUI!? - loginNetworkShare(dirpathFmt, false); //login networks shares, no PW prompt -> is this really RTS's job? + loginNetworkShare(folderPathFmt, false); //login networks shares, no PW prompt -> is this really RTS's job? #endif //2. check dir existence - return zen::dirExists(dirpathFmt); + return zen::dirExists(folderPathFmt); }); - while (ftDirExisting.wait_for(boost::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)) != boost::future_status::ready) - onRefreshGui(dirpathFmt); //may throw! + while (ftDirExisting.wait_for(std::chrono::milliseconds(rts::UI_UPDATE_INTERVAL / 2)) != std::future_status::ready) + onRefreshGui(folderPathFmt); //may throw! if (!ftDirExisting.get()) { @@ -175,8 +175,8 @@ void waitForMissingDirs(const std::vector& dirpathPhrases, //throw File static_assert(CHECK_DIR_INTERVAL * 1000 % refreshInterval == 0, ""); for (int i = 0; i < CHECK_DIR_INTERVAL * 1000 / refreshInterval; ++i) { - onRefreshGui(dirpathFmt); //may throw! - boost::this_thread::sleep_for(boost::chrono::milliseconds(refreshInterval)); //throw boost::thread_interrupted + onRefreshGui(folderPathFmt); //may throw! + std::this_thread::sleep_for(std::chrono::milliseconds(refreshInterval)); } break; } @@ -206,9 +206,9 @@ struct ExecCommandNowException {}; } -void rts::monitorDirectories(const std::vector& dirpathPhrases, unsigned int delay, rts::MonitorCallback& callback) +void rts::monitorDirectories(const std::vector& folderPathPhrases, unsigned int delay, rts::MonitorCallback& callback) { - if (dirpathPhrases.empty()) + if (folderPathPhrases.empty()) { assert(false); return; @@ -217,7 +217,7 @@ void rts::monitorDirectories(const std::vector& dirpathPhrases, unsigne auto execMonitoring = [&] //throw FileError { callback.setPhase(MonitorCallback::MONITOR_PHASE_WAITING); - waitForMissingDirs(dirpathPhrases, [&](const Zstring& dirpath) { callback.requestUiRefresh(); }); //throw FileError + waitForMissingDirs(folderPathPhrases, [&](const Zstring& folderPath) { callback.requestUiRefresh(); }); //throw FileError callback.setPhase(MonitorCallback::MONITOR_PHASE_ACTIVE); //schedule initial execution (*after* all directories have arrived, which could take some time which we don't want to include) @@ -231,7 +231,7 @@ void rts::monitorDirectories(const std::vector& dirpathPhrases, unsigne while (true) //loop over detected changes { //wait for changes (and for all directories to become available) - WaitResult res = waitForChanges(dirpathPhrases, [&](bool readyForSync) //throw FileError, ExecCommandNowException + WaitResult res = waitForChanges(folderPathPhrases, [&](bool readyForSync) //throw FileError, ExecCommandNowException { if (readyForSync) if (nextExecDate <= std::time(nullptr)) @@ -242,7 +242,7 @@ void rts::monitorDirectories(const std::vector& dirpathPhrases, unsigne { case WaitResult::CHANGE_DIR_MISSING: //don't execute the command before all directories are available! callback.setPhase(MonitorCallback::MONITOR_PHASE_WAITING); - waitForMissingDirs(dirpathPhrases, [&](const Zstring& dirpath) { callback.requestUiRefresh(); }); //throw FileError + waitForMissingDirs(folderPathPhrases, [&](const Zstring& folderPath) { callback.requestUiRefresh(); }); //throw FileError callback.setPhase(MonitorCallback::MONITOR_PHASE_ACTIVE); break; diff --git a/FreeFileSync/Source/RealtimeSync/monitor.h b/FreeFileSync/Source/RealtimeSync/monitor.h index 87915b41..a5aee773 100644 --- a/FreeFileSync/Source/RealtimeSync/monitor.h +++ b/FreeFileSync/Source/RealtimeSync/monitor.h @@ -29,7 +29,7 @@ struct MonitorCallback virtual void requestUiRefresh () = 0; virtual void reportError(const std::wstring& msg) = 0; //automatically retries after return! }; -void monitorDirectories(const std::vector& dirpathPhrases, +void monitorDirectories(const std::vector& folderPathPhrases, //non-formatted dirnames that yet require call to getFormattedDirectoryName(); empty directories must be checked by caller! unsigned int delay, MonitorCallback& callback); diff --git a/FreeFileSync/Source/RealtimeSync/tray_menu.cpp b/FreeFileSync/Source/RealtimeSync/tray_menu.cpp index 6eb71946..7357e7fc 100644 --- a/FreeFileSync/Source/RealtimeSync/tray_menu.cpp +++ b/FreeFileSync/Source/RealtimeSync/tray_menu.cpp @@ -319,7 +319,7 @@ rts::AbortReason rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& conf case ConfirmationButton::CANCEL: throw AbortMonitoring(SHOW_GUI); } - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } } diff --git a/FreeFileSync/Source/RealtimeSync/xml_proc.cpp b/FreeFileSync/Source/RealtimeSync/xml_proc.cpp index fdd3b507..68bcf5ba 100644 --- a/FreeFileSync/Source/RealtimeSync/xml_proc.cpp +++ b/FreeFileSync/Source/RealtimeSync/xml_proc.cpp @@ -84,26 +84,26 @@ void xmlAccess::writeConfig(const XmlRealConfig& config, const Zstring& filepath namespace { -xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& batchCfg, const Zstring& filepath) +xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& batchCfg, const Zstring& batchFilePath) { std::set uniqueFolders; //add main folders - uniqueFolders.insert(batchCfg.mainCfg.firstPair.dirpathPhraseLeft); - uniqueFolders.insert(batchCfg.mainCfg.firstPair.dirpathPhraseRight); + uniqueFolders.insert(batchCfg.mainCfg.firstPair.folderPathPhraseLeft_); + uniqueFolders.insert(batchCfg.mainCfg.firstPair.folderPathPhraseRight_); //additional folders for (const FolderPairEnh& fp : batchCfg.mainCfg.additionalPairs) { - uniqueFolders.insert(fp.dirpathPhraseLeft); - uniqueFolders.insert(fp.dirpathPhraseRight); + uniqueFolders.insert(fp.folderPathPhraseLeft_); + uniqueFolders.insert(fp.folderPathPhraseRight_); } uniqueFolders.erase(Zstring()); xmlAccess::XmlRealConfig output; output.directories.assign(uniqueFolders.begin(), uniqueFolders.end()); - output.commandline = Zstr("\"") + zen::getFreeFileSyncLauncher() + Zstr("\" \"") + filepath + Zstr("\""); + output.commandline = Zstr("\"") + zen::getFreeFileSyncLauncher() + Zstr("\" \"") + batchFilePath + Zstr("\""); return output; } } diff --git a/FreeFileSync/Source/algorithm.cpp b/FreeFileSync/Source/algorithm.cpp index e49fd0a0..952fd0af 100644 --- a/FreeFileSync/Source/algorithm.cpp +++ b/FreeFileSync/Source/algorithm.cpp @@ -10,6 +10,8 @@ #include "lib/norm_filter.h" #include "lib/db_file.h" #include "lib/cmp_filetime.h" +#include "lib/status_handler_impl.h" +#include "fs/concrete.h" using namespace zen; //using namespace std::rel_ops; @@ -1081,10 +1083,10 @@ void zen::applyTimeSpanFilter(FolderComparison& folderCmp, std::int64_t timeFrom //############################################################################################################ -std::pair zen::deleteFromGridAndHDPreview(const std::vector& selectionLeft, - const std::vector& selectionRight) +std::pair zen::getSelectedItemsAsString(const std::vector& selectionLeft, + const std::vector& selectionRight) { - //don't use wxString! its imprudent linear allocation strategy brings perf down to a crawl! + //don't use wxString! its rather dumb linear allocation strategy brings perf down to a crawl! std::wstring fileList; // int totalDelCount = 0; @@ -1108,170 +1110,316 @@ std::pair zen::deleteFromGridAndHDPreview(const std::vector inline -bool tryReportingError(Function cmd, DeleteFilesHandler& handler) //throw X?; return "true" on success, "false" if error was ignored +struct FSObjectLambdaVisitor : public FSObjectVisitor { - for (;;) + static void visit(FileSystemObject& fsObj, + const std::function& onDir, + const std::function& onFile, + const std::function& onSymlink) + { + FSObjectLambdaVisitor visitor(onDir, onFile, onSymlink); + fsObj.accept(visitor); + } + +private: + FSObjectLambdaVisitor(const std::function& onDir, + const std::function& onFile, + const std::function& onSymlink) : onDir_(onDir), onFile_(onFile), onSymlink_(onSymlink) {} + + void visit(const DirPair& dirObj ) override { if (onDir_) onDir_ (dirObj ); } + void visit(const FilePair& fileObj) override { if (onFile_) onFile_ (fileObj); } + void visit(const SymlinkPair& linkObj) override { if (onSymlink_) onSymlink_(linkObj); } + + const std::function onDir_; + const std::function onFile_; + const std::function onSymlink_; +}; + + +template +void copyToAlternateFolderFrom(const std::vector& rowsToCopy, + ABF& abfTarget, + bool keepRelPaths, + bool overwriteIfExists, + ProcessCallback& callback) +{ + auto notifyItemCopy = [&](const std::wstring& statusText, const std::wstring& displayPath) + { + callback.reportInfo(replaceCpy(statusText, L"%x", fmtPath(displayPath))); + }; + + const std::wstring txtCreatingFolder(_("Creating folder %x" )); + const std::wstring txtCreatingFile (_("Creating file %x" )); + const std::wstring txtCreatingLink (_("Creating symbolic link %x")); + + auto copyItem = [&](FileSystemObject& fsObj, const Zstring& relPath) //throw FileError + { + const AbstractPathRef targetPath = abfTarget.getAbstractPath(relPath); + + const std::function deleteTargetItem = [&] + { + if (overwriteIfExists) + try + { + //file or (broken) file-symlink: + ABF::removeFile(targetPath); //throw FileError + } + catch (FileError&) + { + //folder or folder-symlink: + if (ABF::folderExists(targetPath)) //directory or dir-symlink + ABF::removeFolderRecursively(targetPath, nullptr /*onBeforeFileDeletion*/, nullptr /*onBeforeFolderDeletion*/); //throw FileError + else + throw; + } + }; + + FSObjectLambdaVisitor::visit(fsObj, + [&](const DirPair& dirObj) + { + StatisticsReporter statReporter(1, 0, callback); + notifyItemCopy(txtCreatingFolder, ABF::getDisplayPath(targetPath)); + + try + { + //deleteTargetItem(); -> never delete pre-existing folders!!! => might delete child items we just copied! + ABF::copyNewFolder(dirObj.getAbstractPath(), targetPath, false /*copyFilePermissions*/); //throw FileError + } + catch (const FileError&) { if (!ABF::folderExists(targetPath)) throw; } //might already exist: see creation of intermediate directories below + statReporter.reportDelta(1, 0); + + statReporter.reportFinished(); + }, + + [&](const FilePair& fileObj) + { + StatisticsReporter statReporter(1, fileObj.getFileSize(), callback); + notifyItemCopy(txtCreatingFile, ABF::getDisplayPath(targetPath)); + + auto onNotifyCopyStatus = [&](std::int64_t bytesDelta) { statReporter.reportDelta(0, bytesDelta); }; + ABF::copyFileTransactional(fileObj.getAbstractPath(), targetPath, //throw FileError, ErrorFileLocked + false /*copyFilePermissions*/, true /*transactionalCopy*/, deleteTargetItem, onNotifyCopyStatus); + statReporter.reportDelta(1, 0); + + statReporter.reportFinished(); + }, + + [&](const SymlinkPair& linkObj) + { + StatisticsReporter statReporter(1, 0, callback); + notifyItemCopy(txtCreatingLink, ABF::getDisplayPath(targetPath)); + + deleteTargetItem(); + ABF::copySymlink(linkObj.getAbstractPath(), targetPath, false /*copyFilePermissions*/); //throw FileError + statReporter.reportDelta(1, 0); + + statReporter.reportFinished(); + }); + }; + + for (FileSystemObject* fsObj : rowsToCopy) + tryReportingError([&] + { + const Zstring& relPath = keepRelPaths ? fsObj->getRelativePath() : fsObj->getItemName(); try { - cmd(); //throw FileError - return true; + copyItem(*fsObj, relPath); //throw FileError } - catch (FileError& error) + catch (FileError&) { - switch (handler.reportError(error.toString())) //throw X? + //create intermediate directories if missing + const AbstractPathRef targetParentPath = abfTarget.getAbstractPath(beforeLast(relPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)); + if (!ABF::somethingExists(targetParentPath)) //->(minor) file system race condition! { - case DeleteFilesHandler::IGNORE_ERROR: - return false; - case DeleteFilesHandler::RETRY: - break; //continue with loop - default: - assert(false); - break; + ABF::createFolderRecursively(targetParentPath); //throw FileError + //retry: this should work now! + copyItem(*fsObj, relPath); //throw FileError } + else + throw; } + }, callback); //throw X? +} } -template -void categorize(const std::set& rowsIn, - std::vector& deletePermanent, - std::vector& deleteRecyler, - bool useRecycleBin, - std::map& recyclerSupported, - DeleteFilesHandler& callback) +void zen::copyToAlternateFolder(const std::vector& rowsToCopyOnLeft, + const std::vector& rowsToCopyOnRight, + const Zstring& targetFolderPathPhrase, + bool keepRelPaths, + bool overwriteIfExists, + ProcessCallback& callback) { - auto hasRecycler = [&](const ABF& baseFolder) -> bool - { - auto it = recyclerSupported.find(&baseFolder); //perf: avoid duplicate checks! - if (it != recyclerSupported.end()) - return it->second; + std::vector itemSelectionLeft = rowsToCopyOnLeft; + std::vector itemSelectionRight = rowsToCopyOnRight; + vector_remove_if(itemSelectionLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + vector_remove_if(itemSelectionRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); - const std::wstring msg = replaceCpy(_("Checking recycle bin availability for folder %x..."), L"%x", - fmtPath(ABF::getDisplayPath(baseFolder.getAbstractPath()))); - bool recSupported = false; - tryReportingError([&]{ - recSupported = baseFolder.supportsRecycleBin([&] { callback.reportStatus(msg); /*may throw*/ }); //throw FileError - }, callback); //throw X? + const int itemCount = static_cast(itemSelectionLeft.size() + itemSelectionRight.size()); + std::int64_t dataToProcess = 0; - recyclerSupported.emplace(&baseFolder, recSupported); - return recSupported; - }; + for (FileSystemObject* fsObj : itemSelectionLeft) + FSObjectLambdaVisitor::visit(*fsObj, nullptr /*onDir*/, + [&](const FilePair& fileObj) {dataToProcess += static_cast(fileObj.getFileSize()); }, nullptr /*onSymlink*/); - for (FileSystemObject* row : rowsIn) - if (!row->isEmpty()) - { - if (useRecycleBin && hasRecycler(row->root().getABF())) //Windows' ::SHFileOperation() will delete permanently anyway, but we have a superior deletion routine - deleteRecyler.push_back(row); - else - deletePermanent.push_back(row); - } + for (FileSystemObject* fsObj : itemSelectionRight) + FSObjectLambdaVisitor::visit(*fsObj, nullptr /*onDir*/, + [&](const FilePair& fileObj) {dataToProcess += static_cast(fileObj.getFileSize()); }, nullptr /*onSymlink*/); + + callback.initNewPhase(itemCount, dataToProcess, ProcessCallback::PHASE_SYNCHRONIZING); //throw X + + std::unique_ptr abfTarget = createAbstractBaseFolder(targetFolderPathPhrase); + + copyToAlternateFolderFrom(itemSelectionLeft, *abfTarget, keepRelPaths, overwriteIfExists, callback); + copyToAlternateFolderFrom(itemSelectionRight, *abfTarget, keepRelPaths, overwriteIfExists, callback); } +//############################################################################################################ +namespace +{ template -struct ItemDeleter : public FSObjectVisitor //throw FileError, but nothrow constructor!!! +void deleteFromGridAndHDOneSide(std::vector& rowsToDelete, + bool useRecycleBin, + ProcessCallback& callback) { - ItemDeleter(bool useRecycleBin, DeleteFilesHandler& handler) : - handler_(handler), useRecycleBin_(useRecycleBin) + auto notifyItemDeletion = [&](const std::wstring& statusText, const std::wstring& displayPath) { - if (useRecycleBin_) - { - txtRemovingFile = _("Moving file %x to the recycle bin" ); - txtRemovingDirectory = _("Moving folder %x to the recycle bin" ); - txtRemovingSymlink = _("Moving symbolic link %x to the recycle bin"); - } - else - { - txtRemovingFile = _("Deleting file %x" ); - txtRemovingDirectory = _("Deleting folder %x" ); - txtRemovingSymlink = _("Deleting symbolic link %x"); - } - } + callback.reportInfo(replaceCpy(statusText, L"%x", fmtPath(displayPath))); + }; - void visit(const FilePair& fileObj) override - { - notifyFileDeletion(ABF::getDisplayPath(fileObj.getAbstractPath())); + std::wstring txtRemovingFile; + std::wstring txtRemovingDirectory; + std::wstring txtRemovingSymlink; - if (useRecycleBin_) - ABF::recycleItemDirectly(fileObj.getAbstractPath()); //throw FileError - else - ABF::removeFile(fileObj.getAbstractPath()); //throw FileError + if (useRecycleBin) + { + txtRemovingFile = _("Moving file %x to the recycle bin"); + txtRemovingDirectory = _("Moving folder %x to the recycle bin"); + txtRemovingSymlink = _("Moving symbolic link %x to the recycle bin"); } - - void visit(const SymlinkPair& linkObj) override + else { - notifySymlinkDeletion(ABF::getDisplayPath(linkObj.getAbstractPath())); - - if (useRecycleBin_) - ABF::recycleItemDirectly(linkObj.getAbstractPath()); //throw FileError - else - { - if (ABF::dirExists(linkObj.getAbstractPath())) //dir symlink - ABF::removeFolderSimple(linkObj.getAbstractPath()); //throw FileError - else //file symlink, broken symlink - ABF::removeFile(linkObj.getAbstractPath()); //throw FileError - } + txtRemovingFile = _("Deleting file %x"); + txtRemovingDirectory = _("Deleting folder %x"); + txtRemovingSymlink = _("Deleting symbolic link %x"); } - void visit(const DirPair& dirObj) override + + for (FileSystemObject* fsObj : rowsToDelete) //all pointers are required(!) to be bound + tryReportingError([&] { - notifyDirectoryDeletion(ABF::getDisplayPath(dirObj.getAbstractPath())); //notfied twice; see below -> no big deal + StatisticsReporter statReporter(1, 0, callback); - if (useRecycleBin_) - ABF::recycleItemDirectly(dirObj.getAbstractPath()); //throw FileError - else + if (!fsObj->isEmpty()) //element may be implicitly deleted, e.g. if parent folder was deleted first { - auto onBeforeFileDeletion = [&](const std::wstring& displayPath) { this->notifyFileDeletion (displayPath); }; //without "this->" GCC 4.7.2 runtime crash on Debian - auto onBeforeDirDeletion = [&](const std::wstring& displayPath) { this->notifyDirectoryDeletion(displayPath); }; + FSObjectLambdaVisitor::visit(*fsObj, + [&](const DirPair& dirObj) + { + if (useRecycleBin) + { + notifyItemDeletion(txtRemovingDirectory, ABF::getDisplayPath(dirObj.getAbstractPath())); + ABF::recycleItemDirectly(dirObj.getAbstractPath()); //throw FileError + statReporter.reportDelta(1, 0); + } + else + { + auto onBeforeFileDeletion = [&](const std::wstring& displayPath) + { + statReporter.reportDelta(1, 0); + notifyItemDeletion(txtRemovingFile, displayPath); + }; + auto onBeforeDirDeletion = [&](const std::wstring& displayPath) + { + statReporter.reportDelta(1, 0); + notifyItemDeletion(txtRemovingDirectory, displayPath); + }; - ABF::removeFolderRecursively(dirObj.getAbstractPath(), onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError - } - } + ABF::removeFolderRecursively(dirObj.getAbstractPath(), onBeforeFileDeletion, onBeforeDirDeletion); //throw FileError + } + }, -private: - void notifyFileDeletion (const std::wstring& displayPath) { notifyItemDeletion(txtRemovingFile , displayPath); } - void notifyDirectoryDeletion(const std::wstring& displayPath) { notifyItemDeletion(txtRemovingDirectory, displayPath); } - void notifySymlinkDeletion (const std::wstring& displayPath) { notifyItemDeletion(txtRemovingSymlink , displayPath); } + [&](const FilePair& fileObj) + { + notifyItemDeletion(txtRemovingFile, ABF::getDisplayPath(fileObj.getAbstractPath())); - void notifyItemDeletion(const std::wstring& statusText, const std::wstring& displayPath) - { - handler_.reportStatus(replaceCpy(statusText, L"%x", fmtPath(displayPath))); - } + if (useRecycleBin) + ABF::recycleItemDirectly(fileObj.getAbstractPath()); //throw FileError + else + ABF::removeFile(fileObj.getAbstractPath()); //throw FileError + statReporter.reportDelta(1, 0); + }, - DeleteFilesHandler& handler_; - const bool useRecycleBin_; + [&](const SymlinkPair& linkObj) + { + notifyItemDeletion(txtRemovingSymlink, ABF::getDisplayPath(linkObj.getAbstractPath())); - std::wstring txtRemovingFile; - std::wstring txtRemovingDirectory; - std::wstring txtRemovingSymlink; -}; + if (useRecycleBin) + ABF::recycleItemDirectly(linkObj.getAbstractPath()); //throw FileError + else + { + if (ABF::folderExists(linkObj.getAbstractPath())) //dir symlink + ABF::removeFolderSimple(linkObj.getAbstractPath()); //throw FileError + else //file symlink, broken symlink + ABF::removeFile(linkObj.getAbstractPath()); //throw FileError + } + statReporter.reportDelta(1, 0); + }); + + fsObj->removeObject(); //if directory: removes recursively! + } + + statReporter.reportFinished(); + + }, callback); //throw X? +} template -void deleteFromGridAndHDOneSide(std::vector& ptrList, - bool useRecycleBin, - DeleteFilesHandler& handler) +void categorize(const std::vector& rows, + std::vector& deletePermanent, + std::vector& deleteRecyler, + bool useRecycleBin, + std::map& recyclerSupported, + ProcessCallback& callback) { - ItemDeleter deleter(useRecycleBin, handler); + auto hasRecycler = [&](const ABF& baseFolder) -> bool + { + auto it = recyclerSupported.find(&baseFolder); //perf: avoid duplicate checks! + if (it != recyclerSupported.end()) + return it->second; - for (FileSystemObject* fsObj : ptrList) //all pointers are required(!) to be bound - if (!fsObj->isEmpty()) //element may be implicitly deleted, e.g. if parent folder was deleted first - tryReportingError([&] + const std::wstring msg = replaceCpy(_("Checking recycle bin availability for folder %x..."), L"%x", + fmtPath(ABF::getDisplayPath(baseFolder.getAbstractPath()))); + + bool recSupported = false; + tryReportingError([&]{ + recSupported = baseFolder.supportsRecycleBin([&] { callback.reportStatus(msg); /*may throw*/ }); //throw FileError + }, callback); //throw X? + + recyclerSupported.emplace(&baseFolder, recSupported); + return recSupported; + }; + + for (FileSystemObject* row : rows) + if (!row->isEmpty()) { - fsObj->accept(deleter); //throw FileError - fsObj->removeObject(); //if directory: removes recursively! - }, handler); //throw X? + if (useRecycleBin && hasRecycler(row->root().getABF())) //Windows' ::SHFileOperation() will delete permanently anyway, but we have a superior deletion routine + deleteRecyler.push_back(row); + else + deletePermanent.push_back(row); + } } } + void zen::deleteFromGridAndHD(const std::vector& rowsToDeleteOnLeft, //refresh GUI grid after deletion to remove invalid rows const std::vector& rowsToDeleteOnRight, //all pointers need to be bound! FolderComparison& folderCmp, //attention: rows will be physically deleted! const std::vector& directCfgs, bool useRecycleBin, - DeleteFilesHandler& statusHandler, - bool& warningRecyclerMissing) + bool& warningRecyclerMissing, + ProcessCallback& callback) { if (folderCmp.empty()) return; @@ -1283,26 +1431,32 @@ void zen::deleteFromGridAndHD(const std::vector& rowsToDelete for (auto it = folderCmp.begin(); it != folderCmp.end(); ++it) baseDirCfgs[&** it] = directCfgs[it - folderCmp.begin()]; - std::set deleteLeft (rowsToDeleteOnLeft .begin(), rowsToDeleteOnLeft .end()); - std::set deleteRight(rowsToDeleteOnRight.begin(), rowsToDeleteOnRight.end()); + std::vector deleteLeft = rowsToDeleteOnLeft; + std::vector deleteRight = rowsToDeleteOnRight; - set_remove_if(deleteLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); //still needed? - set_remove_if(deleteRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); // + vector_remove_if(deleteLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); //needed? + vector_remove_if(deleteRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); //yes, for correct stats: + + const int itemCount = static_cast(deleteLeft.size() + deleteRight.size()); + callback.initNewPhase(itemCount, 0, ProcessCallback::PHASE_SYNCHRONIZING); //throw X //ensure cleanup: redetermination of sync-directions and removal of invalid rows - auto updateDirection = [&]() + auto updateDirection = [&] { //update sync direction: we cannot do a full redetermination since the user may already have entered manual changes - std::set deletedTotal = deleteLeft; - deletedTotal.insert(deleteRight.begin(), deleteRight.end()); + std::vector rowsToDelete; + vector_append(rowsToDelete, deleteLeft); + vector_append(rowsToDelete, deleteRight); + removeDuplicates(rowsToDelete); - for (auto it = deletedTotal.begin(); it != deletedTotal.end(); ++it) + for (auto it = rowsToDelete.begin(); it != rowsToDelete.end(); ++it) { FileSystemObject& fsObj = **it; //all pointers are required(!) to be bound if (fsObj.isEmpty() != fsObj.isEmpty()) //make sure objects exists on one side only { auto cfgIter = baseDirCfgs.find(&fsObj.root()); + assert(cfgIter != baseDirCfgs.end()); if (cfgIter != baseDirCfgs.end()) { SyncDirection newDir = SyncDirection::NONE; @@ -1317,8 +1471,6 @@ void zen::deleteFromGridAndHD(const std::vector& rowsToDelete setSyncDirectionRec(newDir, fsObj); //set new direction (recursively) } - else - assert(!"this should not happen!"); } } @@ -1334,8 +1486,8 @@ void zen::deleteFromGridAndHD(const std::vector& rowsToDelete std::vector deleteRecylerRight; std::map recyclerSupported; - categorize(deleteLeft, deletePermanentLeft, deleteRecylerLeft, useRecycleBin, recyclerSupported, statusHandler); - categorize(deleteRight, deletePermanentRight, deleteRecylerRight, useRecycleBin, recyclerSupported, statusHandler); + categorize(deleteLeft, deletePermanentLeft, deleteRecylerLeft, useRecycleBin, recyclerSupported, callback); + categorize(deleteRight, deletePermanentRight, deleteRecylerRight, useRecycleBin, recyclerSupported, callback); //windows: check if recycle bin really exists; if not, Windows will silently delete, which is wrong if (useRecycleBin && @@ -1347,12 +1499,12 @@ void zen::deleteFromGridAndHD(const std::vector& rowsToDelete if (!item.second) msg += L"\n" + ABF::getDisplayPath(item.first->getAbstractPath()); - statusHandler.reportWarning(msg, warningRecyclerMissing); //throw? + callback.reportWarning(msg, warningRecyclerMissing); //throw? } - deleteFromGridAndHDOneSide(deleteRecylerLeft, true, statusHandler); - deleteFromGridAndHDOneSide(deletePermanentLeft, false, statusHandler); + deleteFromGridAndHDOneSide(deleteRecylerLeft, true, callback); + deleteFromGridAndHDOneSide(deletePermanentLeft, false, callback); - deleteFromGridAndHDOneSide(deleteRecylerRight, true, statusHandler); - deleteFromGridAndHDOneSide(deletePermanentRight, false, statusHandler); + deleteFromGridAndHDOneSide(deleteRecylerRight, true, callback); + deleteFromGridAndHDOneSide(deletePermanentRight, false, callback); } diff --git a/FreeFileSync/Source/algorithm.h b/FreeFileSync/Source/algorithm.h index aab41ae1..3f1235f3 100644 --- a/FreeFileSync/Source/algorithm.h +++ b/FreeFileSync/Source/algorithm.h @@ -10,6 +10,7 @@ #include #include "file_hierarchy.h" #include "lib/soft_filter.h" +#include "process_callback.h" namespace zen { @@ -41,33 +42,27 @@ void applyTimeSpanFilter(FolderComparison& folderCmp, std::int64_t timeFrom, std void setActiveStatus(bool newStatus, FolderComparison& folderCmp); //activate or deactivate all rows void setActiveStatus(bool newStatus, FileSystemObject& fsObj); //activate or deactivate row: (not recursively anymore) - -//manual deletion of files on main grid -std::pair deleteFromGridAndHDPreview( //returns string with elements to be deleted and total count of selected(!) objects, NOT total files/dirs! +std::pair getSelectedItemsAsString( //returns string with item names and total count of selected(!) items, NOT total files/dirs! const std::vector& selectionLeft, //all pointers need to be bound! const std::vector& selectionRight); // -struct DeleteFilesHandler -{ - virtual ~DeleteFilesHandler() {} +//manual copy to alternate folder: +void copyToAlternateFolder(const std::vector& rowsToCopyOnLeft, //all pointers need to be bound! + const std::vector& rowsToCopyOnRight, // + const Zstring& targetFolderPathPhrase, + bool keepRelPaths, + bool overwriteIfExists, + ProcessCallback& callback); - enum Response - { - IGNORE_ERROR = 10, - RETRY - }; - virtual Response reportError (const std::wstring& msg) = 0; - virtual void reportWarning(const std::wstring& msg, bool& warningActive) = 0; - virtual void reportStatus (const std::wstring& msg) = 0; -}; +//manual deletion of files on main grid void deleteFromGridAndHD(const std::vector& rowsToDeleteOnLeft, //refresh GUI grid after deletion to remove invalid rows const std::vector& rowsToDeleteOnRight, //all pointers need to be bound! FolderComparison& folderCmp, //attention: rows will be physically deleted! const std::vector& directCfgs, bool useRecycleBin, - DeleteFilesHandler& statusHandler, //global warnings: - bool& warningRecyclerMissing); + bool& warningRecyclerMissing, + ProcessCallback& callback); } #endif //ALGORITHM_H_34218518475321452548 diff --git a/FreeFileSync/Source/application.cpp b/FreeFileSync/Source/application.cpp index 14aadc03..a69c07ce 100644 --- a/FreeFileSync/Source/application.cpp +++ b/FreeFileSync/Source/application.cpp @@ -50,20 +50,6 @@ int _matherr(struct _exception* except) namespace { -/* -boost::thread::id mainThreadId = boost::this_thread::get_id(); - -void onTerminationRequested() -{ -std::wstring msg = boost::this_thread::get_id() == mainThreadId ? - L"Termination requested in main thread!\n\n" : - L"Termination requested in worker thread!\n\n"; -msg += L"Please file a bug report at: http://sourceforge.net/projects/freefilesync"; - -wxSafeShowMessage(_("An exception occurred"), msg); -std::abort(); -} -*/ #ifdef ZEN_WIN void enableCrashingOnCrashes() //should be needed for 32-bit code only: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work { @@ -144,9 +130,6 @@ const wxEventType EVENT_ENTER_EVENT_LOOP = wxNewEventType(); bool Application::OnInit() { - //-> this seems rather useless: - //std::set_terminate(onTerminationRequested); //unlike wxWidgets uncaught exception handling, this works for all worker threads - #ifdef ZEN_WIN enableCrashingOnCrashes(); #ifdef _MSC_VER @@ -396,8 +379,8 @@ void Application::launch(const std::vector& commandArgs) auto hasNonDefaultConfig = [](const FolderPairEnh& fp) { - return !(fp == FolderPairEnh(fp.dirpathPhraseLeft, - fp.dirpathPhraseRight, + return !(fp == FolderPairEnh(fp.folderPathPhraseLeft_, + fp.folderPathPhraseRight_, nullptr, nullptr, FilterConfig())); }; @@ -416,8 +399,8 @@ void Application::launch(const std::vector& commandArgs) for (size_t i = 0; i < leftDirs.size(); ++i) if (i == 0) { - mainCfg.firstPair.dirpathPhraseLeft = leftDirs [0]; - mainCfg.firstPair.dirpathPhraseRight = rightDirs[0]; + mainCfg.firstPair.folderPathPhraseLeft_ = leftDirs [0]; + mainCfg.firstPair.folderPathPhraseRight_ = rightDirs[0]; } else mainCfg.additionalPairs.emplace_back(leftDirs[i], rightDirs[i], diff --git a/FreeFileSync/Source/comparison.cpp b/FreeFileSync/Source/comparison.cpp index 1d554449..9ab31b8c 100644 --- a/FreeFileSync/Source/comparison.cpp +++ b/FreeFileSync/Source/comparison.cpp @@ -31,7 +31,7 @@ std::vector zen::extractCompareCfg(const MainConfiguration& mainC std::transform(allPairs.begin(), allPairs.end(), std::back_inserter(output), [&](const FolderPairEnh& enhPair) -> FolderPairCfg { - return FolderPairCfg(enhPair.dirpathPhraseLeft, enhPair.dirpathPhraseRight, + return FolderPairCfg(enhPair.folderPathPhraseLeft_, enhPair.folderPathPhraseRight_, enhPair.altCmpConfig.get() ? enhPair.altCmpConfig->compareVar : mainCfg.cmpConfig.compareVar, enhPair.altCmpConfig.get() ? enhPair.altCmpConfig->handleSymlinks : mainCfg.cmpConfig.handleSymlinks, fileTimeTolerance, @@ -80,8 +80,8 @@ ResolvedBaseFolders initializeBaseFolders(const std::vector& cfgL output.resolvedPairs.clear(); for (const FolderPairCfg& fpCfg : cfgList) { - std::shared_ptr abfLeft = createAbstractBaseFolder(fpCfg.dirpathPhraseLeft); - std::shared_ptr abfRight = createAbstractBaseFolder(fpCfg.dirpathPhraseRight); + std::shared_ptr abfLeft = createAbstractBaseFolder(fpCfg.folderPathPhraseLeft_); + std::shared_ptr abfRight = createAbstractBaseFolder(fpCfg.folderPathPhraseRight_); uniqueBaseFolders.insert(abfLeft .get()); uniqueBaseFolders.insert(abfRight.get()); @@ -392,8 +392,8 @@ void categorizeSymlinkByContent(SymlinkPair& linkObj, int fileTimeTolerance, uns if (targetPathRawL == targetPathRawR #ifdef ZEN_WIN //type of symbolic link is relevant for Windows only && - ABF::dirExists(linkObj.getAbstractPath()) == //check if dir-symlink - ABF::dirExists(linkObj.getAbstractPath()) // + ABF::folderExists(linkObj.getAbstractPath()) == //check if dir-symlink + ABF::folderExists(linkObj.getAbstractPath()) // #endif ) { diff --git a/FreeFileSync/Source/comparison.h b/FreeFileSync/Source/comparison.h index 0aa5dd38..c96137de 100644 --- a/FreeFileSync/Source/comparison.h +++ b/FreeFileSync/Source/comparison.h @@ -18,16 +18,16 @@ namespace zen { struct FolderPairCfg { - FolderPairCfg(const Zstring& dirPhraseLeft, - const Zstring& dirPhraseRight, + FolderPairCfg(const Zstring& folderPathPhraseLeft, + const Zstring& folderPathPhraseRight, CompareVariant cmpVar, SymLinkHandling handleSymlinksIn, int fileTimeToleranceIn, unsigned int optTimeShiftHoursIn, const NormalizedFilter& filterIn, const DirectionConfig& directCfg) : - dirpathPhraseLeft(dirPhraseLeft), - dirpathPhraseRight(dirPhraseRight), + folderPathPhraseLeft_ (folderPathPhraseLeft), + folderPathPhraseRight_(folderPathPhraseRight), compareVar(cmpVar), handleSymlinks(handleSymlinksIn), fileTimeTolerance(fileTimeToleranceIn), @@ -35,8 +35,8 @@ struct FolderPairCfg filter(filterIn), directionCfg(directCfg) {} - Zstring dirpathPhraseLeft; //unresolved directory names as entered by user! - Zstring dirpathPhraseRight; // + Zstring folderPathPhraseLeft_; //unresolved directory names as entered by user! + Zstring folderPathPhraseRight_; // CompareVariant compareVar; SymLinkHandling handleSymlinks; diff --git a/FreeFileSync/Source/file_hierarchy.h b/FreeFileSync/Source/file_hierarchy.h index 249346ca..130c6420 100644 --- a/FreeFileSync/Source/file_hierarchy.h +++ b/FreeFileSync/Source/file_hierarchy.h @@ -238,9 +238,6 @@ public: CompareVariant cmpVar, int fileTimeTolerance, unsigned int optTimeShiftHours) : -#ifdef _MSC_VER -#pragma warning(suppress: 4355) //"The this pointer is valid only within nonstatic member functions. It cannot be used in the initializer list for a base class." -#endif HierarchyObject(Zstring(), *this), filter_(filter), cmpVar_(cmpVar), fileTimeTolerance_(fileTimeTolerance), optTimeShiftHours_(optTimeShiftHours), dirExistsLeft_ (dirExistsLeft), diff --git a/FreeFileSync/Source/fs/abstract.cpp b/FreeFileSync/Source/fs/abstract.cpp index ffdf286a..79ba889f 100644 --- a/FreeFileSync/Source/fs/abstract.cpp +++ b/FreeFileSync/Source/fs/abstract.cpp @@ -76,7 +76,7 @@ ABF::FileAttribAfterCopy ABF::copyFileTransactional(const AbstractPathRef& apSou //fall back to stream-based file copy: if (copyFilePermissions) - throw FileError(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(getDisplayPath(apTargetTmp))), + throw FileError(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(ABF::getDisplayPath(apTargetTmp))), _("Operation not supported for different base folder types.")); return copyFileAsStream(apSource, apTargetTmp, onNotifyCopyStatus); //throw FileError, ErrorTargetExisting, ErrorFileLocked @@ -100,7 +100,7 @@ ABF::FileAttribAfterCopy ABF::copyFileTransactional(const AbstractPathRef& apSou } //transactional behavior: ensure cleanup; not needed before copyFileBestEffort() which is already transactional - zen::ScopeGuard guardTempFile = zen::makeGuard([&] { try { removeFile(apTargetTmp); } catch (FileError&) {} }); + zen::ScopeGuard guardTempFile = zen::makeGuard([&] { try { ABF::removeFile(apTargetTmp); } catch (FileError&) {} }); //have target file deleted (after read access on source and target has been confirmed) => allow for almost transactional overwrite if (onDeleteTargetFile) @@ -146,10 +146,10 @@ void ABF::createFolderRecursively(const AbstractPathRef& ap) //throw FileError catch (ErrorTargetExisting&) {} catch (ErrorTargetPathMissing&) { - if (const Opt parentPathImpl = ap.abf->getParentFolderPathImpl(ap.itemPathImpl)) + if (std::unique_ptr parentPath = ABF::getParentFolderPath(ap)) { //recurse... - createFolderRecursively(AbstractPathRef(*ap.abf, *parentPathImpl)); //throw FileError + createFolderRecursively(*parentPath); //throw FileError //now try again... ABF::createFolderSimple(ap); //throw FileError, (ErrorTargetExisting), (ErrorTargetPathMissing) @@ -170,7 +170,7 @@ struct FlatTraverserCallback: public ABF::TraverserCallback std::unique_ptr onDir (const DirInfo& di) override { folderNames_.push_back(di.shortName); return nullptr; } HandleLink onSymlink(const SymlinkInfo& si) override { - if (ABF::dirExists(ABF::appendRelPath(folderPath_, si.shortName))) //dir symlink + if (ABF::folderExists(ABF::appendRelPath(folderPath_, si.shortName))) //dir symlink folderLinkNames_.push_back(si.shortName); else //file symlink, broken symlink fileNames_.push_back(si.shortName); @@ -196,7 +196,7 @@ void removeFolderRecursivelyImpl(const AbstractPathRef& folderPath, //throw File const std::function& onBeforeFolderDeletion) //one call for each *existing* object! { assert(!ABF::symlinkExists(folderPath)); //[!] no symlinks in this context!!! - assert(ABF::dirExists(folderPath)); //Do NOT traverse into it deleting contained files!!! + assert(ABF::folderExists(folderPath)); //Do NOT traverse into it deleting contained files!!! FlatTraverserCallback ft(folderPath); //traverse source directory one level deep ABF::traverseFolder(folderPath, ft); //throw FileError diff --git a/FreeFileSync/Source/fs/abstract.h b/FreeFileSync/Source/fs/abstract.h index 1b951089..566604bf 100644 --- a/FreeFileSync/Source/fs/abstract.h +++ b/FreeFileSync/Source/fs/abstract.h @@ -52,9 +52,17 @@ struct AbstractBaseFolder static Opt getNativeItemPath(const AbstractPathRef& ap) { return ap.abf->isNativeFileSystem() ? Opt(ap.itemPathImpl) : NoValue(); } + static std::unique_ptr getParentFolderPath(const AbstractPathRef& ap) + { + if (const Opt parentPathImpl = ap.abf->getParentFolderPathImpl(ap.itemPathImpl)) + return std::unique_ptr(new AbstractPathRef(*ap.abf, *parentPathImpl)); + return nullptr; + } + //limitation: zen::Opt requires default-constructibility => we need to use std::unique_ptr: + //---------------------------------------------------------------------------------------------------------------- static bool fileExists (const AbstractPathRef& ap) { return ap.abf->fileExists (ap.itemPathImpl); } //noexcept; check whether file or file-symlink exists - static bool dirExists (const AbstractPathRef& ap) { return ap.abf->dirExists (ap.itemPathImpl); } //noexcept; check whether directory or dir-symlink exists + static bool folderExists (const AbstractPathRef& ap) { return ap.abf->folderExists (ap.itemPathImpl); } //noexcept; check whether directory or dir-symlink exists static bool symlinkExists (const AbstractPathRef& ap) { return ap.abf->symlinkExists (ap.itemPathImpl); } //noexcept; check whether a symbolic link exists static bool somethingExists(const AbstractPathRef& ap) { return ap.abf->somethingExists(ap.itemPathImpl); } //noexcept; check whether any object with this name exists //---------------------------------------------------------------------------------------------------------------- @@ -95,7 +103,7 @@ struct AbstractBaseFolder //- THREAD-SAFETY: must be thread-safe like an int! => no dangling references to this instance! static IconLoader getAsyncIconLoader(const AbstractPathRef& ap) { return ap.abf->getAsyncIconLoader(ap.itemPathImpl); } //noexcept! virtual std::function /*throw FileError*/ getAsyncConnectFolder(bool allowUserInteraction) const = 0; //noexcept, optional return value - static std::function /*throw FileError*/ getAsyncCheckDirExists(const AbstractPathRef& ap) { return ap.abf->getAsyncCheckDirExists(ap.itemPathImpl); } //noexcept + static std::function /*throw FileError*/ getAsyncCheckFolderExists(const AbstractPathRef& ap) { return ap.abf->getAsyncCheckFolderExists(ap.itemPathImpl); } //noexcept //---------------------------------------------------------------------------------------------------------------- using FileId = Zbase; @@ -161,10 +169,10 @@ struct AbstractBaseFolder struct FileInfo { - const Zchar* shortName; - std::uint64_t fileSize; //unit: bytes! - std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC - const FileId& id; //optional: empty if not supported! + const Zchar* shortName; + std::uint64_t fileSize; //unit: bytes! + std::int64_t lastWriteTime; //number of seconds since Jan. 1st 1970 UTC + const FileId id; //optional: empty if not supported! const SymlinkInfo* symlinkInfo; //only filled if file is a followed symlink }; @@ -294,7 +302,7 @@ private: //---------------------------------------------------------------------------------------------------------------- virtual bool fileExists (const Zstring& itemPathImpl) const = 0; //noexcept - virtual bool dirExists (const Zstring& itemPathImpl) const = 0; //noexcept + virtual bool folderExists (const Zstring& itemPathImpl) const = 0; //noexcept virtual bool symlinkExists (const Zstring& itemPathImpl) const = 0; //noexcept virtual bool somethingExists(const Zstring& itemPathImpl) const = 0; //noexcept //---------------------------------------------------------------------------------------------------------------- @@ -320,7 +328,7 @@ private: //---------------------------------------------------------------------------------------------------------------- //- THREAD-SAFETY: must be thread-safe like an int! => no dangling references to this instance! virtual IconLoader getAsyncIconLoader(const Zstring& itemPathImpl) const = 0; //noexcept! - virtual std::function /*throw FileError*/ getAsyncCheckDirExists(const Zstring& itemPathImpl) const = 0; //noexcept + virtual std::function /*throw FileError*/ getAsyncCheckFolderExists(const Zstring& itemPathImpl) const = 0; //noexcept //---------------------------------------------------------------------------------------------------------------- virtual std::unique_ptr getInputStream (const Zstring& itemPathImpl) const = 0; //throw FileError, ErrorFileLocked virtual std::unique_ptr getOutputStream(const Zstring& itemPathImpl, //throw FileError, ErrorTargetExisting diff --git a/FreeFileSync/Source/fs/native.cpp b/FreeFileSync/Source/fs/native.cpp index 3ddc397b..7bbe4c06 100644 --- a/FreeFileSync/Source/fs/native.cpp +++ b/FreeFileSync/Source/fs/native.cpp @@ -304,7 +304,7 @@ private: //---------------------------------------------------------------------------------------------------------------- bool fileExists (const Zstring& itemPathImpl) const override { return zen::fileExists (itemPathImpl); } //noexcept - bool dirExists (const Zstring& itemPathImpl) const override { return zen::dirExists (itemPathImpl); } //noexcept + bool folderExists (const Zstring& itemPathImpl) const override { return zen::dirExists (itemPathImpl); } //noexcept bool symlinkExists (const Zstring& itemPathImpl) const override { return zen::symlinkExists (itemPathImpl); } //noexcept bool somethingExists(const Zstring& itemPathImpl) const override { return zen::somethingExists(itemPathImpl); } //noexcept //---------------------------------------------------------------------------------------------------------------- @@ -357,9 +357,9 @@ private: } //- THREAD-SAFETY: must be thread-safe like an int! => no dangling references to this instance! - std::function /*throw FileError*/ getAsyncCheckDirExists(const Zstring& itemPathImpl) const override //noexcept + std::function /*throw FileError*/ getAsyncCheckFolderExists(const Zstring& itemPathImpl) const override //noexcept { - warn_static("finish file error handling") + warn_static("finish file error detection") return [itemPathImpl] { return zen::dirExists(itemPathImpl); }; } @@ -476,43 +476,61 @@ bool RecycleSessionNative::recycleItem(const AbstractPathRef& ap, const Zstring& assert(!startsWith(logicalRelPath, FILE_NAME_SEPARATOR)); #ifdef ZEN_WIN + const bool remnantRecyclerItem = [&itemPath] //clean-up of recycler temp directory failed during last sync + { + //search for path component named "RecycleBin.ffs_tmp" or "RecycleBin_.ffs_tmp": + const size_t pos = itemPath.find(L"\\RecycleBin"); + if (pos == Zstring::npos) + return false; + + const size_t pos2 = itemPath.find(L'\\', pos + 1); + return endsWith(StringRef(itemPath.begin(), pos2 == Zstring::npos ? itemPath.end() : itemPath.begin() + pos2), ABF::TEMP_FILE_ENDING); + }(); + + //do not create RecycleBin.ffs_tmp directories recursively if recycling a particular item fails forever! + //=> 1. stack overflow crashes 2. paths longer than 260 chars, undeletable/viewable with Explorer + if (remnantRecyclerItem) + return recycleOrDelete(itemPath); //throw FileError + const Zstring tmpPath = getOrCreateRecyclerTempDirPf() + logicalRelPath; //throw FileError bool deleted = false; auto moveToTempDir = [&] { - try - { - //performance optimization: Instead of moving each object into recycle bin separately, - //we rename them one by one into a temporary directory and batch-recycle this directory after sync - renameFile(itemPath, tmpPath); //throw FileError, ErrorDifferentVolume - this->toBeRecycled.push_back(tmpPath); - deleted = true; - } - catch (ErrorDifferentVolume&) //MoveFileEx() returns ERROR_PATH_NOT_FOUND *before* considering ERROR_NOT_SAME_DEVICE! => we have to create tmpParentDir anyway to find out! - { - deleted = recycleOrDelete(itemPath); //throw FileError - } + //perf: Instead of recycling each object separately, we rename them one by one + // into a temporary directory and batch-recycle all at once after sync + renameFile(itemPath, tmpPath); //throw FileError, ErrorDifferentVolume + this->toBeRecycled.push_back(tmpPath); + deleted = true; }; try { - moveToTempDir(); //throw FileError, ErrorDifferentVolume - } - catch (FileError&) - { - if (somethingExists(itemPath)) + try + { + moveToTempDir(); //throw FileError, ErrorDifferentVolume + } + catch (ErrorDifferentVolume&) { throw; } + catch (FileError&) { - const Zstring tmpParentDir = beforeLast(tmpPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); //what if C:\ ? - if (!somethingExists(tmpParentDir)) + if (somethingExists(itemPath)) { - makeDirectoryRecursively(tmpParentDir); //throw FileError - moveToTempDir(); //throw FileError -> this should work now! + const Zstring tmpParentDir = beforeLast(tmpPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); //what if C:\ ? + if (!somethingExists(tmpParentDir)) + { + makeDirectoryRecursively(tmpParentDir); //throw FileError + moveToTempDir(); //throw FileError, ErrorDifferentVolume -> this should work now! + } + else + throw; } - else - throw; } } + catch (ErrorDifferentVolume&) //MoveFileEx() returns ERROR_PATH_NOT_FOUND *before* considering ERROR_NOT_SAME_DEVICE! => we have to create tmpParentDir to find out! + { + return recycleOrDelete(itemPath); //throw FileError + } + return deleted; #elif defined ZEN_LINUX || defined ZEN_MAC diff --git a/FreeFileSync/Source/lib/binary.cpp b/FreeFileSync/Source/lib/binary.cpp index d1f6e1b4..f55a99a9 100644 --- a/FreeFileSync/Source/lib/binary.cpp +++ b/FreeFileSync/Source/lib/binary.cpp @@ -8,7 +8,6 @@ #include #include #include -#include using namespace zen; using ABF = AbstractBaseFolder; @@ -75,16 +74,6 @@ const std::int64_t TICKS_PER_SEC = ticksPerSec(); bool zen::filesHaveSameContent(const AbstractPathRef& filePath1, const AbstractPathRef& filePath2, const std::function& onUpdateStatus) //throw FileError { - static boost::thread_specific_ptr> cpyBuf1; - static boost::thread_specific_ptr> cpyBuf2; - if (!cpyBuf1.get()) - cpyBuf1.reset(new std::vector()); - if (!cpyBuf2.get()) - cpyBuf2.reset(new std::vector()); - - std::vector& memory1 = *cpyBuf1; - std::vector& memory2 = *cpyBuf2; - const std::unique_ptr inStream1 = ABF::getInputStream(filePath1); //throw FileError, (ErrorFileLocked) const std::unique_ptr inStream2 = ABF::getInputStream(filePath2); // @@ -92,22 +81,24 @@ bool zen::filesHaveSameContent(const AbstractPathRef& filePath1, const AbstractP inStream2->optimalBlockSize())); TickVal lastDelayViolation = getTicks(); + std::vector buf; //make this thread-local? => on noticeable perf advantage! for (;;) { const size_t bufSize = dynamicBufSize.get(); //save for reliable eof check below!!! - setMinSize(memory1, bufSize); - setMinSize(memory2, bufSize); + setMinSize(buf, 2 * bufSize); + char* buf1 = &buf[0]; + char* buf2 = &buf[bufSize]; const TickVal startTime = getTicks(); - const size_t length1 = inStream1->read(&memory1[0], bufSize); //throw FileError - const size_t length2 = inStream2->read(&memory2[0], bufSize); //returns actual number of bytes read + const size_t length1 = inStream1->read(buf1, bufSize); //throw FileError + const size_t length2 = inStream2->read(buf2, bufSize); //returns actual number of bytes read //send progress updates immediately after reading to reliably allow speed calculations for our clients! if (onUpdateStatus) onUpdateStatus(std::max(length1, length2)); - if (length1 != length2 || ::memcmp(&memory1[0], &memory2[0], length1) != 0) + if (length1 != length2 || ::memcmp(buf1, buf2, length1) != 0) return false; //-------- dynamically set buffer size to keep callback interval between 100 - 500ms --------------------- diff --git a/FreeFileSync/Source/lib/cmp_filetime.h b/FreeFileSync/Source/lib/cmp_filetime.h index 088537ac..4d47a63b 100644 --- a/FreeFileSync/Source/lib/cmp_filetime.h +++ b/FreeFileSync/Source/lib/cmp_filetime.h @@ -34,11 +34,8 @@ bool sameFileTime(std::int64_t lhs, std::int64_t rhs, int tolerance, unsigned in return false; } -//--------------------------------------------------------------------------------------------------------------- -//number of seconds since Jan 1st 1970 + 1 year (needn't be too precise) -const std::int64_t oneYearFromNow = std::time(nullptr) + 365 * 24 * 3600; //init at program startup in *each* compilation unit -> avoid MT issues -//refactor when C++11 thread-safe static initialization is availalbe in VS (already in GCC) +//--------------------------------------------------------------------------------------------------------------- enum class TimeResult { @@ -53,6 +50,13 @@ enum class TimeResult inline TimeResult compareFileTime(std::int64_t lhs, std::int64_t rhs, int tolerance, unsigned int optTimeShiftHours) { +#if defined _MSC_VER && _MSC_VER < 1900 +#error function scope static initialization is not yet thread-safe! +#endif + + //number of seconds since Jan 1st 1970 + 1 year (needn't be too precise) + static const std::int64_t oneYearFromNow = std::time(nullptr) + 365 * 24 * 3600; + if (sameFileTime(lhs, rhs, tolerance, optTimeShiftHours)) //last write time may differ by up to 2 seconds (NTFS vs FAT32) return TimeResult::EQUAL; diff --git a/FreeFileSync/Source/lib/db_file.cpp b/FreeFileSync/Source/lib/db_file.cpp index b4441604..a924e3e2 100644 --- a/FreeFileSync/Source/lib/db_file.cpp +++ b/FreeFileSync/Source/lib/db_file.cpp @@ -656,9 +656,10 @@ private: //if directory is not included in "currentDirs", it is either not existing anymore, in which case it should be deleted from database //or it was excluded via filter and the database entry should be preserved - warn_static("insufficient for *.txt-include filters! -> e.g. 1. *.txt-include, both sides in sync, txt-fiels in subfolder") - warn_static("2. delete all subfolders externally ") - warn_static("3. sync => db should be updated == entries removed for .txt; mabye even for deleted subfolders!?!") + warn_static("insufficient for *.txt-include filters! -> e.g. " + "1. *.txt-include, both sides in sync, txt-fiels in subfolder" + "2. delete all subfolders externally " + "3. sync => db should be updated == entries removed for .txt; mabye even for deleted subfolders!?!") }); } @@ -720,7 +721,7 @@ void zen::saveLastSynchronousState(const BaseDirPair& baseDirObj, const std::fun ABF::removeFile(dbPathRightTmp); //throw FileError //(try to) load old database files... - DbStreams streamsLeft; //list of session ID + DirInfo-stream + DbStreams streamsLeft; //list of session ID + DirInfo-stream DbStreams streamsRight; //std::function onUpdateLoadStatus; diff --git a/FreeFileSync/Source/lib/dir_exist_async.h b/FreeFileSync/Source/lib/dir_exist_async.h index 4e376d8b..0e7e8f02 100644 --- a/FreeFileSync/Source/lib/dir_exist_async.h +++ b/FreeFileSync/Source/lib/dir_exist_async.h @@ -7,6 +7,7 @@ #ifndef DIR_EXIST_HEADER_08173281673432158067342132467183267 #define DIR_EXIST_HEADER_08173281673432158067342132467183267 +#include #include #include #include "../fs/abstract.h" @@ -28,30 +29,13 @@ struct DirectoryStatus }; -struct DirCheckResult -{ - bool exists; - std::unique_ptr error; - - DirCheckResult(bool existsIn, std::unique_ptr&& errorIn) : exists(existsIn), error(std::move(errorIn)) {} - - DirCheckResult (DirCheckResult&& tmp) : exists(tmp.exists), error(std::move(tmp.error)) {} //= default with C++14 - DirCheckResult& operator=(DirCheckResult&& tmp) //= default with C++14 - { - exists = tmp.exists; - error = std::move(tmp.error); - return *this; - } -}; - - DirectoryStatus checkFolderExistenceUpdating(const std::set& baseFolders, bool allowUserInteraction, ProcessCallback& procCallback) { using namespace zen; DirectoryStatus output; - std::list>> futureInfo; + std::list>> futureInfo; for (const ABF* baseFolder : baseFolders) if (!baseFolder->emptyBaseFolderPath()) //skip empty dirs @@ -59,28 +43,21 @@ DirectoryStatus checkFolderExistenceUpdating(const std::setgetAbstractPath(Zstring()); std::function connectFolder /*throw FileError*/ = baseFolder->getAsyncConnectFolder(allowUserInteraction); //noexcept - std::function dirExists /*throw FileError*/ = ABF::getAsyncCheckDirExists(folderPath); //noexcept + std::function dirExists /*throw FileError*/ = ABF::getAsyncCheckFolderExists(folderPath); //noexcept futureInfo.emplace_back(baseFolder, runAsync([connectFolder, dirExists] { - try - { - //1. login to network share, open FTP connection, ect. - if (connectFolder) - connectFolder(); //throw FileError - - //2. check dir existence - return DirCheckResult(dirExists(), nullptr); //throw FileError - } - catch (const FileError& e) - { - return DirCheckResult(false, make_unique(e)); - } + //1. login to network share, open FTP connection, ect. + if (connectFolder) + connectFolder(); //throw FileError + + //2. check dir existence + return dirExists(); //throw FileError })); } //don't wait (almost) endlessly like win32 would on non-existing network shares: - boost::chrono::steady_clock::time_point endTime = boost::chrono::steady_clock::now() + boost::chrono::seconds(20); //consider CD-rom insert or hard disk spin up time from sleep + std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + std::chrono::seconds(20); //consider CD-rom insert or hard disk spin up time from sleep for (auto& fi : futureInfo) { @@ -88,19 +65,21 @@ DirectoryStatus checkFolderExistenceUpdating(const std::set +#include #include #include #include -#include //includes +#include #include #include #include @@ -54,16 +54,15 @@ using MemStreamIn = MemoryStreamIn ; class LifeSigns { public: - LifeSigns(const Zstring& lockfilepath) : //throw()!!! siehe SharedDirLock() - lockfilepath_(lockfilepath) {} //thread safety: make deep copy! + LifeSigns(const Zstring& lockfilepath) : lockfilepath_(lockfilepath) {} - void operator()() const //thread entry + void operator()() const //throw ThreadInterruption { try { for (;;) { - boost::this_thread::sleep_for(boost::chrono::seconds(EMIT_LIFE_SIGN_INTERVAL)); //throw boost::thread_interrupted + interruptibleSleep(std::chrono::seconds(EMIT_LIFE_SIGN_INTERVAL)); //throw ThreadInterruption //actual work emitLifeSign(); //throw () @@ -327,7 +326,7 @@ struct LockInformation //throw FileError { char tmp[sizeof(LOCK_FORMAT_DESCR)] = {}; readArray(stream, &tmp, sizeof(tmp)); //file format header - const int lockFileVersion = readNumber(stream); // + const int lockFileVersion = readNumber(stream); // if (!std::equal(std::begin(tmp), std::end(tmp), std::begin(LOCK_FORMAT_DESCR)) || lockFileVersion != LOCK_FORMAT_VER) @@ -343,7 +342,7 @@ struct LockInformation //throw FileError void toStream(MemStreamOut& stream) const //throw () { writeArray(stream, LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR)); - writeNumber(stream, LOCK_FORMAT_VER); + writeNumber(stream, LOCK_FORMAT_VER); static_assert(sizeof(processId) <= sizeof(std::uint64_t), ""); //ensure cross-platform compatibility! static_assert(sizeof(sessionId) <= sizeof(std::uint64_t), ""); // @@ -458,7 +457,7 @@ void waitOnDirLock(const Zstring& lockfilepath, DirLockCallback* callback) //thr for (;;) { const TickVal now = getTicks(); - const std::uint64_t fileSizeNew = ::getLockFileSize(lockfilepath); //throw FileError + const std::uint64_t fileSizeNew = getLockFileSize(lockfilepath); //throw FileError if (TICKS_PER_SEC <= 0 || !lastLifeSign.isValid() || !now.isValid()) throw FileError(L"System timer failed."); //no i18n: "should" never throw ;) @@ -480,7 +479,7 @@ void waitOnDirLock(const Zstring& lockfilepath, DirLockCallback* callback) //thr if (retrieveLockId(lockfilepath) != originalLockId) //throw FileError -> since originalLockId is filled, we are not expecting errors! return; //another process has placed a new lock, leave scope: the wait for the old lock is technically over... - if (::getLockFileSize(lockfilepath) != fileSizeOld) //throw FileError + if (getLockFileSize(lockfilepath) != fileSizeOld) //throw FileError continue; //late life sign removeFile(lockfilepath); //throw FileError @@ -492,7 +491,7 @@ void waitOnDirLock(const Zstring& lockfilepath, DirLockCallback* callback) //thr for (size_t i = 0; i < 1000 * POLL_LIFE_SIGN_INTERVAL / GUI_CALLBACK_INTERVAL; ++i) { if (callback) callback->requestUiRefresh(); - boost::this_thread::sleep_for(boost::chrono::milliseconds(GUI_CALLBACK_INTERVAL)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(GUI_CALLBACK_INTERVAL)); if (callback) { @@ -603,13 +602,13 @@ public: while (!::tryLock(lockfilepath)) //throw FileError ::waitOnDirLock(lockfilepath, callback); // - threadObj = boost::thread(LifeSigns(lockfilepath)); + lifeSignthread = InterruptibleThread(LifeSigns(lockfilepath)); } ~SharedDirLock() { - threadObj.interrupt(); //thread lifetime is subset of this instances's life - threadObj.join(); //throw boost::thread_interrupted -> not expected => main thread! + lifeSignthread.interrupt(); //thread lifetime is subset of this instances's life + lifeSignthread.join(); ::releaseLock(lockfilepath_); //throw () } @@ -619,7 +618,7 @@ private: SharedDirLock& operator=(const DirLock&) = delete; const Zstring lockfilepath_; - boost::thread threadObj; + InterruptibleThread lifeSignthread; }; diff --git a/FreeFileSync/Source/lib/dir_lock.h b/FreeFileSync/Source/lib/dir_lock.h index 8fd43fcf..00634b5d 100644 --- a/FreeFileSync/Source/lib/dir_lock.h +++ b/FreeFileSync/Source/lib/dir_lock.h @@ -16,7 +16,7 @@ const size_t GUI_CALLBACK_INTERVAL = 100; struct DirLockCallback //while waiting for the lock { virtual ~DirLockCallback() {} - virtual void requestUiRefresh() = 0; //allowed to throw exceptions + virtual void requestUiRefresh() = 0; //allowed to throw exceptions virtual void reportStatus(const std::wstring& text) = 0; }; diff --git a/FreeFileSync/Source/lib/generate_logfile.h b/FreeFileSync/Source/lib/generate_logfile.h index 60f33126..608e0289 100644 --- a/FreeFileSync/Source/lib/generate_logfile.h +++ b/FreeFileSync/Source/lib/generate_logfile.h @@ -8,7 +8,6 @@ #define GEN_LOGFILE_H_93172643216748973216458732165415 #include -//#include #include #include #include "ffs_paths.h" diff --git a/FreeFileSync/Source/lib/hard_filter.cpp b/FreeFileSync/Source/lib/hard_filter.cpp index d2313f88..4d786483 100644 --- a/FreeFileSync/Source/lib/hard_filter.cpp +++ b/FreeFileSync/Source/lib/hard_filter.cpp @@ -218,14 +218,6 @@ bool matchesMaskBegin(const Zstring& name, const std::vector& masks) { return std::any_of(masks.begin(), masks.end(), [&](const Zstring& mask) { return matchesMaskBegin(name.c_str(), mask.c_str()); }); } - - -inline -void removeDuplicates(std::vector& v) -{ - std::sort(v.begin(), v.end()); - v.erase(std::unique(v.begin(), v.end()), v.end()); -} } diff --git a/FreeFileSync/Source/lib/icon_buffer.cpp b/FreeFileSync/Source/lib/icon_buffer.cpp index 01acd175..98426049 100644 --- a/FreeFileSync/Source/lib/icon_buffer.cpp +++ b/FreeFileSync/Source/lib/icon_buffer.cpp @@ -5,8 +5,9 @@ // ************************************************************************** #include "icon_buffer.h" +#include #include -#include //includes +#include //includes #include #include #include "icon_loader.h" @@ -24,7 +25,7 @@ namespace const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to hold in buffer: must be big enough to hold visible icons + preload buffer! Consider OS limit on GDI resources (wxBitmap)!!! #ifndef NDEBUG - const boost::thread::id mainThreadId = boost::this_thread::get_id(); + const std::thread::id mainThreadId = std::this_thread::get_id(); #endif #ifdef ZEN_WIN @@ -35,7 +36,7 @@ const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to hold in buffer: //destroys raw icon! Call from GUI thread only! wxBitmap extractWxBitmap(ImageHolder&& ih) { - assert(boost::this_thread::get_id() == mainThreadId); + assert(std::this_thread::get_id() == mainThreadId); #ifndef NDEBUG auto check = [&] { assert(!ih); }; //work around V120_XP compilation issue ZEN_ON_SCOPE_EXIT(check()); @@ -132,11 +133,13 @@ struct WorkItem class WorkLoad { public: - WorkItem extractNextFile() //context of worker thread, blocking + //context of worker thread, blocking: + WorkItem extractNextFile() //throw ThreadInterruption { - assert(boost::this_thread::get_id() != mainThreadId); - boost::unique_lock dummy(lockFiles); - conditionNewWork.wait(dummy, [this] { return !workLoad.empty(); }); //throw boost::thread_interrupted + assert(std::this_thread::get_id() != mainThreadId); + std::unique_lock dummy(lockFiles); + + interruptibleWait(conditionNewWork, dummy, [this] { return !workLoad.empty(); }); //throw ThreadInterruption WorkItem workItem = workLoad.back(); // workLoad.pop_back(); //yes, not std::bad_alloc exception-safe, but bad_alloc is not relevant for us @@ -145,9 +148,9 @@ public: void setWorkload(const std::vector& newLoad) //context of main thread { - assert(boost::this_thread::get_id() == mainThreadId); + assert(std::this_thread::get_id() == mainThreadId); { - boost::lock_guard dummy(lockFiles); + std::lock_guard dummy(lockFiles); workLoad.clear(); for (const AbstractPathRef& filePath : newLoad) @@ -161,9 +164,9 @@ public: void addToWorkload(const AbstractPathRef& filePath) //context of main thread { - assert(boost::this_thread::get_id() == mainThreadId); + assert(std::this_thread::get_id() == mainThreadId); { - boost::lock_guard dummy(lockFiles); + std::lock_guard dummy(lockFiles); workLoad.emplace_back(filePath.getUniqueId(), //set as next item to retrieve ABF::getAsyncIconLoader(filePath), //noexcept! @@ -173,9 +176,9 @@ public: } private: - std::vector workLoad; //processes last elements of vector first! - boost::mutex lockFiles; - boost::condition_variable conditionNewWork; //signal event: data for processing available + std::vector workLoad; //processes last elements of vector first! + std::mutex lockFiles; + std::condition_variable conditionNewWork; //signal event: data for processing available }; @@ -187,15 +190,15 @@ public: //called by main and worker thread: bool hasIcon(const AbstractPathRef::ItemId& id) const { - boost::lock_guard dummy(lockIconList); + std::lock_guard dummy(lockIconList); return iconList.find(id) != iconList.end(); } //must be called by main thread only! => wxBitmap is NOT thread-safe like an int (non-atomic ref-count!!!) Opt retrieve(const AbstractPathRef::ItemId& id) { - assert(boost::this_thread::get_id() == mainThreadId); - boost::lock_guard dummy(lockIconList); + assert(std::this_thread::get_id() == mainThreadId); + std::lock_guard dummy(lockIconList); auto it = iconList.find(id); if (it == iconList.end()) @@ -215,7 +218,7 @@ public: //called by main and worker thread: void insert(const AbstractPathRef::ItemId& id, ImageHolder&& icon) { - boost::lock_guard dummy(lockIconList); + std::lock_guard dummy(lockIconList); //thread safety: moving ImageHolder is free from side effects, but ~wxBitmap() is NOT! => do NOT delete items from iconList here! auto rc = iconList.emplace(id, makeValueObject()); @@ -231,8 +234,8 @@ public: //call at an appropriate time, e.g. after Workload::setWorkload() void limitSize() { - assert(boost::this_thread::get_id() == mainThreadId); - boost::lock_guard dummy(lockIconList); + assert(std::this_thread::get_id() == mainThreadId); + std::lock_guard dummy(lockIconList); while (iconList.size() > BUFFER_SIZE_MAX) { @@ -329,7 +332,7 @@ private: FileIconMap::iterator next_; // }; - mutable boost::mutex lockIconList; + mutable std::mutex lockIconList; FileIconMap iconList; //shared resource; Zstring is thread-safe like an int FileIconMap::iterator firstInsertPos; FileIconMap::iterator lastInsertPos; @@ -347,7 +350,7 @@ public: buffer_(buffer), iconSizeType(st) {} - void operator()(); //thread entry + void operator()() const; //thread entry private: std::shared_ptr workload_; //main/worker thread may access different shared_ptr instances safely (even though they have the same target!) @@ -379,7 +382,7 @@ public: } dummy; -void WorkerThread::operator()() //thread entry +void WorkerThread::operator()() const //thread entry { #ifdef ZEN_WIN //1. Initialize COM @@ -393,9 +396,10 @@ void WorkerThread::operator()() //thread entry for (;;) { - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption - const WorkItem workItem = workload_->extractNextFile(); //start work: blocks until next icon to load is retrieved + //start work: blocks until next icon to load is retrieved: + const WorkItem workItem = workload_->extractNextFile(); //throw ThreadInterruption if (!buffer_->hasIcon(workItem.id_)) //perf: workload may contain duplicate entries? buffer_->insert(workItem.id_, getDisplayIcon(workItem.iconLoader_, workItem.fileName_, iconSizeType)); @@ -413,13 +417,13 @@ struct IconBuffer::Pimpl std::shared_ptr workload; std::shared_ptr buffer; - boost::thread worker; + InterruptibleThread worker; }; IconBuffer::IconBuffer(IconSize sz) : pimpl(make_unique()), iconSizeType(sz) { - pimpl->worker = boost::thread(WorkerThread(pimpl->workload, pimpl->buffer, sz)); + pimpl->worker = InterruptibleThread(WorkerThread(pimpl->workload, pimpl->buffer, sz)); } @@ -427,7 +431,7 @@ IconBuffer::~IconBuffer() { setWorkload({}); //make sure interruption point is always reached! pimpl->worker.interrupt(); - pimpl->worker.join(); //throw boost::thread_interrupted -> not expected => main thread! + pimpl->worker.join(); } @@ -492,7 +496,7 @@ void IconBuffer::setWorkload(const std::vector& load) assert(load.size() < BUFFER_SIZE_MAX / 2); pimpl->workload->setWorkload(load); //since buffer can only increase due to new workload, - pimpl->buffer->limitSize(); //this is the place to impose the limit from main thread! + pimpl->buffer->limitSize(); //this is the place to impose the limit from main thread! } diff --git a/FreeFileSync/Source/lib/icon_holder.h b/FreeFileSync/Source/lib/icon_holder.h index 7f1719f3..b26deb1e 100644 --- a/FreeFileSync/Source/lib/icon_holder.h +++ b/FreeFileSync/Source/lib/icon_holder.h @@ -22,23 +22,11 @@ struct ImageHolder //prepare conversion to wxImage as much as possible while sta rgb(static_cast(::malloc(width * height * 3))), alpha(withAlpha ? static_cast(::malloc(width * height)) : nullptr) {} - ImageHolder (const ImageHolder&) = delete; //move semantics only! + ImageHolder (ImageHolder&& tmp) = default; // + ImageHolder& operator=(ImageHolder&& tmp) = default; //move semantics only! + ImageHolder (const ImageHolder&) = delete; // ImageHolder& operator=(const ImageHolder&) = delete; // - ImageHolder(ImageHolder&& tmp) : width(tmp.width), //= default in C++14 - height(tmp.height), - rgb(tmp.rgb.release()), - alpha(tmp.alpha.release()) {} - - ImageHolder& operator=(ImageHolder&& tmp) //= default in C++14 - { - std::swap(width, tmp.width); - std::swap(height, tmp.height); - std::swap(rgb, tmp.rgb); - std::swap(alpha, tmp.alpha); - return *this; - } - explicit operator bool() const { return rgb.get() != nullptr; } int getWidth () const { return width; } diff --git a/FreeFileSync/Source/lib/parallel_scan.cpp b/FreeFileSync/Source/lib/parallel_scan.cpp index 8421821d..fc4f9af8 100644 --- a/FreeFileSync/Source/lib/parallel_scan.cpp +++ b/FreeFileSync/Source/lib/parallel_scan.cpp @@ -6,7 +6,7 @@ #include "parallel_scan.h" #include -#include //includes +#include #include #include #include "db_file.h" @@ -156,19 +156,15 @@ typedef Zbase BasicWString; //thread-safe st class AsyncCallback //actor pattern { public: - AsyncCallback() : notifyingThreadID(0), - textScanning(_("Scanning:")), - itemsScanned(0), - activeWorker(0) {} - - FillBufferCallback::HandleError reportError(const std::wstring& msg, size_t retryNumber) //blocking call: context of worker thread + //blocking call: context of worker thread + FillBufferCallback::HandleError reportError(const std::wstring& msg, size_t retryNumber) //throw ThreadInterruption { - boost::unique_lock dummy(lockErrorInfo); - conditionCanReportError.wait(dummy, [this] { return !errorInfo && !errorResponse; }); //throw boost::thread_interrupted + std::unique_lock dummy(lockErrorInfo); + interruptibleWait(conditionCanReportError, dummy, [this] { return !errorInfo && !errorResponse; }); //throw ThreadInterruption - errorInfo = make_unique>(BasicWString(msg), retryNumber); + errorInfo = make_unique>(copyStringTo(msg), retryNumber); - conditionGotResponse.wait(dummy, [this] { return static_cast(errorResponse); }); //throw boost::thread_interrupted + interruptibleWait(conditionGotResponse, dummy, [this] { return static_cast(errorResponse); }); //throw ThreadInterruption FillBufferCallback::HandleError rv = *errorResponse; @@ -183,7 +179,7 @@ public: void processErrors(FillBufferCallback& callback) //context of main thread, call repreatedly { - boost::unique_lock dummy(lockErrorInfo); + std::unique_lock dummy(lockErrorInfo); if (errorInfo.get() && !errorResponse.get()) { FillBufferCallback::HandleError rv = callback.reportError(copyStringTo(errorInfo->first), errorInfo->second); //throw! @@ -203,7 +199,7 @@ public: { if (threadID != notifyingThreadID) return; //only one thread at a time may report status - boost::lock_guard dummy(lockCurrentStatus); + std::lock_guard dummy(lockCurrentStatus); currentFile = copyStringTo(filepath); } @@ -211,7 +207,7 @@ public: { std::wstring filepath; { - boost::lock_guard dummy(lockCurrentStatus); + std::lock_guard dummy(lockCurrentStatus); filepath = copyStringTo(currentFile); } @@ -238,23 +234,23 @@ public: private: //---- error handling ---- - boost::mutex lockErrorInfo; - boost::condition_variable conditionCanReportError; - boost::condition_variable conditionGotResponse; + std::mutex lockErrorInfo; + std::condition_variable conditionCanReportError; + std::condition_variable conditionGotResponse; std::unique_ptr> errorInfo; //error message + retry number std::unique_ptr errorResponse; //---- status updates ---- - std::atomic notifyingThreadID; //CAVEAT: do NOT use boost::thread::id: https://svn.boost.org/trac/boost/ticket/5754 + std::atomic notifyingThreadID { 0 }; //CAVEAT: do NOT use boost::thread::id: https://svn.boost.org/trac/boost/ticket/5754 - boost::mutex lockCurrentStatus; //use a different lock for current file: continue traversing while some thread may process an error + std::mutex lockCurrentStatus; //use a different lock for current file: continue traversing while some thread may process an error BasicWString currentFile; - const BasicWString textScanning; //this one is (currently) not shared and could be made a std::wstring, but we stay consistent and use thread-safe variables in this class only! + const BasicWString textScanning { copyStringTo(_("Scanning:")) }; //this one is (currently) not shared and could be made a std::wstring, but we stay consistent and use thread-safe variables in this class only! //---- status updates II (lock free) ---- - std::atomic itemsScanned; - std::atomic activeWorker; + std::atomic itemsScanned{ 0 }; //std:atomic is uninitialized by default! + std::atomic activeWorker{ 0 }; // }; //------------------------------------------------------------------------------------------------- @@ -299,12 +295,12 @@ public: relNameParentPf_(relNameParentPf), output_(output) {} - virtual void onFile (const FileInfo& fi) override; - virtual std::unique_ptr onDir (const DirInfo& di) override; - virtual HandleLink onSymlink(const SymlinkInfo& li) override; + virtual void onFile (const FileInfo& fi) override; // + virtual std::unique_ptr onDir (const DirInfo& di) override; //throw ThreadInterruption + virtual HandleLink onSymlink(const SymlinkInfo& li) override; // - HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override; - HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override; + HandleError reportDirError (const std::wstring& msg, size_t retryNumber) override; //throw ThreadInterruption + HandleError reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) override; // private: TraverserShared& cfg; @@ -313,9 +309,9 @@ private: }; -void DirCallback::onFile(const FileInfo& fi) +void DirCallback::onFile(const FileInfo& fi) //throw ThreadInterruption { - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption const Zstring fileNameShort(fi.shortName); @@ -352,9 +348,9 @@ void DirCallback::onFile(const FileInfo& fi) } -std::unique_ptr DirCallback::onDir(const DirInfo& di) +std::unique_ptr DirCallback::onDir(const DirInfo& di) //throw ThreadInterruption { - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption const Zstring& relDirPath = relNameParentPf_ + di.shortName; @@ -378,9 +374,9 @@ std::unique_ptr DirCallback::onDir(const DirInfo& di) } -DirCallback::HandleLink DirCallback::onSymlink(const SymlinkInfo& si) +DirCallback::HandleLink DirCallback::onSymlink(const SymlinkInfo& si) //throw ThreadInterruption { - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption const Zstring& relLinkPath = relNameParentPf_ + si.shortName; @@ -419,10 +415,9 @@ DirCallback::HandleLink DirCallback::onSymlink(const SymlinkInfo& si) } -DirCallback::HandleError DirCallback::reportDirError(const std::wstring& msg, size_t retryNumber) +DirCallback::HandleError DirCallback::reportDirError(const std::wstring& msg, size_t retryNumber) //throw ThreadInterruption { - //AsyncCallback::reportError() blocks while implementing boost::this_thread::interruption_point() - switch (cfg.acb_.reportError(msg, retryNumber)) + switch (cfg.acb_.reportError(msg, retryNumber)) //throw ThreadInterruption { case FillBufferCallback::ON_ERROR_IGNORE: cfg.failedDirReads_[beforeLast(relNameParentPf_, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE)] = msg; @@ -436,10 +431,9 @@ DirCallback::HandleError DirCallback::reportDirError(const std::wstring& msg, si } -DirCallback::HandleError DirCallback::reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) +DirCallback::HandleError DirCallback::reportItemError(const std::wstring& msg, size_t retryNumber, const Zchar* shortName) //throw ThreadInterruption { - //AsyncCallback::reportError() blocks while implementing boost::this_thread::interruption_point() - switch (cfg.acb_.reportError(msg, retryNumber)) + switch (cfg.acb_.reportError(msg, retryNumber)) //throw ThreadInterruption { case FillBufferCallback::ON_ERROR_IGNORE: cfg.failedItemReads_[relNameParentPf_ + shortName] = msg; @@ -466,7 +460,7 @@ public: dirKey_(dirKey), dirOutput_(dirOutput) {} - void operator()() //thread entry + void operator()() const //thread entry { acb_->incActiveWorker(); ZEN_ON_SCOPE_EXIT(acb_->decActiveWorker();); @@ -507,13 +501,13 @@ void zen::fillBuffer(const std::set& keysToRead, //in { buf.clear(); - FixedList worker; //note: we cannot use std::vector: compiler error on GCC 4.7, probably a boost screw-up + FixedList worker; zen::ScopeGuard guardWorker = zen::makeGuard([&] { - for (boost::thread& wt : worker) + for (InterruptibleThread& wt : worker) wt.interrupt(); //interrupt all at once first, then join - for (boost::thread& wt : worker) + for (InterruptibleThread& wt : worker) if (wt.joinable()) //= precondition of thread::join(), which throws an exception if violated! wt.join(); //in this context it is possible a thread is *not* joinable anymore due to the thread::try_join_for() below! }); @@ -531,7 +525,7 @@ void zen::fillBuffer(const std::set& keysToRead, //in } //wait until done - for (boost::thread& wt : worker) + for (InterruptibleThread& wt : worker) { do { @@ -541,7 +535,7 @@ void zen::fillBuffer(const std::set& keysToRead, //in //process errors acb->processErrors(callback); } - while (!wt.try_join_for(boost::chrono::milliseconds(updateInterval))); + while (!wt.tryJoinFor(std::chrono::milliseconds(updateInterval))); acb->incrementNotifyingThreadId(); //process info messages of one thread at a time only } diff --git a/FreeFileSync/Source/lib/parallel_scan.h b/FreeFileSync/Source/lib/parallel_scan.h index 5a93b804..8a05522d 100644 --- a/FreeFileSync/Source/lib/parallel_scan.h +++ b/FreeFileSync/Source/lib/parallel_scan.h @@ -48,7 +48,7 @@ struct DirectoryValue { DirContainer dirCont; //relative names (or empty string for root) for directories that could not be read (completely), e.g. access denied, or temporal network drop - std::map failedDirReads; //with corresponding error message + std::map failedDirReads; //with corresponding error message //relative names (never empty) for failure to read single file/dir/symlink with corresponding error message std::map failedItemReads; diff --git a/FreeFileSync/Source/lib/parse_lng.h b/FreeFileSync/Source/lib/parse_lng.h index 92ad6929..a54d4683 100644 --- a/FreeFileSync/Source/lib/parse_lng.h +++ b/FreeFileSync/Source/lib/parse_lng.h @@ -25,7 +25,7 @@ namespace lngfile { //singular forms -typedef std::map TranslationMap; //orig |-> translation +typedef std::map TranslationMap; //orig |-> translation //plural forms typedef std::pair SingularPluralPair; //1 house| n houses diff --git a/FreeFileSync/Source/lib/process_xml.cpp b/FreeFileSync/Source/lib/process_xml.cpp index f90395f2..f303ecd0 100644 --- a/FreeFileSync/Source/lib/process_xml.cpp +++ b/FreeFileSync/Source/lib/process_xml.cpp @@ -801,8 +801,8 @@ void readConfig(const XmlIn& in, FilterConfig& filter) void readConfig(const XmlIn& in, FolderPairEnh& enhPair) { //read folder pairs - in["Left" ](enhPair.dirpathPhraseLeft); - in["Right"](enhPair.dirpathPhraseRight); + in["Left" ](enhPair.folderPathPhraseLeft_); + in["Right"](enhPair.folderPathPhraseRight_); //########################################################### //alternate comp configuration (optional) @@ -939,9 +939,17 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) inWnd.attribute("PosY", config.gui.dlgPos.y); inWnd.attribute("Maximized", config.gui.isMaximized); + XmlIn inCopyTo = inWnd["ManualCopyTo"]; + inCopyTo.attribute("KeepRelativePaths", config.gui.copyToCfg.keepRelPaths); + inCopyTo.attribute("OverwriteIfExists", config.gui.copyToCfg.overwriteIfExists); + + XmlIn inCopyToHistory = inCopyTo["FolderHistory"]; + inCopyToHistory(config.gui.copyToCfg.folderHistory); + inCopyToHistory.attribute("LastUsedPath" , config.gui.copyToCfg.lastUsedPath); + inCopyToHistory.attribute("MaxSize" , config.gui.copyToCfg.historySizeMax); + XmlIn inManualDel = inWnd["ManualDeletion"]; - //inManualDel.attribute("DeleteOnBothSides", config.gui.deleteOnBothSides); - inManualDel.attribute("UseRecycler" , config.gui.useRecyclerForManualDeletion); + inManualDel.attribute("UseRecycler", config.gui.manualDeletionUseRecycler); inWnd["CaseSensitiveSearch"].attribute("Enabled", config.gui.textSearchRespectCase); inWnd["FolderPairsVisible" ].attribute("Max", config.gui.maxFolderPairsVisible); @@ -992,11 +1000,6 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config) //external applications inGui["ExternalApplications"](config.gui.externelApplications); - warn_static("remove after migration: cleanup the old placeholder syntax") //26.10.2013 - if (std::any_of(config.gui.externelApplications.begin(), config.gui.externelApplications.end(), - [](const std::pair& ea) { return contains(ea.second, L"%name") || contains(ea.second, L"%nameCo") || contains(ea.second, L"%dir") || contains(ea.second, L"%dirCo"); })) - config.gui.externelApplications = XmlGlobalSettings().gui.externelApplications; - //last update check inGui["LastOnlineCheck" ](config.gui.lastUpdateCheck); inGui["LastOnlineVersion"](config.gui.lastOnlineVersion); @@ -1191,8 +1194,8 @@ void writeConfigFolderPair(const FolderPairEnh& enhPair, XmlOut& out) XmlOut outPair = out.ref().addChild("Pair"); //read folder pairs - outPair["Left" ](enhPair.dirpathPhraseLeft); - outPair["Right"](enhPair.dirpathPhraseRight); + outPair["Left" ](enhPair.folderPathPhraseLeft_); + outPair["Right"](enhPair.folderPathPhraseRight_); //########################################################### //alternate comp configuration (optional) @@ -1321,9 +1324,17 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out) outWnd.attribute("PosY", config.gui.dlgPos.y); outWnd.attribute("Maximized", config.gui.isMaximized); + XmlOut outCopyTo = outWnd["ManualCopyTo"]; + outCopyTo.attribute("KeepRelativePaths", config.gui.copyToCfg.keepRelPaths); + outCopyTo.attribute("OverwriteIfExists", config.gui.copyToCfg.overwriteIfExists); + + XmlOut outCopyToHistory = outCopyTo["FolderHistory"]; + outCopyToHistory(config.gui.copyToCfg.folderHistory); + outCopyToHistory.attribute("LastUsedPath" , config.gui.copyToCfg.lastUsedPath); + outCopyToHistory.attribute("MaxSize" , config.gui.copyToCfg.historySizeMax); + XmlOut outManualDel = outWnd["ManualDeletion"]; - //outManualDel.attribute("DeleteOnBothSides", config.gui.deleteOnBothSides); - outManualDel.attribute("UseRecycler" , config.gui.useRecyclerForManualDeletion); + outManualDel.attribute("UseRecycler", config.gui.manualDeletionUseRecycler); outWnd["CaseSensitiveSearch"].attribute("Enabled", config.gui.textSearchRespectCase); outWnd["FolderPairsVisible" ].attribute("Max", config.gui.maxFolderPairsVisible); diff --git a/FreeFileSync/Source/lib/process_xml.h b/FreeFileSync/Source/lib/process_xml.h index d37ca956..12d6ac44 100644 --- a/FreeFileSync/Source/lib/process_xml.h +++ b/FreeFileSync/Source/lib/process_xml.h @@ -156,7 +156,7 @@ struct XmlGlobalSettings int fileTimeTolerance; //max. allowed file time deviation; < 0 means unlimited tolerance bool runWithBackgroundPriority; bool createLockFile; - bool verifyFileCopy; //verify copied files + bool verifyFileCopy; //verify copied files size_t lastSyncsLogFileSizeMax; OptionalDialogs optDialogs; @@ -164,48 +164,7 @@ struct XmlGlobalSettings //--------------------------------------------------------------------- struct Gui { - Gui() : - dlgPos(wxDefaultCoord, wxDefaultCoord), - dlgSize(wxDefaultCoord, wxDefaultCoord), - isMaximized(false), - sashOffset(0), - maxFolderPairsVisible(6), - columnAttribNavi (zen::getDefaultColumnAttributesNavi()), - columnAttribLeft (zen::getDefaultColumnAttributesLeft()), - columnAttribRight(zen::getDefaultColumnAttributesRight()), - naviLastSortColumn(zen::defaultValueLastSortColumn), - naviLastSortAscending(zen::defaultValueLastSortAscending), - showPercentBar(zen::defaultValueShowPercentage), - cfgFileHistMax(30), - folderHistMax(15), - onCompletionHistoryMax(8), -#ifdef ZEN_WIN - defaultExclusionFilter(Zstr("\\System Volume Information\\") Zstr("\n") - Zstr("\\$Recycle.Bin\\") Zstr("\n") - Zstr("\\RECYCLER\\") Zstr("\n") - Zstr("\\RECYCLED\\") Zstr("\n") - Zstr("*\\desktop.ini") Zstr("\n") - Zstr("*\\thumbs.db")), -#elif defined ZEN_LINUX - defaultExclusionFilter(Zstr("/.Trash-*/") Zstr("\n") - Zstr("/.recycle/")), -#elif defined ZEN_MAC - defaultExclusionFilter(Zstr("/.fseventsd/") Zstr("\n") - Zstr("/.Spotlight-V100/") Zstr("\n") - Zstr("/.Trashes/") Zstr("\n") - Zstr("*/.DS_Store") Zstr("\n") - Zstr("*/._.*")), -#endif - //deleteOnBothSides(false), - useRecyclerForManualDeletion(true), //enable if OS supports it; else user will have to activate first and then get an error message -#if defined ZEN_WIN || defined ZEN_MAC - textSearchRespectCase(false), -#elif defined ZEN_LINUX - textSearchRespectCase(true), -#endif - showIcons(true), - iconSize(ICON_SIZE_SMALL), - lastUpdateCheck(0) + Gui() { //default external apps will be translated "on the fly"!!! //CONTRACT: first entry will be used for [Enter] or mouse double-click, second for open with default app! @@ -224,46 +183,73 @@ struct XmlGlobalSettings #endif } - wxPoint dlgPos; - wxSize dlgSize; - bool isMaximized; - int sashOffset; + wxPoint dlgPos { wxDefaultCoord, wxDefaultCoord }; + wxSize dlgSize { wxDefaultCoord, wxDefaultCoord }; + bool isMaximized = false; + int sashOffset = 0; - int maxFolderPairsVisible; + int maxFolderPairsVisible = 6; - std::vector columnAttribNavi; //compressed view/navigation - std::vector columnAttribLeft; - std::vector columnAttribRight; + std::vector columnAttribNavi = zen::getDefaultColumnAttributesNavi(); //compressed view/navigation + std::vector columnAttribLeft = zen::getDefaultColumnAttributesLeft(); + std::vector columnAttribRight = zen::getDefaultColumnAttributesRight(); - zen::ColumnTypeNavi naviLastSortColumn; //remember sort on navigation panel - bool naviLastSortAscending; // + zen::ColumnTypeNavi naviLastSortColumn = zen::defaultValueLastSortColumn; //remember sort on navigation panel + bool naviLastSortAscending = zen::defaultValueLastSortAscending; // - bool showPercentBar; //in navigation panel + bool showPercentBar = zen::defaultValueShowPercentage; //in navigation panel ExternalApps externelApplications; std::vector cfgFileHistory; - size_t cfgFileHistMax; + size_t cfgFileHistMax = 30; std::vector lastUsedConfigFiles; std::vector folderHistoryLeft; std::vector folderHistoryRight; - size_t folderHistMax; + size_t folderHistMax = 15; std::vector onCompletionHistory; - size_t onCompletionHistoryMax; + size_t onCompletionHistoryMax = 8; - Zstring defaultExclusionFilter; +#ifdef ZEN_WIN + Zstring defaultExclusionFilter = Zstr("\\System Volume Information\\") Zstr("\n") + Zstr("\\$Recycle.Bin\\") Zstr("\n") + Zstr("\\RECYCLER\\") Zstr("\n") + Zstr("\\RECYCLED\\") Zstr("\n") + Zstr("*\\desktop.ini") Zstr("\n") + Zstr("*\\thumbs.db"); +#elif defined ZEN_LINUX + Zstring defaultExclusionFilter = Zstr("/.Trash-*/") Zstr("\n") + Zstr("/.recycle/"); +#elif defined ZEN_MAC + Zstring defaultExclusionFilter = Zstr("/.fseventsd/") Zstr("\n") + Zstr("/.Spotlight-V100/") Zstr("\n") + Zstr("/.Trashes/") Zstr("\n") + Zstr("*/.DS_Store") Zstr("\n") + Zstr("*/._.*"); +#endif + struct + { + bool keepRelPaths = true; + bool overwriteIfExists = false; + Zstring lastUsedPath; + std::vector folderHistory; + size_t historySizeMax = 15; + } copyToCfg; - //bool deleteOnBothSides; - bool useRecyclerForManualDeletion; - bool textSearchRespectCase; + bool manualDeletionUseRecycler = true; - bool showIcons; - FileIconSize iconSize; +#if defined ZEN_WIN || defined ZEN_MAC + bool textSearchRespectCase = false; +#elif defined ZEN_LINUX + bool textSearchRespectCase = true; +#endif + bool showIcons = true; + FileIconSize iconSize = ICON_SIZE_SMALL; - long lastUpdateCheck; //time of last update check + long lastUpdateCheck = 0; //time of last update check wxString lastOnlineVersion; ViewFilterDefault viewFilterDefault; diff --git a/FreeFileSync/Source/lib/resolve_path.cpp b/FreeFileSync/Source/lib/resolve_path.cpp index 50f2b260..5cc51236 100644 --- a/FreeFileSync/Source/lib/resolve_path.cpp +++ b/FreeFileSync/Source/lib/resolve_path.cpp @@ -90,6 +90,9 @@ public: static const CsidlToDirMap& get() { +#if defined _MSC_VER && _MSC_VER < 1900 +#error function scope static initialization is not yet thread-safe! +#endif //function scope static initialization: avoid static initialization order problem in global namespace! static const CsidlToDirMap inst = createCsidlMapping(); return inst; @@ -117,9 +120,6 @@ private: //================================================================================================ //SHGetKnownFolderPath: API available only with Windows Vista and later: -#ifdef __MINGW32__ -#define KF_FLAG_DONT_VERIFY 0x00004000 -#endif typedef HRESULT (STDAPICALLTYPE* SHGetKnownFolderPathFunc)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR* ppszPath); const SysDllFun shGetKnownFolderPath(L"Shell32.dll", "SHGetKnownFolderPath"); @@ -202,12 +202,6 @@ private: return output; } }; - -//caveat: function scope static initialization is not thread-safe in VS 2010! -#if defined _MSC_VER && _MSC_VER > 1800 - #error get rid! -#endif -auto& dummy = CsidlConstants::get(); #endif @@ -511,9 +505,9 @@ void getDirectoryAliasesRecursive(const Zstring& dirpath, std::set zen::getDirectoryAliases(const Zstring& dirpathPhrase) +std::vector zen::getDirectoryAliases(const Zstring& folderPathPhrase) { - const Zstring dirpath = trimCpy(dirpathPhrase, true, false); + const Zstring dirpath = trimCpy(folderPathPhrase, true, false); if (dirpath.empty()) return std::vector(); @@ -528,9 +522,9 @@ std::vector zen::getDirectoryAliases(const Zstring& dirpathPhrase) //coordinate changes with acceptsFolderPathPhraseNative()! -Zstring zen::getResolvedDirectoryPath(const Zstring& dirpassPhrase) //noexcept +Zstring zen::getResolvedDirectoryPath(const Zstring& folderPathPhrase) //noexcept { - Zstring dirpath = dirpassPhrase; + Zstring dirpath = folderPathPhrase; dirpath = expandMacros(dirpath); //expand before trimming! diff --git a/FreeFileSync/Source/lib/resolve_path.h b/FreeFileSync/Source/lib/resolve_path.h index 7bfcfd1e..d7e65b00 100644 --- a/FreeFileSync/Source/lib/resolve_path.h +++ b/FreeFileSync/Source/lib/resolve_path.h @@ -21,12 +21,12 @@ namespace zen => may block for slow USB sticks and idle HDDs => not thread-safe, see ::GetFullPathName()! */ -Zstring getResolvedDirectoryPath(const Zstring& dirpassPhrase); //noexcept +Zstring getResolvedDirectoryPath(const Zstring& folderPathPhrase); //noexcept //macro substitution only Zstring expandMacros(const Zstring& text); -std::vector getDirectoryAliases(const Zstring& dirpassPhrase); //may block for slow USB sticks when resolving [] +std::vector getDirectoryAliases(const Zstring& folderPathPhrase); //may block for slow USB sticks when resolving [] #ifdef ZEN_WIN //*blocks* if network is not reachable or when showing login prompt dialog! diff --git a/FreeFileSync/Source/lib/status_handler.h b/FreeFileSync/Source/lib/status_handler.h index 6f90506c..554d8226 100644 --- a/FreeFileSync/Source/lib/status_handler.h +++ b/FreeFileSync/Source/lib/status_handler.h @@ -87,7 +87,7 @@ protected: { abortRequested = true; statusText_ = _("Stop requested: Waiting for current operation to finish..."); - } //called from GUI code: this does NOT call abortProcessNow() immediately, but when we're out of the C GUI call stack + } //called from GUI code: this does NOT call abortProcessNow() immediately, but later when we're out of the C GUI call stack //implement Statistics Phase currentPhase() const override { return currentPhase_; } diff --git a/FreeFileSync/Source/lib/status_handler_impl.h b/FreeFileSync/Source/lib/status_handler_impl.h index 145d02f8..18465a71 100644 --- a/FreeFileSync/Source/lib/status_handler_impl.h +++ b/FreeFileSync/Source/lib/status_handler_impl.h @@ -40,9 +40,6 @@ class StatisticsReporter { public: StatisticsReporter(int itemsExpected, std::int64_t bytesExpected, ProcessCallback& cb) : - taskCancelled(true), - itemsReported(), - bytesReported(), itemsExpected_(itemsExpected), bytesExpected_(bytesExpected), cb_(cb) {} @@ -51,6 +48,10 @@ public: { if (taskCancelled) cb_.updateTotalData(itemsReported, bytesReported); //=> unexpected increase of total workload + else + //update statistics to consider the real amount of data, e.g. more than the "file size" for ADS streams, + //less for sparse and compressed files, or file changed in the meantime! + cb_.updateTotalData(itemsReported - itemsExpected_, bytesReported - bytesExpected_); //noexcept! } void reportDelta(int itemsDelta, std::int64_t bytesDelta) //may throw! @@ -77,16 +78,13 @@ public: void reportFinished() //nothrow! { assert(taskCancelled); - //update statistics to consider the real amount of data, e.g. more than the "file size" for ADS streams, - //less for sparse and compressed files, or file changed in the meantime! - cb_.updateTotalData(itemsReported - itemsExpected_, bytesReported - bytesExpected_); //noexcept! taskCancelled = false; } private: - bool taskCancelled; - int itemsReported; - std::int64_t bytesReported; + bool taskCancelled = true; + int itemsReported = 0; + std::int64_t bytesReported = 0; const int itemsExpected_; const std::int64_t bytesExpected_; ProcessCallback& cb_; diff --git a/FreeFileSync/Source/lib/versioning.cpp b/FreeFileSync/Source/lib/versioning.cpp index 44a6e288..ea3ce43b 100644 --- a/FreeFileSync/Source/lib/versioning.cpp +++ b/FreeFileSync/Source/lib/versioning.cpp @@ -127,14 +127,22 @@ void moveItem(const AbstractPathRef& sourcePath, //throw FileError auto removeTarget = [&] { - //remove target object - if (ABF::dirExists(targetPath)) //directory or dir-symlink + try { - assert(false); //we do not expect targetPath to be a directory in general (but possible!) - ABF::removeFolderRecursively(targetPath, nullptr /*onBeforeFileDeletion*/, nullptr /*onBeforeFolderDeletion*/); //throw FileError - } - else //file or (broken) file-symlink + //file or (broken) file-symlink: ABF::removeFile(targetPath); //throw FileError + } + catch (FileError&) + { + //folder or folder-symlink: + if (ABF::folderExists(targetPath)) //directory or dir-symlink + { + assert(ABF::symlinkExists(targetPath)); //we do not expect targetPath to be a directory in general (but possible!) + ABF::removeFolderRecursively(targetPath, nullptr /*onBeforeFileDeletion*/, nullptr /*onBeforeFolderDeletion*/); //throw FileError + } + else + throw; + } }; //first try to move directly without copying @@ -143,7 +151,7 @@ void moveItem(const AbstractPathRef& sourcePath, //throw FileError ABF::renameItem(sourcePath, targetPath); //throw FileError, ErrorTargetExisting, ErrorDifferentVolume return; //great, we get away cheaply! } - //if moving failed treat as error (except when it tried to move to a different volume: in this case we will copy the file) + //if moving failed, treat as error (except when it tried to move to a different volume: in this case we will copy the file) catch (const ErrorDifferentVolume&) { removeTarget(); //throw FileError @@ -174,8 +182,8 @@ void moveFileOrSymlink(const AbstractPathRef& sourcePath, //throw FileError if (ABF::symlinkExists(sourcePath)) ABF::copySymlink(sourcePath, targetPath, false /*copy filesystem permissions*/); //throw FileError else - ABF::copyFileTransactional(sourcePath, targetPath, //throw FileError, (ErrorFileLocked) - false /*copyFilePermissions*/, true /*transactionalCopy*/, nullptr, onNotifyCopyStatus); + ABF::copyFileTransactional(sourcePath, targetPath, //throw FileError, ErrorFileLocked + false /*copyFilePermissions*/, true /*transactionalCopy*/, nullptr /*onDeleteTargetFile*/, onNotifyCopyStatus); ABF::removeFile(sourcePath); //throw FileError; newly copied file is NOT deleted if exception is thrown here! }; @@ -191,7 +199,7 @@ void moveFile(const AbstractPathRef& sourcePath, //throw FileError auto copyDelete = [&] { assert(!ABF::somethingExists(targetPath)); - ABF::copyFileTransactional(sourcePath, targetPath, //throw FileError, (ErrorFileLocked) + ABF::copyFileTransactional(sourcePath, targetPath, //throw FileError, ErrorFileLocked false /*copyFilePermissions*/, true /*transactionalCopy*/, nullptr /*onDeleteTargetFile*/, onNotifyCopyStatus); ABF::removeFile(sourcePath); //throw FileError; newly copied file is NOT deleted if exception is thrown here! }; @@ -231,7 +239,7 @@ struct FlatTraverserCallback: public ABF::TraverserCallback std::unique_ptr onDir (const DirInfo& di) override { folderNames_.push_back(di.shortName); return nullptr; } HandleLink onSymlink(const SymlinkInfo& si) override { - if (ABF::dirExists(ABF::appendRelPath(folderPath_, si.shortName))) //dir symlink + if (ABF::folderExists(ABF::appendRelPath(folderPath_, si.shortName))) //dir symlink folderLinkNames_.push_back(si.shortName); else //file symlink, broken symlink fileLinkNames_.push_back(si.shortName); @@ -299,7 +307,7 @@ void FileVersioner::revisionFolderImpl(const AbstractPathRef& folderPath, const const std::function& onNotifyCopyStatus) { assert(!ABF::symlinkExists(folderPath)); //[!] no symlinks in this context!!! - assert(ABF::dirExists(folderPath)); //Do NOT traverse into it deleting contained files!!! + assert(ABF::folderExists(folderPath)); //Do NOT traverse into it deleting contained files!!! //create target directories only when needed in moveFileToVersioning(): avoid empty directories! diff --git a/FreeFileSync/Source/structures.cpp b/FreeFileSync/Source/structures.cpp index 8db6bb00..28c2495e 100644 --- a/FreeFileSync/Source/structures.cpp +++ b/FreeFileSync/Source/structures.cpp @@ -391,8 +391,8 @@ FilterConfig mergeFilterConfig(const FilterConfig& global, const FilterConfig& l inline bool effectivelyEmpty(const FolderPairEnh& fp) { - return trimCpy(fp.dirpathPhraseLeft ).empty() && - trimCpy(fp.dirpathPhraseRight).empty(); + return trimCpy(fp.folderPathPhraseLeft_ ).empty() && + trimCpy(fp.folderPathPhraseRight_).empty(); } } diff --git a/FreeFileSync/Source/structures.h b/FreeFileSync/Source/structures.h index ac07c11a..f3cff19f 100644 --- a/FreeFileSync/Source/structures.h +++ b/FreeFileSync/Source/structures.h @@ -112,7 +112,7 @@ struct DirectionSet SyncDirection exLeftSideOnly; SyncDirection exRightSideOnly; - SyncDirection leftNewer; //CMP_BY_TIME_SIZE only! + SyncDirection leftNewer; //CMP_BY_TIME_SIZE only! SyncDirection rightNewer; // SyncDirection different; //CMP_BY_CONTENT only! SyncDirection conflict; @@ -335,19 +335,19 @@ struct FolderPairEnh //enhanced folder pairs with (optional) alternate configura { FolderPairEnh() {} - FolderPairEnh(const Zstring& phraseLeft, - const Zstring& phraseRight, + FolderPairEnh(const Zstring& folderPathPhraseLeft, + const Zstring& folderPathPhraseRight, const std::shared_ptr& cmpConfig, const std::shared_ptr& syncConfig, const FilterConfig& filter) : - dirpathPhraseLeft (phraseLeft), - dirpathPhraseRight(phraseRight), + folderPathPhraseLeft_ (folderPathPhraseLeft), + folderPathPhraseRight_(folderPathPhraseRight), altCmpConfig(cmpConfig), altSyncConfig(syncConfig), localFilter(filter) {} - Zstring dirpathPhraseLeft; //unresolved directory names as entered by user! - Zstring dirpathPhraseRight; // + Zstring folderPathPhraseLeft_; //unresolved directory names as entered by user! + Zstring folderPathPhraseRight_; // std::shared_ptr altCmpConfig; //optional std::shared_ptr altSyncConfig; // @@ -358,8 +358,8 @@ struct FolderPairEnh //enhanced folder pairs with (optional) alternate configura inline bool operator==(const FolderPairEnh& lhs, const FolderPairEnh& rhs) { - return lhs.dirpathPhraseLeft == rhs.dirpathPhraseLeft && - lhs.dirpathPhraseRight == rhs.dirpathPhraseRight && + return lhs.folderPathPhraseLeft_ == rhs.folderPathPhraseLeft_ && + lhs.folderPathPhraseRight_ == rhs.folderPathPhraseRight_ && (lhs.altCmpConfig.get() && rhs.altCmpConfig.get() ? *lhs.altCmpConfig == *rhs.altCmpConfig : diff --git a/FreeFileSync/Source/synchronization.cpp b/FreeFileSync/Source/synchronization.cpp index 501ef39f..0593294c 100644 --- a/FreeFileSync/Source/synchronization.cpp +++ b/FreeFileSync/Source/synchronization.cpp @@ -19,7 +19,8 @@ #include "lib/shadow.h" #elif defined ZEN_LINUX || defined ZEN_MAC - #include //open, close + #include //fsync + #include //open #endif using namespace zen; @@ -538,7 +539,7 @@ void DeletionHandling::removeFileWithCallback(const AbstractPathRef& filePath, template inline void DeletionHandling::removeLinkWithCallback(const AbstractPathRef& linkPath, const Zstring& relativePath, Function onNotifyItemDeletion, const std::function& onNotifyCopyStatus) //throw FileError { - if (ABF::dirExists(linkPath)) //dir symlink + if (ABF::folderExists(linkPath)) //dir symlink return removeDirWithCallback(linkPath, relativePath, onNotifyItemDeletion, onNotifyCopyStatus); //throw FileError else //file symlink, broken symlink return removeFileWithCallback(linkPath, relativePath, onNotifyItemDeletion, onNotifyCopyStatus); //throw FileError @@ -1531,7 +1532,7 @@ void SynchronizeFolderPair::synchronizeFolderInt(DirPair& dirObj, SyncOperation if (parentDir->isEmpty()) //BaseDirPair OTOH is always non-empty and existing in this context => else: fatal error in zen::synchronize() return; //if parent directory creation failed, there's no reason to show more errors! - warn_static("save this file access:") + warn_static("save this file access?") if (ABF::somethingExists(dirObj.getAbstractPath())) //do not check on type (symlink, file, folder) -> if there is a type change, FFS should error out! { const AbstractPathRef targetPath = dirObj.getABF().getAbstractPath(dirObj.getRelativePath()); @@ -1541,7 +1542,7 @@ void SynchronizeFolderPair::synchronizeFolderInt(DirPair& dirObj, SyncOperation { ABF::copyNewFolder(dirObj.getAbstractPath(), targetPath, copyFilePermissions_); //throw FileError } - catch (const FileError&) { if (!ABF::dirExists(targetPath)) throw; } + catch (const FileError&) { if (!ABF::folderExists(targetPath)) throw; } //update DirPair dirObj.setSyncedTo(dirObj.getItemName()); diff --git a/FreeFileSync/Source/ui/batch_config.cpp b/FreeFileSync/Source/ui/batch_config.cpp index 420e25db..4f65bd1e 100644 --- a/FreeFileSync/Source/ui/batch_config.cpp +++ b/FreeFileSync/Source/ui/batch_config.cpp @@ -83,7 +83,7 @@ BatchDialog::BatchDialog(wxWindow* parent, m_bitmapBatchJob->SetBitmap(getResourceImage(L"batch")); - logfileDir = make_unique(*m_panelLogfile, *m_buttonSelectLogfileDir, *m_bpButtonSelectSftp, *m_logfileDir); + logfileDir = make_unique(*m_panelLogfile, *m_buttonSelectLogfileDir, *m_bpButtonSelectSftp, *m_logfileDir, nullptr /*staticText*/, nullptr /*wxWindow*/); setConfig(batchCfg); diff --git a/FreeFileSync/Source/ui/batch_status_handler.cpp b/FreeFileSync/Source/ui/batch_status_handler.cpp index 0872e9c6..a58da82e 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.cpp +++ b/FreeFileSync/Source/ui/batch_status_handler.cpp @@ -288,7 +288,7 @@ BatchStatusHandler::~BatchStatusHandler() //notify to progressDlg that current process has ended if (abortIsRequested()) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events + progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events else if (totalErrors > 0) progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_ERROR, errorLog); else if (totalWarnings > 0) @@ -305,7 +305,7 @@ BatchStatusHandler::~BatchStatusHandler() while (progressDlg) { wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted -> not expected => main thread! + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } } } @@ -399,7 +399,7 @@ ProcessCallback::Response BatchStatusHandler::reportError(const std::wstring& er { reportStatus(_("Error") + L": " + _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", (1000 * automaticRetryDelay_ - i * UI_UPDATE_INTERVAL + 999) / 1000)); //integer round up - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } return ProcessCallback::RETRY; } @@ -502,7 +502,7 @@ void BatchStatusHandler::forceUiRefresh() void BatchStatusHandler::abortProcessNow() { requestAbortion(); //just make sure... - throw BatchAbortProcess(); //abort can be triggered by progressDlg + throw BatchAbortProcess(); //abort can be triggered by progressDlg } diff --git a/FreeFileSync/Source/ui/batch_status_handler.h b/FreeFileSync/Source/ui/batch_status_handler.h index 251875e4..b2ac7227 100644 --- a/FreeFileSync/Source/ui/batch_status_handler.h +++ b/FreeFileSync/Source/ui/batch_status_handler.h @@ -8,11 +8,9 @@ #define BATCH_STATUS_HANDLER_857390451451234566 #include -//#include #include #include "progress_indicator.h" #include "switch_to_gui.h" -//#include "../fs/concrete.h" #include "../lib/status_handler.h" #include "../lib/process_xml.h" #include "../lib/return_codes.h" diff --git a/FreeFileSync/Source/ui/check_version.cpp b/FreeFileSync/Source/ui/check_version.cpp index 716b8fdf..0cb63d6c 100644 --- a/FreeFileSync/Source/ui/check_version.cpp +++ b/FreeFileSync/Source/ui/check_version.cpp @@ -45,7 +45,7 @@ std::wstring getIso639Language() bufSize); //_In_ int cchData if (0 < rv && rv < bufSize) return buf; //MSDN: "This can be a 3-letter code for languages that don't have a 2-letter code"! - else assert(false); + assert(false); #endif const std::wstring localeName(wxLocale::GetLanguageCanonicalName(wxLocale::GetSystemLanguage())); if (localeName.empty()) @@ -66,7 +66,7 @@ std::wstring getIso3166Country() bufSize); //_In_ int cchData if (0 < rv && rv < bufSize) return buf; //MSDN: "This can also return a number, such as "029" for Caribbean."! - else assert(false); + assert(false); #endif const std::wstring localeName(wxLocale::GetLanguageCanonicalName(wxLocale::GetSystemLanguage())); if (localeName.empty()) diff --git a/FreeFileSync/Source/ui/custom_grid.cpp b/FreeFileSync/Source/ui/custom_grid.cpp index 32a84b96..11de7272 100644 --- a/FreeFileSync/Source/ui/custom_grid.cpp +++ b/FreeFileSync/Source/ui/custom_grid.cpp @@ -5,6 +5,7 @@ // ************************************************************************** #include "custom_grid.h" +#include #include #include #include @@ -517,28 +518,29 @@ private: const IconInfo ii = getIconInfo(row); - wxBitmap fileIcon = [&] + wxBitmap fileIcon; + switch (ii.type) { - switch (ii.type) - { - case IconInfo::FOLDER: - return iconMgr_->getGenericDirIcon(); - - case IconInfo::ICON_PATH: - if (Opt tmpIco = iconMgr_->refIconBuffer().retrieveFileIcon(ii.fsObj->template getAbstractPath())) - return *tmpIco; + case IconInfo::FOLDER: + fileIcon = iconMgr_->getGenericDirIcon(); + break; + case IconInfo::ICON_PATH: + if (Opt tmpIco = iconMgr_->refIconBuffer().retrieveFileIcon(ii.fsObj->template getAbstractPath())) + fileIcon = *tmpIco; + else + { setFailedLoad(row); //save status of failed icon load -> used for async. icon loading //falsify only! we want to avoid writing incorrect success values when only partially updating the DC, e.g. when scrolling, //see repaint behavior of ::ScrollWindow() function! - return iconMgr_->refIconBuffer().getIconByExtension(ii.fsObj->template getItemName()); //better than nothing - //return iconMgr_->getGenericFileIcon(); + fileIcon = iconMgr_->refIconBuffer().getIconByExtension(ii.fsObj->template getItemName()); //better than nothing + } + break; //return iconMgr_->getGenericFileIcon(); + + case IconInfo::EMPTY: + break; + } - case IconInfo::EMPTY: - break; - } - return wxBitmap(); - }(); if (fileIcon.IsOk()) { @@ -655,11 +657,11 @@ private: ICON_PATH, }; IconType type; - const FileSystemObject* fsObj; //only set if type != EMPTY + const FileSystemObject* fsObj; //only set if type != EMPTY bool drawAsLink; }; - IconInfo getIconInfo(size_t row) const //return ICON_FILE_FOLDER if row points to a folder + IconInfo getIconInfo(size_t row) const //return ICON_FILE_FOLDER if row points to a folder { IconInfo out = {}; diff --git a/FreeFileSync/Source/ui/folder_history_types.h b/FreeFileSync/Source/ui/folder_history_types.h index 768bc25c..ce7e5446 100644 --- a/FreeFileSync/Source/ui/folder_history_types.h +++ b/FreeFileSync/Source/ui/folder_history_types.h @@ -7,7 +7,6 @@ #ifndef FOLDER_HIST_TYPES_32481457137432143214 #define FOLDER_HIST_TYPES_32481457137432143214 -//#include #include diff --git a/FreeFileSync/Source/ui/folder_selector.cpp b/FreeFileSync/Source/ui/folder_selector.cpp index 09fd1c4d..3e0632af 100644 --- a/FreeFileSync/Source/ui/folder_selector.cpp +++ b/FreeFileSync/Source/ui/folder_selector.cpp @@ -26,23 +26,22 @@ using ABF = AbstractBaseFolder; namespace { -void setFolderPathPhrase(const Zstring& dirpath, FolderHistoryBox* comboBox, wxWindow& tooltipWnd, wxStaticText* staticText) //pointers are optional +void setFolderPathPhrase(const Zstring& folderPathPhrase, FolderHistoryBox* comboBox, wxWindow& tooltipWnd, wxStaticText* staticText) //pointers are optional { if (comboBox) - comboBox->setValue(toWx(dirpath)); + comboBox->setValue(toWx(folderPathPhrase)); - const Zstring folderPathPhrase = createAbstractBaseFolder(dirpath)->getInitPathPhrase(); //noexcept + const Zstring folderPathPhraseFmt = createAbstractBaseFolder(folderPathPhrase)->getInitPathPhrase(); //noexcept //may block when resolving [] tooltipWnd.SetToolTip(nullptr); //workaround wxComboBox bug http://trac.wxwidgets.org/ticket/10512 / http://trac.wxwidgets.org/ticket/12659 - tooltipWnd.SetToolTip(toWx(folderPathPhrase)); //who knows when the real bugfix reaches mere mortals via an official release... + tooltipWnd.SetToolTip(toWx(folderPathPhraseFmt)); //who knows when the real bugfix reaches mere mortals via an official release... if (staticText) { //change static box label only if there is a real difference to what is shown in wxTextCtrl anyway - const Zstring dirpathFmt = trimCpy(dirpath); - - staticText->SetLabel(EqualFilePath()(appendSeparator(dirpathFmt), appendSeparator(folderPathPhrase)) ? wxString(_("Drag && drop")) : toWx(folderPathPhrase)); + staticText->SetLabel(EqualFilePath()(appendSeparator(trimCpy(folderPathPhrase)), appendSeparator(folderPathPhraseFmt)) ? + wxString(_("Drag && drop")) : toWx(folderPathPhraseFmt)); } } @@ -74,22 +73,21 @@ bool onIFileDialogAcceptFolder(HWND wnd, const Zstring& shellFolderPath) //############################################################################################################## - -const wxEventType zen::EVENT_ON_DIR_SELECTED = wxNewEventType(); -const wxEventType zen::EVENT_ON_DIR_MANUAL_CORRECTION = wxNewEventType(); +const wxEventType zen::EVENT_ON_FOLDER_SELECTED = wxNewEventType(); +const wxEventType zen::EVENT_ON_FOLDER_MANUAL_EDIT = wxNewEventType(); -FolderSelector::FolderSelector(wxWindow& dropWindow, - wxButton& selectFolderButton, - wxButton& selectSftpButton, - FolderHistoryBox& dirpath, - wxStaticText* staticText, - wxWindow* dropWindow2) : +FolderSelector::FolderSelector(wxWindow& dropWindow, + wxButton& selectFolderButton, + wxButton& selectSftpButton, + FolderHistoryBox& folderComboBox, + wxStaticText* staticText, + wxWindow* dropWindow2) : dropWindow_(dropWindow), dropWindow2_(dropWindow2), selectFolderButton_(selectFolderButton), selectSftpButton_(selectSftpButton), - dirpath_(dirpath), + folderComboBox_(folderComboBox), staticText_(staticText) { auto setupDragDrop = [&](wxWindow& dropWin) @@ -105,7 +103,6 @@ FolderSelector::FolderSelector(wxWindow& dropWindow, setupDragDrop(dropWindow_); if (dropWindow2_) setupDragDrop(*dropWindow2_); - #ifdef ZEN_WIN_VISTA_AND_LATER selectSftpButton.SetBitmapLabel(getResourceImage(L"sftp_small")); #else @@ -113,10 +110,10 @@ FolderSelector::FolderSelector(wxWindow& dropWindow, #endif //keep dirPicker and dirpath synchronous - dirpath_ .Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector::onMouseWheel ), nullptr, this); - dirpath_ .Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector::onWriteDirManually), nullptr, this); - selectFolderButton_.Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectFolder ), nullptr, this); - selectSftpButton_ .Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectSftp ), nullptr, this); + folderComboBox_ .Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector::onMouseWheel ), nullptr, this); + folderComboBox_ .Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector::onEditFolderPath), nullptr, this); + selectFolderButton_.Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectFolder ), nullptr, this); + selectSftpButton_ .Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectSftp ), nullptr, this); } @@ -127,10 +124,10 @@ FolderSelector::~FolderSelector() if (dropWindow2_) dropWindow2_->Disconnect(EVENT_DROP_FILE, FileDropEventHandler(FolderSelector::onFilesDropped), nullptr, this); - dirpath_ .Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector::onMouseWheel ), nullptr, this); - dirpath_ .Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector::onWriteDirManually), nullptr, this); - selectFolderButton_.Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectFolder ), nullptr, this); - selectSftpButton_ .Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectSftp ), nullptr, this); + folderComboBox_ .Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (FolderSelector::onMouseWheel ), nullptr, this); + folderComboBox_ .Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FolderSelector::onEditFolderPath), nullptr, this); + selectFolderButton_.Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectFolder ), nullptr, this); + selectSftpButton_ .Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderSelector::onSelectSftp ), nullptr, this); } @@ -140,7 +137,7 @@ void FolderSelector::onMouseWheel(wxMouseEvent& event) //additionally this will delete manual entries, although all the users wanted is scroll the parent window! //redirect to parent scrolled window! - wxWindow* wnd = &dirpath_; + wxWindow* wnd = &folderComboBox_; while ((wnd = wnd->GetParent()) != nullptr) //silence MSVC warning if (dynamic_cast(wnd) != nullptr) if (wxEvtHandler* evtHandler = wnd->GetEventHandler()) @@ -154,36 +151,43 @@ void FolderSelector::onMouseWheel(wxMouseEvent& event) void FolderSelector::onFilesDropped(FileDropEvent& event) { - const auto& files = event.getFiles(); - if (files.empty()) + const auto& itemPaths = event.getPaths(); + if (itemPaths.empty()) return; - if (canSetDroppedShellPaths(files)) + if (canSetDroppedShellPaths(itemPaths)) { - Zstring newFolderPathPhrase = files[0]; - - if (!ABF::dirExists(createAbstractBaseFolder(files[0])->getAbstractPath())) + auto fmtShellPath = [](const Zstring& shellItemPath) { - Zstring parentPathPhrase = beforeLast(files[0], FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); - if (!parentPathPhrase.empty()) + std::unique_ptr abf = createAbstractBaseFolder(shellItemPath); + + if (!ABF::folderExists(abf->getAbstractPath())) { + Zstring parentShellPath = beforeLast(shellItemPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_NONE); + if (!parentShellPath.empty()) + { #ifdef ZEN_WIN - if (endsWith(parentPathPhrase, L":")) //volume root - parentPathPhrase += FILE_NAME_SEPARATOR; + if (endsWith(parentShellPath, L":")) //volume root + parentShellPath += FILE_NAME_SEPARATOR; #endif - if (ABF::dirExists(createAbstractBaseFolder(parentPathPhrase)->getAbstractPath())) - newFolderPathPhrase = parentPathPhrase; - //else: keep original name unconditionally: usecase: inactive mapped network shares - } - } + std::unique_ptr abfParent = createAbstractBaseFolder(parentShellPath); - //make sure FFS-specific explicit MTP-syntax is applied! - newFolderPathPhrase = createAbstractBaseFolder(newFolderPathPhrase)->getInitPathPhrase(); + if (ABF::folderExists(abfParent->getAbstractPath())) + return abfParent->getInitPathPhrase(); + //else: keep original name unconditionally: usecase: inactive mapped network shares + } + } + //make sure FFS-specific explicit MTP-syntax is applied! + return abf->getInitPathPhrase(); + }; - setFolderPathPhrase(newFolderPathPhrase, &dirpath_, dirpath_, staticText_); + setPath(fmtShellPath(itemPaths[0])); + //drop two folder paths at once: + if (siblingSelector && itemPaths.size() >= 2) + siblingSelector->setPath(fmtShellPath(itemPaths[1])); //notify action invoked by user - wxCommandEvent dummy(EVENT_ON_DIR_SELECTED); + wxCommandEvent dummy(EVENT_ON_FOLDER_SELECTED); ProcessEvent(dummy); } else @@ -191,11 +195,11 @@ void FolderSelector::onFilesDropped(FileDropEvent& event) } -void FolderSelector::onWriteDirManually(wxCommandEvent& event) +void FolderSelector::onEditFolderPath(wxCommandEvent& event) { - setFolderPathPhrase(toZ(event.GetString()), nullptr, dirpath_, staticText_); + setFolderPathPhrase(toZ(event.GetString()), nullptr, folderComboBox_, staticText_); - wxCommandEvent dummy(EVENT_ON_DIR_MANUAL_CORRECTION); + wxCommandEvent dummy(EVENT_ON_FOLDER_MANUAL_EDIT); ProcessEvent(dummy); event.Skip(); } @@ -211,7 +215,8 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event) { auto baseFolderExisting = [](const ABF& abf) { - std::function /*throw FileError*/ dirExists = ABF::getAsyncCheckDirExists(abf.getAbstractPath()); //noexcept + std::function /*throw FileError*/ dirExists = ABF::getAsyncCheckFolderExists(abf.getAbstractPath()); //noexcept + auto ft = runAsync([dirExists] { try @@ -220,7 +225,7 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event) } catch (FileError&) { return false; } }); - return ft.wait_for(boost::chrono::milliseconds(200)) == boost::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most + return ft.wait_for(std::chrono::milliseconds(200)) == std::future_status::ready && ft.get(); //potentially slow network access: wait 200ms at most }; const Zstring folderPathPhrase = getPath(); @@ -268,10 +273,10 @@ void FolderSelector::onSelectFolder(wxCommandEvent& event) const Zstring newFolderPathPhrase = toZ(dirPicker.GetPath()); #endif - setFolderPathPhrase(newFolderPathPhrase, &dirpath_, dirpath_, staticText_); + setFolderPathPhrase(newFolderPathPhrase, &folderComboBox_, folderComboBox_, staticText_); //notify action invoked by user - wxCommandEvent dummy(EVENT_ON_DIR_SELECTED); + wxCommandEvent dummy(EVENT_ON_FOLDER_SELECTED); ProcessEvent(dummy); } @@ -283,10 +288,10 @@ void FolderSelector::onSelectSftp(wxCommandEvent& event) if (showSftpSetupDialog(&selectSftpButton_, folderPathPhrase) != ReturnSmallDlg::BUTTON_OKAY) return; - setFolderPathPhrase(folderPathPhrase, &dirpath_, dirpath_, staticText_); + setFolderPathPhrase(folderPathPhrase, &folderComboBox_, folderComboBox_, staticText_); //notify action invoked by user - wxCommandEvent dummy(EVENT_ON_DIR_SELECTED); + wxCommandEvent dummy(EVENT_ON_FOLDER_SELECTED); ProcessEvent(dummy); #endif } @@ -294,11 +299,11 @@ void FolderSelector::onSelectSftp(wxCommandEvent& event) Zstring FolderSelector::getPath() const { - return toZ(dirpath_.GetValue()); + return toZ(folderComboBox_.GetValue()); } -void FolderSelector::setPath(const Zstring& dirpath) +void FolderSelector::setPath(const Zstring& folderPathPhrase) { - setFolderPathPhrase(dirpath, &dirpath_, dirpath_, staticText_); + setFolderPathPhrase(folderPathPhrase, &folderComboBox_, folderComboBox_, staticText_); } diff --git a/FreeFileSync/Source/ui/folder_selector.h b/FreeFileSync/Source/ui/folder_selector.h index 243a498a..3cb0b986 100644 --- a/FreeFileSync/Source/ui/folder_selector.h +++ b/FreeFileSync/Source/ui/folder_selector.h @@ -24,40 +24,43 @@ Reasons NOT to use wxDirPickerCtrl, but wxButton instead: - hard-codes "Browse" button label */ -extern const wxEventType EVENT_ON_DIR_SELECTED; //directory is changed by the user (except manual type-in) -extern const wxEventType EVENT_ON_DIR_MANUAL_CORRECTION; //manual type-in -//example: wnd.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MyDlg::OnDirSelected), nullptr, this); +extern const wxEventType EVENT_ON_FOLDER_SELECTED; //directory is changed by the user (except manual type-in) +extern const wxEventType EVENT_ON_FOLDER_MANUAL_EDIT; //manual type-in +//example: wnd.Connect(EVENT_ON_FOLDER_SELECTED, wxCommandEventHandler(MyDlg::OnDirSelected), nullptr, this); class FolderSelector: public wxEvtHandler { public: - FolderSelector(wxWindow& dropWindow, - wxButton& selectFolderButton, - wxButton& selectSftpButton, - FolderHistoryBox& dirpath, - wxStaticText* staticText = nullptr, //optional - wxWindow* dropWindow2 = nullptr); // + FolderSelector(wxWindow& dropWindow, + wxButton& selectFolderButton, + wxButton& selectSftpButton, + FolderHistoryBox& folderComboBox, + wxStaticText* staticText, //optional + wxWindow* dropWindow2); // ~FolderSelector(); + void setSiblingSelector(FolderSelector* selector) { siblingSelector = selector; } + Zstring getPath() const; - void setPath(const Zstring& dirpath); + void setPath(const Zstring& folderPathPhrase); private: virtual bool canSetDroppedShellPaths(const std::vector& shellItemPaths) { return true; }; //return true if drop should be processed - void onMouseWheel (wxMouseEvent& event); - void onFilesDropped (FileDropEvent& event); - void onWriteDirManually(wxCommandEvent& event); - void onSelectFolder (wxCommandEvent& event); - void onSelectSftp (wxCommandEvent& event); + void onMouseWheel (wxMouseEvent& event); + void onFilesDropped (FileDropEvent& event); + void onEditFolderPath(wxCommandEvent& event); + void onSelectFolder (wxCommandEvent& event); + void onSelectSftp (wxCommandEvent& event); - wxWindow& dropWindow_; - wxWindow* dropWindow2_; - wxButton& selectFolderButton_; - wxButton& selectSftpButton_; - FolderHistoryBox& dirpath_; - wxStaticText* staticText_; //optional + wxWindow& dropWindow_; + wxWindow* dropWindow2_ = nullptr; + wxButton& selectFolderButton_; + wxButton& selectSftpButton_; + FolderHistoryBox& folderComboBox_; + wxStaticText* staticText_ = nullptr; //optional + FolderSelector* siblingSelector = nullptr; }; } diff --git a/FreeFileSync/Source/ui/grid_view.cpp b/FreeFileSync/Source/ui/grid_view.cpp index a34d42c4..51c7c711 100644 --- a/FreeFileSync/Source/ui/grid_view.cpp +++ b/FreeFileSync/Source/ui/grid_view.cpp @@ -281,17 +281,17 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool showExcluded, //map } -std::vector GridView::getAllFileRef(const std::set& rows) +std::vector GridView::getAllFileRef(const std::vector& rows) { + const size_t viewSize = viewRef.size(); + std::vector output; - auto iterLast = rows.lower_bound(rowsOnView()); //loop over valid rows only! - std::for_each(rows.begin(), iterLast, - [&](size_t pos) - { - if (FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos])) - output.push_back(fsObj); - }); + for (size_t pos : rows) + if (pos < viewSize) + if (FileSystemObject* fsObj = FileSystemObject::retrieve(viewRef[pos])) + output.push_back(fsObj); + return output; } diff --git a/FreeFileSync/Source/ui/grid_view.h b/FreeFileSync/Source/ui/grid_view.h index 3ee2f642..5a2fb293 100644 --- a/FreeFileSync/Source/ui/grid_view.h +++ b/FreeFileSync/Source/ui/grid_view.h @@ -7,7 +7,7 @@ #ifndef GRIDVIEW_H_INCLUDED #define GRIDVIEW_H_INCLUDED -#include +#include #include #include "column_attr.h" #include "../file_hierarchy.h" @@ -22,14 +22,14 @@ public: GridView() : folderPairCount(0) {} //direct data access via row number - const FileSystemObject* getObject(size_t row) const; //returns nullptr if object is not found; complexity: constant! + const FileSystemObject* getObject(size_t row) const; //returns nullptr if object is not found; complexity: constant! /**/ FileSystemObject* getObject(size_t row); // size_t rowsOnView() const { return viewRef .size(); } //only visible elements size_t rowsTotal () const { return sortedRef.size(); } //total rows available //get references to FileSystemObject: no nullptr-check needed! Everything's bound. - std::vector getAllFileRef(const std::set& rows); + std::vector getAllFileRef(const std::vector& rows); struct StatusCmpResult { @@ -141,7 +141,7 @@ private: std::unordered_map rowPositionsFirstChild; //find first child on sortedRef of a hierarchy object //void* instead of HierarchyObject*: these are weak pointers and should *never be dereferenced*! - std::vector viewRef; //partial view on sortedRef + std::vector viewRef; //partial view on sortedRef /* /|\ | (update...) | */ diff --git a/FreeFileSync/Source/ui/gui_generated.cpp b/FreeFileSync/Source/ui/gui_generated.cpp index a5b0f856..5cd7df3a 100644 --- a/FreeFileSync/Source/ui/gui_generated.cpp +++ b/FreeFileSync/Source/ui/gui_generated.cpp @@ -71,7 +71,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_menubar1->Append( m_menu4, _("&Actions") ); m_menuTools = new wxMenu(); - m_menuItemOptions = new wxMenuItem( m_menuTools, wxID_PREFERENCES, wxString( _("&Options") ) , wxEmptyString, wxITEM_NORMAL ); + m_menuItemOptions = new wxMenuItem( m_menuTools, wxID_PREFERENCES, wxString( _("&Preferences") ) + wxT('\t') + wxT("Ctrl+,"), wxEmptyString, wxITEM_NORMAL ); m_menuTools->Append( m_menuItemOptions ); m_menuLanguages = new wxMenu(); @@ -1858,48 +1858,61 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c m_staticText12311 = new wxStaticText( m_panel41, wxID_ANY, _("Server name or IP address:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText12311->Wrap( -1 ); - fgSizer16->Add( m_staticText12311, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + fgSizer16->Add( m_staticText12311, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 300,-1 ), 0 ); - fgSizer16->Add( m_textCtrlServer, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bSizer183; + bSizer183 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText1381 = new wxStaticText( m_panel41, wxID_ANY, _("Examples:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1381->Wrap( -1 ); - m_staticText1381->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + m_textCtrlServer = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 260,-1 ), 0 ); + bSizer183->Add( m_textCtrlServer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText1233 = new wxStaticText( m_panel41, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1233->Wrap( -1 ); + bSizer183->Add( m_staticText1233, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxTOP|wxBOTTOM|wxLEFT, 5 ); - fgSizer16->Add( m_staticText1381, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + m_textCtrlPort = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), 0 ); + bSizer183->Add( m_textCtrlPort, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + fgSizer16->Add( bSizer183, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + fgSizer16->Add( 0, 0, 0, 0, 5 ); wxBoxSizer* bSizer181; bSizer181 = new wxBoxSizer( wxHORIZONTAL ); + m_staticText1381 = new wxStaticText( m_panel41, wxID_ANY, _("Examples:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1381->Wrap( -1 ); + m_staticText1381->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + + bSizer181->Add( m_staticText1381, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxBOTTOM|wxRIGHT, 5 ); + m_staticText1382 = new wxStaticText( m_panel41, wxID_ANY, _("www.website.com"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText1382->Wrap( -1 ); m_staticText1382->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer181->Add( m_staticText1382, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer181->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer181->Add( m_staticText1382, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); m_staticText138 = new wxStaticText( m_panel41, wxID_ANY, _("123.123.123"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText138->Wrap( -1 ); m_staticText138->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - bSizer181->Add( m_staticText138, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer181->Add( m_staticText138, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - fgSizer16->Add( bSizer181, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + fgSizer16->Add( bSizer181, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); m_staticText123 = new wxStaticText( m_panel41, wxID_ANY, _("User name:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText123->Wrap( -1 ); - fgSizer16->Add( m_staticText123, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + fgSizer16->Add( m_staticText123, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); m_textCtrlUserName = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); fgSizer16->Add( m_textCtrlUserName, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); m_staticText1231 = new wxStaticText( m_panel41, wxID_ANY, _("Password:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText1231->Wrap( -1 ); - fgSizer16->Add( m_staticText1231, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxRIGHT|wxLEFT, 5 ); + fgSizer16->Add( m_staticText1231, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 ); wxBoxSizer* bSizer182; bSizer182 = new wxBoxSizer( wxVERTICAL ); @@ -1921,13 +1934,13 @@ SftpSetupDlgGenerated::SftpSetupDlgGenerated( wxWindow* parent, wxWindowID id, c m_staticText1232 = new wxStaticText( m_panel41, wxID_ANY, _("Directory on server:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText1232->Wrap( -1 ); - fgSizer16->Add( m_staticText1232, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + fgSizer16->Add( m_staticText1232, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5 ); m_textCtrlServerPath = new wxTextCtrl( m_panel41, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); fgSizer16->Add( m_textCtrlServerPath, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer185->Add( fgSizer16, 1, wxALL|wxEXPAND, 5 ); + bSizer185->Add( fgSizer16, 0, wxALL, 5 ); m_panel41->SetSizer( bSizer185 ); @@ -3048,6 +3061,120 @@ DeleteDlgGenerated::~DeleteDlgGenerated() { } +CopyToDlgGenerated::CopyToDlgGenerated( 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( -1,-1 ), wxDefaultSize ); + this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapCopyTo = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer72->Add( m_bitmapCopyTo, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 10 ); + + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0|wxNO_BORDER ); + m_staticTextHeader->Wrap( 460 ); + bSizer72->Add( m_staticTextHeader, 0, wxALIGN_CENTER_VERTICAL|wxALL, 10 ); + + + bSizer24->Add( bSizer72, 0, 0, 5 ); + + m_staticline91 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline91, 0, wxEXPAND, 5 ); + + m_panel31 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel31->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + wxBoxSizer* bSizer185; + bSizer185 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer185->Add( 60, 0, 0, 0, 5 ); + + m_staticline42 = new wxStaticLine( m_panel31, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer185->Add( m_staticline42, 0, wxEXPAND, 5 ); + + m_textCtrlFileList = new wxTextCtrl( m_panel31, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 500,200 ), wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER ); + bSizer185->Add( m_textCtrlFileList, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + + m_panel31->SetSizer( bSizer185 ); + m_panel31->Layout(); + bSizer185->Fit( m_panel31 ); + bSizer24->Add( m_panel31, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer182; + bSizer182 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryTarget = new FolderHistoryBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + bSizer182->Add( m_directoryTarget, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonSelectFolder = new wxButton( this, wxID_ANY, _("Browse"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonSelectFolder->SetToolTip( _("Select a folder") ); + + bSizer182->Add( m_buttonSelectFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSelectSftp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 26,-1 ), wxBU_AUTODRAW ); + m_bpButtonSelectSftp->SetToolTip( _("Select SFTP folder") ); + + bSizer182->Add( m_bpButtonSelectSftp, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + + bSizer24->Add( bSizer182, 0, wxEXPAND|wxALL, 5 ); + + m_staticline9 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer24->Add( m_staticline9, 0, wxEXPAND, 5 ); + + bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer189; + bSizer189 = new wxBoxSizer( wxVERTICAL ); + + m_checkBoxKeepRelPath = new wxCheckBox( this, wxID_ANY, _("&Keep relative paths"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxKeepRelPath->SetValue(true); + bSizer189->Add( m_checkBoxKeepRelPath, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 ); + + m_checkBoxOverwriteIfExists = new wxCheckBox( this, wxID_ANY, _("&Overwrite existing files"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxOverwriteIfExists->SetValue(true); + bSizer189->Add( m_checkBoxOverwriteIfExists, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + + bSizerStdButtons->Add( bSizer189, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonOK = new wxButton( this, wxID_OK, _("&Copy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOK->SetDefault(); + m_buttonOK->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, false, wxEmptyString ) ); + + bSizerStdButtons->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 ); + + + bSizer24->Add( bSizerStdButtons, 0, wxEXPAND, 5 ); + + + this->SetSizer( bSizer24 ); + this->Layout(); + bSizer24->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CopyToDlgGenerated::OnClose ) ); + m_checkBoxKeepRelPath->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::OnUseRecycler ), NULL, this ); + m_checkBoxOverwriteIfExists->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::OnUseRecycler ), NULL, this ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::OnOK ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CopyToDlgGenerated::OnCancel ), NULL, this ); +} + +CopyToDlgGenerated::~CopyToDlgGenerated() +{ +} + OptionsDlgGenerated::OptionsDlgGenerated( 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( -1,-1 ), wxDefaultSize ); @@ -3436,18 +3563,6 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer171->Add( m_hyperlink11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink9 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("MinGW"), wxT("http://www.mingw.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink9->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink9->SetToolTip( _("http://www.mingw.org") ); - - bSizer171->Add( m_hyperlink9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink10 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Code::Blocks"), wxT("http://www.codeblocks.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink10->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink10->SetToolTip( _("http://www.codeblocks.org") ); - - bSizer171->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink7 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("wxWidgets"), wxT("http://www.wxwidgets.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink7->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); m_hyperlink7->SetToolTip( _("http://www.wxwidgets.org") ); @@ -3458,7 +3573,13 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_hyperlink14->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); m_hyperlink14->SetToolTip( _("http://wxformbuilder.org") ); - bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer171->Add( m_hyperlink14, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink16 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink16->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink16->SetToolTip( _("http://astyle.sourceforge.net") ); + + bSizer171->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL, 5 ); bSizer187->Add( bSizer171, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); @@ -3472,29 +3593,35 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer172->Add( m_hyperlink15, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_hyperlink12 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Google Test"), wxT("http://code.google.com/p/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink12->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink12->SetToolTip( _("http://code.google.com/p/googletest") ); + + bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + m_hyperlink13 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Boost"), wxT("http://www.boost.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink13->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); m_hyperlink13->SetToolTip( _("http://www.boost.org") ); bSizer172->Add( m_hyperlink13, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink16 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Artistic Style"), wxT("http://astyle.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink16->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink16->SetToolTip( _("http://astyle.sourceforge.net") ); + m_hyperlink10 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("libssh2"), wxT("http://www.libssh2.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink10->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink10->SetToolTip( _("http://www.libssh2.org") ); - bSizer172->Add( m_hyperlink16, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer172->Add( m_hyperlink10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink12 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Google Test"), wxT("http://code.google.com/p/googletest"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink12->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink12->SetToolTip( _("http://code.google.com/p/googletest") ); + m_hyperlink18 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("NSIS"), wxT("http://nsis.sourceforge.net"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink18->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink18->SetToolTip( _("http://nsis.sourceforge.net") ); - bSizer172->Add( m_hyperlink12, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - m_hyperlink18 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Unicode NSIS"), wxT("http://www.scratchpaper.com"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink18->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_hyperlink18->SetToolTip( _("http://www.scratchpaper.com") ); + m_hyperlink9 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("Inno Setup"), wxT("http://www.jrsoftware.org"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink9->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink9->SetToolTip( _("http://www.jrsoftware.org") ); - bSizer172->Add( m_hyperlink18, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer172->Add( m_hyperlink9, 0, wxALIGN_CENTER_VERTICAL, 5 ); bSizer187->Add( bSizer172, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); @@ -3575,6 +3702,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_hyperlink1 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("FreeFileSync.org"), wxT("http://www.freefilesync.org/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink1->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, true, wxEmptyString ) ); m_hyperlink1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink1->SetToolTip( _("http://www.freefilesync.org") ); bSizer166->Add( m_hyperlink1, 0, wxALIGN_CENTER_VERTICAL, 5 ); @@ -3589,6 +3717,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_hyperlink2 = new wxHyperlinkCtrl( m_panel41, wxID_ANY, _("zenju@gmx.de"), wxT("mailto:zenju@gmx.de"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); m_hyperlink2->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 92, true, wxEmptyString ) ); m_hyperlink2->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_hyperlink2->SetToolTip( _("mailto:zenju@gmx.de") ); bSizer166->Add( m_hyperlink2, 0, wxALIGN_CENTER_VERTICAL, 5 ); diff --git a/FreeFileSync/Source/ui/gui_generated.h b/FreeFileSync/Source/ui/gui_generated.h index bc69b713..b1fd8228 100644 --- a/FreeFileSync/Source/ui/gui_generated.h +++ b/FreeFileSync/Source/ui/gui_generated.h @@ -435,6 +435,8 @@ protected: wxPanel* m_panel41; wxStaticText* m_staticText12311; wxTextCtrl* m_textCtrlServer; + wxStaticText* m_staticText1233; + wxTextCtrl* m_textCtrlPort; wxStaticText* m_staticText1381; wxStaticText* m_staticText1382; wxStaticText* m_staticText138; @@ -737,6 +739,44 @@ public: }; +/////////////////////////////////////////////////////////////////////////////// +/// Class CopyToDlgGenerated +/////////////////////////////////////////////////////////////////////////////// +class CopyToDlgGenerated : public wxDialog +{ +private: + +protected: + wxStaticBitmap* m_bitmapCopyTo; + wxStaticText* m_staticTextHeader; + wxStaticLine* m_staticline91; + wxPanel* m_panel31; + wxStaticLine* m_staticline42; + wxTextCtrl* m_textCtrlFileList; + wxButton* m_buttonSelectFolder; + wxStaticLine* m_staticline9; + wxBoxSizer* bSizerStdButtons; + wxCheckBox* m_checkBoxKeepRelPath; + wxCheckBox* m_checkBoxOverwriteIfExists; + wxButton* m_buttonOK; + wxButton* m_buttonCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } + virtual void OnUseRecycler( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOK( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } + + +public: + FolderHistoryBox* m_directoryTarget; + wxBitmapButton* m_bpButtonSelectSftp; + + CopyToDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Copy items"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER ); + ~CopyToDlgGenerated(); + +}; + /////////////////////////////////////////////////////////////////////////////// /// Class OptionsDlgGenerated /////////////////////////////////////////////////////////////////////////////// @@ -858,15 +898,15 @@ protected: wxStaticLine* m_staticline341; wxStaticText* m_staticText96; wxHyperlinkCtrl* m_hyperlink11; - wxHyperlinkCtrl* m_hyperlink9; - wxHyperlinkCtrl* m_hyperlink10; wxHyperlinkCtrl* m_hyperlink7; wxHyperlinkCtrl* m_hyperlink14; - wxHyperlinkCtrl* m_hyperlink15; - wxHyperlinkCtrl* m_hyperlink13; wxHyperlinkCtrl* m_hyperlink16; + wxHyperlinkCtrl* m_hyperlink15; wxHyperlinkCtrl* m_hyperlink12; + wxHyperlinkCtrl* m_hyperlink13; + wxHyperlinkCtrl* m_hyperlink10; wxHyperlinkCtrl* m_hyperlink18; + wxHyperlinkCtrl* m_hyperlink9; wxPanel* m_panelDonate; wxPanel* m_panel39; wxStaticBitmap* m_bitmapDonate; diff --git a/FreeFileSync/Source/ui/gui_status_handler.cpp b/FreeFileSync/Source/ui/gui_status_handler.cpp index fcaeff50..2502788b 100644 --- a/FreeFileSync/Source/ui/gui_status_handler.cpp +++ b/FreeFileSync/Source/ui/gui_status_handler.cpp @@ -20,7 +20,7 @@ using namespace zen; using namespace xmlAccess; -CompareStatusHandler::CompareStatusHandler(MainDialog& dlg) : +StatusHandlerTemporaryPanel::StatusHandlerTemporaryPanel(MainDialog& dlg) : mainDlg(dlg), ignoreErrors(false) { @@ -28,7 +28,6 @@ CompareStatusHandler::CompareStatusHandler(MainDialog& dlg) : #ifdef ZEN_WIN wxWindowUpdateLocker dummy(&mainDlg); //leads to GUI corruption problems on Linux/OS X! #endif - mainDlg.compareStatus->init(*this); //clear old values before showing panel //------------------------------------------------------------------ @@ -92,16 +91,16 @@ CompareStatusHandler::CompareStatusHandler(MainDialog& dlg) : mainDlg.Update(); //don't wait until idle event! //register keys - mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this); + mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StatusHandlerTemporaryPanel::OnKeyPressed), nullptr, this); + mainDlg.m_buttonCancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusHandlerTemporaryPanel::OnAbortCompare), nullptr, this); } -CompareStatusHandler::~CompareStatusHandler() +StatusHandlerTemporaryPanel::~StatusHandlerTemporaryPanel() { //unregister keys - mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(CompareStatusHandler::OnAbortCompare), nullptr, this); + mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StatusHandlerTemporaryPanel::OnKeyPressed), nullptr, this); + mainDlg.m_buttonCancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusHandlerTemporaryPanel::OnAbortCompare), nullptr, this); mainDlg.auiMgr.GetPane(mainDlg.compareStatus->getAsWindow()).Hide(); mainDlg.auiMgr.Update(); @@ -109,7 +108,7 @@ CompareStatusHandler::~CompareStatusHandler() } -void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) +void StatusHandlerTemporaryPanel::OnKeyPressed(wxKeyEvent& event) { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) @@ -122,17 +121,17 @@ void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) } -void CompareStatusHandler::initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) +void StatusHandlerTemporaryPanel::initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) { StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID); switch (currentPhase()) { case PHASE_NONE: - case PHASE_SYNCHRONIZING: assert(false); case PHASE_SCANNING: break; + case PHASE_SYNCHRONIZING: case PHASE_COMPARING_CONTENT: { #ifdef ZEN_WIN @@ -149,7 +148,7 @@ void CompareStatusHandler::initNewPhase(int objectsTotal, std::int64_t dataTotal } -ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& errorMessage, size_t retryNumber) +ProcessCallback::Response StatusHandlerTemporaryPanel::reportError(const std::wstring& errorMessage, size_t retryNumber) { //no need to implement auto-retry here: 1. user is watching 2. comparison is fast //=> similar behavior like "ignoreErrors" which does not honor sync settings @@ -182,14 +181,14 @@ ProcessCallback::Response CompareStatusHandler::reportError(const std::wstring& } -void CompareStatusHandler::reportFatalError(const std::wstring& errorMessage) +void StatusHandlerTemporaryPanel::reportFatalError(const std::wstring& errorMessage) { forceUiRefresh(); showNotificationDialog(&mainDlg, DialogInfoType::ERROR2, PopupDialogCfg().setTitle(_("Serious Error")).setDetailInstructions(errorMessage)); } -void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) +void StatusHandlerTemporaryPanel::reportWarning(const std::wstring& warningMessage, bool& warningActive) { if (!warningActive || ignoreErrors) //if errors are ignored, then warnings should also return; @@ -213,19 +212,19 @@ void CompareStatusHandler::reportWarning(const std::wstring& warningMessage, boo } -void CompareStatusHandler::forceUiRefresh() +void StatusHandlerTemporaryPanel::forceUiRefresh() { mainDlg.compareStatus->updateStatusPanelNow(); } -void CompareStatusHandler::OnAbortCompare(wxCommandEvent& event) +void StatusHandlerTemporaryPanel::OnAbortCompare(wxCommandEvent& event) { requestAbortion(); } -void CompareStatusHandler::abortProcessNow() +void StatusHandlerTemporaryPanel::abortProcessNow() { requestAbortion(); //just make sure... throw GuiAbortProcess(); @@ -233,14 +232,14 @@ void CompareStatusHandler::abortProcessNow() //######################################################################################################## -SyncStatusHandler::SyncStatusHandler(wxFrame* parentDlg, - size_t lastSyncsLogFileSizeMax, - OnGuiError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const std::wstring& jobName, - const Zstring& onCompletion, - std::vector& onCompletionHistory) : +StatusHandlerFloatingDialog::StatusHandlerFloatingDialog(wxFrame* parentDlg, + size_t lastSyncsLogFileSizeMax, + OnGuiError handleError, + size_t automaticRetryCount, + size_t automaticRetryDelay, + const std::wstring& jobName, + const Zstring& onCompletion, + std::vector& onCompletionHistory) : progressDlg(createProgressDialog(*this, [this] { this->onProgressDialogTerminate(); }, *this, parentDlg, true, jobName, onCompletion, onCompletionHistory)), lastSyncsLogFileSizeMax_(lastSyncsLogFileSizeMax), handleError_(handleError), @@ -250,7 +249,7 @@ SyncStatusHandler::SyncStatusHandler(wxFrame* parentDlg, startTime_(wxGetUTCTimeMillis().GetValue()) {} -SyncStatusHandler::~SyncStatusHandler() +StatusHandlerFloatingDialog::~StatusHandlerFloatingDialog() { //------------ "on completion" command conceptually is part of the sync, not cleanup -------------------------------------- @@ -331,7 +330,7 @@ SyncStatusHandler::~SyncStatusHandler() if (showFinalResults) { if (abortIsRequested()) - progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events + progressDlg->processHasFinished(SyncProgressDialog::RESULT_ABORTED, errorLog); //enable okay and close events else if (totalErrors > 0) progressDlg->processHasFinished(SyncProgressDialog::RESULT_FINISHED_WITH_ERROR, errorLog); else if (totalWarnings > 0) @@ -348,13 +347,13 @@ SyncStatusHandler::~SyncStatusHandler() while (progressDlg) { wxTheApp->Yield(); //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted -> not expected => main thread! + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } } } -void SyncStatusHandler::initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) +void StatusHandlerFloatingDialog::initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) { assert(phaseID == PHASE_SYNCHRONIZING); StatusHandler::initNewPhase(objectsTotal, dataTotal, phaseID); @@ -365,7 +364,7 @@ void SyncStatusHandler::initNewPhase(int objectsTotal, std::int64_t dataTotal, P } -void SyncStatusHandler::updateProcessedData(int objectsDelta, std::int64_t dataDelta) +void StatusHandlerFloatingDialog::updateProcessedData(int objectsDelta, std::int64_t dataDelta) { StatusHandler::updateProcessedData(objectsDelta, dataDelta); if (progressDlg) @@ -374,14 +373,14 @@ void SyncStatusHandler::updateProcessedData(int objectsDelta, std::int64_t dataD } -void SyncStatusHandler::reportInfo(const std::wstring& text) +void StatusHandlerFloatingDialog::reportInfo(const std::wstring& text) { StatusHandler::reportInfo(text); errorLog.logMsg(text, TYPE_INFO); } -ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& errorMessage, size_t retryNumber) +ProcessCallback::Response StatusHandlerFloatingDialog::reportError(const std::wstring& errorMessage, size_t retryNumber) { //auto-retry if (retryNumber < automaticRetryCount_) @@ -394,7 +393,7 @@ ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& err { reportStatus(_("Error") + L": " + _P("Automatic retry in 1 second...", "Automatic retry in %x seconds...", (1000 * automaticRetryDelay_ - i * UI_UPDATE_INTERVAL + 999) / 1000)); //integer round up - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } return ProcessCallback::RETRY; } @@ -443,7 +442,7 @@ ProcessCallback::Response SyncStatusHandler::reportError(const std::wstring& err } -void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage) +void StatusHandlerFloatingDialog::reportFatalError(const std::wstring& errorMessage) { errorLog.logMsg(errorMessage, TYPE_FATAL_ERROR); @@ -479,7 +478,7 @@ void SyncStatusHandler::reportFatalError(const std::wstring& errorMessage) } -void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool& warningActive) +void StatusHandlerFloatingDialog::reportWarning(const std::wstring& warningMessage, bool& warningActive) { errorLog.logMsg(warningMessage, TYPE_WARNING); @@ -516,21 +515,21 @@ void SyncStatusHandler::reportWarning(const std::wstring& warningMessage, bool& } -void SyncStatusHandler::forceUiRefresh() +void StatusHandlerFloatingDialog::forceUiRefresh() { if (progressDlg) progressDlg->updateGui(); } -void SyncStatusHandler::abortProcessNow() +void StatusHandlerFloatingDialog::abortProcessNow() { requestAbortion(); //just make sure... - throw GuiAbortProcess(); //abort can be triggered by progressDlg + throw GuiAbortProcess(); //abort can be triggered by progressDlg } -void SyncStatusHandler::onProgressDialogTerminate() +void StatusHandlerFloatingDialog::onProgressDialogTerminate() { //it's responsibility of "progressDlg" to call requestAbortion() when closing dialog progressDlg = nullptr; diff --git a/FreeFileSync/Source/ui/gui_status_handler.h b/FreeFileSync/Source/ui/gui_status_handler.h index 803c8fdb..35789972 100644 --- a/FreeFileSync/Source/ui/gui_status_handler.h +++ b/FreeFileSync/Source/ui/gui_status_handler.h @@ -18,14 +18,14 @@ //Exception class used to abort the "compare" and "sync" process class GuiAbortProcess {}; -//classes handling sync and compare error as well as status information +//classes handling sync and compare errors as well as status feedback -//CompareStatusHandler(CompareProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! -class CompareStatusHandler : private wxEvtHandler, public zen::StatusHandler //throw GuiAbortProcess +//StatusHandlerTemporaryPanel(CompareProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! +class StatusHandlerTemporaryPanel : private wxEvtHandler, public zen::StatusHandler //throw GuiAbortProcess { public: - CompareStatusHandler(MainDialog& dlg); - ~CompareStatusHandler(); + StatusHandlerTemporaryPanel(MainDialog& dlg); + ~StatusHandlerTemporaryPanel(); void initNewPhase(int objectsTotal, std::int64_t dataTotal, Phase phaseID) override; void forceUiRefresh() override; @@ -45,19 +45,19 @@ private: }; -//SyncStatusHandler(SyncProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! -class SyncStatusHandler : public zen::StatusHandler +//StatusHandlerFloatingDialog(SyncProgressDialog) will internally process Window messages! disable GUI controls to avoid unexpected callbacks! +class StatusHandlerFloatingDialog : public zen::StatusHandler { public: - SyncStatusHandler(wxFrame* parentDlg, - size_t lastSyncsLogFileSizeMax, - xmlAccess::OnGuiError handleError, - size_t automaticRetryCount, - size_t automaticRetryDelay, - const std::wstring& jobName, - const Zstring& onCompletion, - std::vector& onCompletionHistory); - ~SyncStatusHandler(); + StatusHandlerFloatingDialog(wxFrame* parentDlg, + size_t lastSyncsLogFileSizeMax, + xmlAccess::OnGuiError handleError, + size_t automaticRetryCount, + size_t automaticRetryDelay, + const std::wstring& jobName, + const Zstring& onCompletion, + std::vector& onCompletionHistory); + ~StatusHandlerFloatingDialog(); void initNewPhase (int objectsTotal, std::int64_t dataTotal, Phase phaseID) override; void updateProcessedData(int objectsDelta, std::int64_t dataDelta ) override; diff --git a/FreeFileSync/Source/ui/main_dlg.cpp b/FreeFileSync/Source/ui/main_dlg.cpp index 2a08c3f8..4850031c 100644 --- a/FreeFileSync/Source/ui/main_dlg.cpp +++ b/FreeFileSync/Source/ui/main_dlg.cpp @@ -173,7 +173,7 @@ private: wxWindow* getParentWindow() override { return &mainDlg; } std::unique_ptr& getFilterCfgOnClipboardRef() override { return mainDlg.filterCfgOnClipboard; } - void onAltCompCfgChange () override { mainDlg.applyCompareConfig(); } + void onAltCompCfgChange () override { mainDlg.applyCompareConfig(false /*setDefaultViewType*/); } void onAltSyncCfgChange () override { mainDlg.applySyncConfig(); } void onLocalFilterCfgChange() override { mainDlg.applyFilterConfig(); } //re-apply filter @@ -189,14 +189,17 @@ public: FolderPairPanel(wxWindow* parent, MainDialog& mainDialog) : FolderPairPanelGenerated(parent), FolderPairCallback(static_cast(*this), mainDialog), //pass FolderPairPanelGenerated part... - dirpathLeft (mainDialog, *m_panelLeft, *m_buttonSelectDirLeft, *m_bpButtonSelectSftpLeft, *m_directoryLeft), - dirpathRight(mainDialog, *m_panelRight, *m_buttonSelectDirRight, *m_bpButtonSelectSftpRight, *m_directoryRight) + folderSelectorLeft (mainDialog, *m_panelLeft, *m_buttonSelectDirLeft, *m_bpButtonSelectSftpLeft, *m_directoryLeft), + folderSelectorRight(mainDialog, *m_panelRight, *m_buttonSelectDirRight, *m_bpButtonSelectSftpRight, *m_directoryRight) { - dirpathLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - dirpathRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); + folderSelectorLeft .setSiblingSelector(&folderSelectorRight); + folderSelectorRight.setSiblingSelector(&folderSelectorLeft); - dirpathLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - dirpathRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); + folderSelectorLeft .Connect(EVENT_ON_FOLDER_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); + folderSelectorRight.Connect(EVENT_ON_FOLDER_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); + + folderSelectorLeft .Connect(EVENT_ON_FOLDER_MANUAL_EDIT, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); + folderSelectorRight.Connect(EVENT_ON_FOLDER_MANUAL_EDIT, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); m_bpButtonFolderPairOptions->SetBitmapLabel(getResourceImage(L"button_arrow_down")); } @@ -204,19 +207,16 @@ public: void setValues(const FolderPairEnh& fp) { setConfig(fp.altCmpConfig, fp.altSyncConfig, fp.localFilter); - dirpathLeft .setPath(fp.dirpathPhraseLeft); - dirpathRight.setPath(fp.dirpathPhraseRight); + folderSelectorLeft .setPath(fp.folderPathPhraseLeft_); + folderSelectorRight.setPath(fp.folderPathPhraseRight_); } - FolderPairEnh getValues() const { return FolderPairEnh(getLeftDir(), getRightDir(), getAltCompConfig(), getAltSyncConfig(), getAltFilterConfig()); } - - Zstring getLeftDir () const { return dirpathLeft .getPath(); } - Zstring getRightDir() const { return dirpathRight.getPath(); } + FolderPairEnh getValues() const { return FolderPairEnh(folderSelectorLeft.getPath(), folderSelectorRight.getPath(), getAltCompConfig(), getAltSyncConfig(), getAltFilterConfig()); } private: //support for drag and drop - FolderSelectorImpl dirpathLeft; - FolderSelectorImpl dirpathRight; + FolderSelectorImpl folderSelectorLeft; + FolderSelectorImpl folderSelectorRight; }; @@ -227,26 +227,29 @@ public: FolderPairCallback(mainDialog, mainDialog), //prepare drag & drop - dirpathLeft(mainDialog, - *mainDialog.m_panelTopLeft, - *mainDialog.m_buttonSelectDirLeft, - *mainDialog.m_bpButtonSelectSftpLeft, - *mainDialog.m_directoryLeft, - mainDialog.m_staticTextResolvedPathL, - &mainDialog.m_gridMainL->getMainWin()), - dirpathRight(mainDialog, - *mainDialog.m_panelTopRight, - *mainDialog.m_buttonSelectDirRight, - *mainDialog.m_bpButtonSelectSftpRight, - *mainDialog.m_directoryRight, - mainDialog.m_staticTextResolvedPathR, - &mainDialog.m_gridMainR->getMainWin()) - { - dirpathLeft .Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - dirpathRight.Connect(EVENT_ON_DIR_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); - - dirpathLeft .Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); - dirpathRight.Connect(EVENT_ON_DIR_MANUAL_CORRECTION, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); + folderSelectorLeft(mainDialog, + *mainDialog.m_panelTopLeft, + *mainDialog.m_buttonSelectDirLeft, + *mainDialog.m_bpButtonSelectSftpLeft, + *mainDialog.m_directoryLeft, + mainDialog.m_staticTextResolvedPathL, + &mainDialog.m_gridMainL->getMainWin()), + folderSelectorRight(mainDialog, + *mainDialog.m_panelTopRight, + *mainDialog.m_buttonSelectDirRight, + *mainDialog.m_bpButtonSelectSftpRight, + *mainDialog.m_directoryRight, + mainDialog.m_staticTextResolvedPathR, + &mainDialog.m_gridMainR->getMainWin()) + { + folderSelectorLeft .setSiblingSelector(&folderSelectorRight); + folderSelectorRight.setSiblingSelector(&folderSelectorLeft); + + folderSelectorLeft .Connect(EVENT_ON_FOLDER_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); + folderSelectorRight.Connect(EVENT_ON_FOLDER_SELECTED, wxCommandEventHandler(MainDialog::onDirSelected), nullptr, &mainDialog); + + folderSelectorLeft .Connect(EVENT_ON_FOLDER_MANUAL_EDIT, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); + folderSelectorRight.Connect(EVENT_ON_FOLDER_MANUAL_EDIT, wxCommandEventHandler(MainDialog::onDirManualCorrection), nullptr, &mainDialog); mainDialog.m_panelTopLeft ->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::onTopFolderPairKeyEvent), nullptr, &mainDialog); mainDialog.m_panelTopMiddle->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::onTopFolderPairKeyEvent), nullptr, &mainDialog); @@ -256,19 +259,16 @@ public: void setValues(const FolderPairEnh& fp) { setConfig(fp.altCmpConfig, fp.altSyncConfig, fp.localFilter); - dirpathLeft .setPath(fp.dirpathPhraseLeft); - dirpathRight.setPath(fp.dirpathPhraseRight); + folderSelectorLeft .setPath(fp.folderPathPhraseLeft_); + folderSelectorRight.setPath(fp.folderPathPhraseRight_); } - FolderPairEnh getValues() const { return FolderPairEnh(getLeftDir(), getRightDir(), getAltCompConfig(), getAltSyncConfig(), getAltFilterConfig()); } - - Zstring getLeftDir () const { return dirpathLeft .getPath(); } - Zstring getRightDir() const { return dirpathRight.getPath(); } + FolderPairEnh getValues() const { return FolderPairEnh(folderSelectorLeft.getPath(), folderSelectorRight.getPath(), getAltCompConfig(), getAltSyncConfig(), getAltFilterConfig()); } private: //support for drag and drop - FolderSelectorImpl dirpathLeft; - FolderSelectorImpl dirpathRight; + FolderSelectorImpl folderSelectorLeft; + FolderSelectorImpl folderSelectorRight; }; @@ -328,7 +328,7 @@ void setMenuItemImage(wxMenuItem*& menuItem, const wxBitmap& bmp) //just greyscale instead of brightened like bitmap buttons; much better: newItem->SetDisabledBitmap(bmp.ConvertToDisabled()); #endif - bool isDestroyed = menu->Destroy(menuItem); //actual workaround + bool isDestroyed = menu->Destroy(menuItem); //actual workaround assert(isDestroyed); (void)isDestroyed; menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer! @@ -404,7 +404,7 @@ void MainDialog::create(const Zstring& globalConfigFile) firstMissingDir.addJob([filepath] { return filepath.empty() /*ever empty??*/ || !fileExists(filepath) ? make_unique() : nullptr; }); //potentially slow network access: give all checks 500ms to finish - const bool allFilesExist = firstMissingDir.timedWait(boost::chrono::milliseconds(500)) && //false: time elapsed + const bool allFilesExist = firstMissingDir.timedWait(std::chrono::milliseconds(500)) && //false: time elapsed !firstMissingDir.get(); //no missing if (!allFilesExist) filepaths.clear(); //we do NOT want to show an error due to last config file missing on application start! @@ -524,11 +524,11 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, m_bpButtonAddPair ->SetBitmapLabel(getResourceImage(L"item_add")); m_bpButtonHideSearch ->SetBitmapLabel(getResourceImage(L"close_panel")); - warn_static("remove after test") -#ifdef ZEN_MAC - //follow OS conventions: - // m_menuItemOptions->SetItemLabel(_("&Preferences") + L"\tCtrl+,"); //"Ctrl" is automatically mapped to command button! - //this->SetMenuBar(m_menubar1); + //we have to use the OS X naming convention by default, because wxMac permanently populates the display menu when the wxMenuItem is created for the first time! + //=> other wx ports are not that badly programmed; therefore revert: + assert(m_menuItemOptions->GetItemLabel() == _("&Preferences") + L"\tCtrl+,"); //"Ctrl" is automatically mapped to command button! +#ifndef ZEN_MAC + m_menuItemOptions->SetItemLabel(_("&Options")); #endif //---------------- support for dockable gui style -------------------------------- @@ -805,8 +805,8 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, auto addDirCheck = [&](const FolderPairEnh& fp) { - std::unique_ptr abfL = createAbstractBaseFolder(fp.dirpathPhraseLeft); - std::unique_ptr abfR = createAbstractBaseFolder(fp.dirpathPhraseRight); + std::unique_ptr abfL = createAbstractBaseFolder(fp.folderPathPhraseLeft_); + std::unique_ptr abfR = createAbstractBaseFolder(fp.folderPathPhraseRight_); if (abfL->emptyBaseFolderPath() != abfR->emptyBaseFolderPath()) //only skip check if both sides are empty! havePartialPair = true; @@ -814,9 +814,9 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, haveFullPair = true; if (!abfL->emptyBaseFolderPath()) - asyncDirChecks.push_back(ABF::getAsyncCheckDirExists(abfL->getAbstractPath())); //noexcept + asyncDirChecks.push_back(ABF::getAsyncCheckFolderExists(abfL->getAbstractPath())); //noexcept if (!abfR->emptyBaseFolderPath()) - asyncDirChecks.push_back(ABF::getAsyncCheckDirExists(abfR->getAbstractPath())); //noexcept + asyncDirChecks.push_back(ABF::getAsyncCheckFolderExists(abfR->getAbstractPath())); //noexcept }; addDirCheck(currMainCfg.firstPair); @@ -839,7 +839,7 @@ MainDialog::MainDialog(const Zstring& globalConfigFile, return make_unique(); }); - const bool startComparisonNow = !firstMissingDir.timedWait(boost::chrono::milliseconds(500)) || //= no result yet => start comparison anyway! + const bool startComparisonNow = !firstMissingDir.timedWait(std::chrono::milliseconds(500)) || //= no result yet => start comparison anyway! !firstMissingDir.get(); //= all directories exist if (startComparisonNow) @@ -1144,19 +1144,16 @@ void MainDialog::copySelectionToClipboard(const std::vector& gridRe std::vector MainDialog::getGridSelection(bool fromLeft, bool fromRight) const { - std::set selectedRows; - - auto addSelection = [&](const Grid& grid) - { - const std::vector& sel = grid.getSelectedRows(); - selectedRows.insert(sel.begin(), sel.end()); - }; + std::vector selectedRows; if (fromLeft) - addSelection(*m_gridMainL); + vector_append(selectedRows, m_gridMainL->getSelectedRows()); if (fromRight) - addSelection(*m_gridMainR); + vector_append(selectedRows, m_gridMainR->getSelectedRows()); + + removeDuplicates(selectedRows); + assert(std::is_sorted(selectedRows.begin(), selectedRows.end())); return gridDataView->getAllFileRef(selectedRows); } @@ -1195,174 +1192,96 @@ std::vector MainDialog::getTreeSelection() const } -//Exception class used to abort the "compare" and "sync" process -class AbortDeleteProcess {}; - -class ManualDeletionHandler : private wxEvtHandler, public DeleteFilesHandler //throw AbortDeleteProcess +void MainDialog::copyToAlternateFolder(const std::vector& selectionLeft, + const std::vector& selectionRight) { -public: - ManualDeletionHandler(MainDialog& main) : - mainDlg(main), - abortRequested(false), - ignoreErrors(false) - { - mainDlg.disableAllElements(true); //disable everything except abort button - - //register abort button - mainDlg.m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion), nullptr, this ); - mainDlg.Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), nullptr, this); - } - - ~ManualDeletionHandler() - { - //de-register abort button - mainDlg.Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(ManualDeletionHandler::OnKeyPressed), nullptr, this); - mainDlg.m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ManualDeletionHandler::OnAbortDeletion ), nullptr, this ); + std::vector itemSelectionLeft = selectionLeft; + std::vector itemSelectionRight = selectionRight; + vector_remove_if(itemSelectionLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + vector_remove_if(itemSelectionRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + if (itemSelectionLeft.empty() && itemSelectionRight.empty()) + return; - mainDlg.enableAllElements(); - } + wxWindow* oldFocus = wxWindow::FindFocus(); + ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus()); + + if (zen::showCopyToDialog(this, + itemSelectionLeft, itemSelectionRight, + globalCfg.gui.copyToCfg.lastUsedPath, + globalCfg.gui.copyToCfg.folderHistory, + globalCfg.gui.copyToCfg.historySizeMax, + globalCfg.gui.copyToCfg.keepRelPaths, + globalCfg.gui.copyToCfg.overwriteIfExists) != ReturnSmallDlg::BUTTON_OKAY) + return; - Response reportError(const std::wstring& msg) override + try { - if (ignoreErrors) - return DeleteFilesHandler::IGNORE_ERROR; + disableAllElements(true); //StatusHandlerTemporaryPanel will internally process Window messages, so avoid unexpected callbacks! + auto app = wxTheApp; //fix lambda/wxWigets/VC fuck up + ZEN_ON_SCOPE_EXIT(app->Yield(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks - forceUiRefresh(); - bool ignoreNextErrors = false; - switch (showConfirmationDialog3(&mainDlg, DialogInfoType::ERROR2, PopupDialogCfg3(). - setDetailInstructions(msg). - setCheckBox(ignoreNextErrors, _("&Ignore subsequent errors"), ConfirmationButton3::DONT_DO_IT), - _("&Ignore"), _("&Retry"))) - { - case ConfirmationButton3::DO_IT: //ignore - ignoreErrors = ignoreNextErrors; - return DeleteFilesHandler::IGNORE_ERROR; + StatusHandlerTemporaryPanel statusHandler(*this); //handle status display and error messages - case ConfirmationButton3::DONT_DO_IT: //retry - return DeleteFilesHandler::RETRY; + zen::copyToAlternateFolder(itemSelectionLeft, itemSelectionRight, + globalCfg.gui.copyToCfg.lastUsedPath, + globalCfg.gui.copyToCfg.keepRelPaths, + globalCfg.gui.copyToCfg.overwriteIfExists, + statusHandler); - case ConfirmationButton3::CANCEL: - throw AbortDeleteProcess(); - } - - assert (false); - return DeleteFilesHandler::IGNORE_ERROR; //dummy return value + //"clearSelection" not needed/desired } + catch (GuiAbortProcess&) {} - void reportWarning(const std::wstring& msg, bool& warningActive) override - { - if (!warningActive || ignoreErrors) - return; - - forceUiRefresh(); - bool dontWarnAgain = false; - switch (showConfirmationDialog(&mainDlg, DialogInfoType::WARNING, PopupDialogCfg(). - setDetailInstructions(msg). - setCheckBox(dontWarnAgain, _("&Don't show this warning again")), _("&Ignore"))) - { - case ConfirmationButton::DO_IT: - warningActive = !dontWarnAgain; - break; - case ConfirmationButton::CANCEL: - throw AbortDeleteProcess(); - } - } + //updateGui(); -> not needed +} - void reportStatus (const std::wstring& msg) override - { - statusMsg = msg; - requestUiRefresh(); - } -private: - void requestUiRefresh() - { - if (updateUiIsAllowed()) //test if specific time span between ui updates is over - forceUiRefresh(); +void MainDialog::deleteSelectedFiles(const std::vector& selectionLeft, + const std::vector& selectionRight) +{ + std::vector itemSelectionLeft = selectionLeft; + std::vector itemSelectionRight = selectionRight; + vector_remove_if(itemSelectionLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + vector_remove_if(itemSelectionRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + if (itemSelectionLeft.empty() && itemSelectionRight.empty()) + return; - if (abortRequested) //test after (implicit) call to wxApp::Yield() - throw AbortDeleteProcess(); - } + wxWindow* oldFocus = wxWindow::FindFocus(); + ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus()); - void forceUiRefresh() - { - //std::wstring msg = toGuiString(deletionCount) + - mainDlg.setStatusBarFullText(statusMsg); - wxTheApp->Yield(); - } + if (zen::showDeleteDialog(this, + itemSelectionLeft, itemSelectionRight, + globalCfg.gui.manualDeletionUseRecycler) != ReturnSmallDlg::BUTTON_OKAY) + return; - //context: C callstack message loop => throw()! - void OnAbortDeletion(wxCommandEvent& event) //handle abort button click - { - abortRequested = true; //don't throw exceptions across a C call stack! - } + disableAllElements(true); //StatusHandlerTemporaryPanel will internally process Window messages, so avoid unexpected callbacks! + auto app = wxTheApp; //fix lambda/wxWigets/VC fuck up + ZEN_ON_SCOPE_EXIT(app->Yield(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks - void OnKeyPressed(wxKeyEvent& event) + //wxBusyCursor dummy; -> redundant: progress already shown in status bar! + try { - const int keyCode = event.GetKeyCode(); - if (keyCode == WXK_ESCAPE) - { - abortRequested = true; //don't throw exceptions across a C call stack! - return; - } - - event.Skip(); - } - - MainDialog& mainDlg; + StatusHandlerTemporaryPanel statusHandler(*this); //handle status display and error messages - bool abortRequested; - bool ignoreErrors; - //size_t deletionCount; // - std::wstring statusMsg; //status reporting -}; - - -void MainDialog::deleteSelectedFiles(const std::vector& selectionLeft, - const std::vector& selectionRight) -{ - //=> cleanup empty selection on either side: - std::vector selectionLeftTmp; - std::vector selectionRightTmp; - std::copy_if(selectionLeft .begin(), selectionLeft .end(), std::back_inserter(selectionLeftTmp ), [](const FileSystemObject* fsObj) { return !fsObj->isEmpty(); }); - std::copy_if(selectionRight.begin(), selectionRight.end(), std::back_inserter(selectionRightTmp), [](const FileSystemObject* fsObj) { return !fsObj->isEmpty(); }); + zen::deleteFromGridAndHD(itemSelectionLeft, itemSelectionRight, + folderCmp, + extractDirectionCfg(getConfig().mainCfg), + globalCfg.gui.manualDeletionUseRecycler, + globalCfg.optDialogs.warningRecyclerMissing, + statusHandler); - if (!selectionLeftTmp.empty() || !selectionRightTmp.empty()) - { - wxWindow* oldFocus = wxWindow::FindFocus(); - ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();) + m_gridMainL->clearSelection(ALLOW_GRID_EVENT); + m_gridMainC->clearSelection(ALLOW_GRID_EVENT); + m_gridMainR->clearSelection(ALLOW_GRID_EVENT); - if (zen::showDeleteDialog(this, - selectionLeftTmp, - selectionRightTmp, - globalCfg.gui.useRecyclerForManualDeletion) == ReturnSmallDlg::BUTTON_OKAY) - { - //wxBusyCursor dummy; -> redundant: progress already shown in status bar! - try - { - //handle errors when deleting files/folders - ManualDeletionHandler statusHandler(*this); - - zen::deleteFromGridAndHD(selectionLeftTmp, - selectionRightTmp, - folderCmp, - extractDirectionCfg(getConfig().mainCfg), - globalCfg.gui.useRecyclerForManualDeletion, - statusHandler, - globalCfg.optDialogs.warningRecyclerMissing); - - m_gridMainL->clearSelection(ALLOW_GRID_EVENT); - m_gridMainC->clearSelection(ALLOW_GRID_EVENT); - m_gridMainR->clearSelection(ALLOW_GRID_EVENT); - } - catch (AbortDeleteProcess&) {} //do not clear grids, if aborted! + m_gridNavi->clearSelection(ALLOW_GRID_EVENT); + } + catch (GuiAbortProcess&) {} //do not clear grids, if aborted! - //remove rows that are empty: just a beautification, invalid rows shouldn't cause issues - gridDataView->removeInvalidRows(); + //remove rows that are empty: just a beautification, invalid rows shouldn't cause issues + gridDataView->removeInvalidRows(); - updateGui(); - } - } + updateGui(); } @@ -1416,8 +1335,8 @@ void MainDialog::openExternalApplication(const wxString& commandline, const std: (leftSide && selectionTmp[0]->isEmpty()) || (!leftSide && selectionTmp[0]->isEmpty())) { - auto abfL = createAbstractBaseFolder(firstFolderPair->getLeftDir ()); //keep AbstractPathRef valid! - auto abfR = createAbstractBaseFolder(firstFolderPair->getRightDir()); // + auto abfL = createAbstractBaseFolder(firstFolderPair->getValues().folderPathPhraseLeft_); //keep AbstractPathRef valid! + auto abfR = createAbstractBaseFolder(firstFolderPair->getValues().folderPathPhraseRight_); // AbstractPathRef fallbackFolderPath = [&] { @@ -1567,20 +1486,20 @@ void MainDialog::setStatusBarFileStatistics(size_t filesOnLeftView, } -void MainDialog::setStatusBarFullText(const wxString& msg) -{ - const bool needLayoutUpdate = !m_staticTextFullStatus->IsShown(); - //select state - bSizerFileStatus->Show(false); - m_staticTextFullStatus->Show(); - - //update status information - setText(*m_staticTextFullStatus, msg); - m_panelStatusBar->Layout(); - - if (needLayoutUpdate) - auiMgr.Update(); //fix status bar height (needed on OS X) -} +//void MainDialog::setStatusBarFullText(const wxString& msg) +//{ +// const bool needLayoutUpdate = !m_staticTextFullStatus->IsShown(); +// //select state +// bSizerFileStatus->Show(false); +// m_staticTextFullStatus->Show(); +// +// //update status information +// setText(*m_staticTextFullStatus, msg); +// m_panelStatusBar->Layout(); +// +// if (needLayoutUpdate) +// auiMgr.Update(); //fix status bar height (needed on OS X) +//} void MainDialog::flashStatusInformation(const wxString& text) @@ -1594,7 +1513,7 @@ void MainDialog::flashStatusInformation(const wxString& text) m_panelStatusBar->Layout(); //if (needLayoutUpdate) auiMgr.Update(); -> not needed here, this is called anyway in updateGui() - processAsync2([] { boost::this_thread::sleep_for(boost::chrono::milliseconds(2500)); }, //throw boost::thread_interrupted + processAsync2([] { std::this_thread::sleep_for(std::chrono::milliseconds(2500)); }, [this] { this->restoreStatusInformation(); }); } @@ -1649,7 +1568,10 @@ void MainDialog::disableAllElements(bool enableAbort) m_bpButtonSyncConfig ->Disable(); m_buttonSync ->Disable(); m_panelDirectoryPairs->Disable(); - m_splitterMain ->Disable(); //includes m_panelCenter, but not m_panelStatusBar! + m_splitterMain ->Disable(); + m_gridMainL ->Disable(); //disabled state already covered by m_splitterMain, + m_gridMainC ->Disable(); //however grid.cpp used IsThisEnabled() for rendering! + m_gridMainR ->Disable(); // m_panelViewFilter ->Disable(); m_panelConfig ->Disable(); m_gridNavi ->Disable(); @@ -1688,6 +1610,9 @@ void MainDialog::enableAllElements() m_buttonSync ->Enable(); m_panelDirectoryPairs->Enable(); m_splitterMain ->Enable(); + m_gridMainL ->Enable(); + m_gridMainC ->Enable(); + m_gridMainR ->Enable(); m_panelViewFilter ->Enable(); m_panelConfig ->Enable(); m_gridNavi ->Enable(); @@ -1876,6 +1801,11 @@ void MainDialog::onGridButtonEvent(wxKeyEvent& event, Grid& grid, bool leftSide) case WXK_INSERT: //CTRL + C || CTRL + INS copySelectionToClipboard({ m_gridMainL, m_gridMainR} ); return; // -> swallow event! don't allow default grid commands! + + case 'T': //CTRL + T + copyToAlternateFolder(getGridSelection(true, false), + getGridSelection(false, true)); + return; } else if (event.AltDown()) @@ -2125,7 +2055,7 @@ void MainDialog::onNaviGridContext(GridClickEvent& event) } //---------------------------------------------------------------------------------------------------- - //FILE FILTER + auto addFilterMenu = [&](const std::wstring& label, const wxString& iconName, bool include) { if (selection.size() == 1) @@ -2170,10 +2100,17 @@ void MainDialog::onNaviGridContext(GridClickEvent& event) menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false); //---------------------------------------------------------------------------------------------------- - //CONTEXT_DELETE_FILES + const bool haveNonEmptyItems = std::any_of(selection.begin(), selection.end(), [&](const FileSystemObject* fsObj) { return !fsObj->isEmpty() || !fsObj->isEmpty(); }); + + //menu.addSeparator(); + + //menu.addItem(_("Copy to...") + L"\tCtrl+T", [&] { copyToAlternateFolder(selection, selection); }, nullptr, haveNonEmptyItems); + + //---------------------------------------------------------------------------------------------------- + menu.addSeparator(); - menu.addItem(_("Delete") + L"\tDel", [&] { deleteSelectedFiles(selection, selection); }, nullptr, !selection.empty()); + menu.addItem(_("Delete") + L"\tDel", [&] { deleteSelectedFiles(selection, selection); }, nullptr, haveNonEmptyItems); menu.popup(*this); } @@ -2241,7 +2178,7 @@ void MainDialog::onMainGridContextRim(bool leftSide) } //---------------------------------------------------------------------------------------------------- - //FILE FILTER + auto addFilterMenu = [&](const wxString& label, const wxString& iconName, bool include) { if (selection.size() == 1) @@ -2284,6 +2221,7 @@ void MainDialog::onMainGridContextRim(bool leftSide) addFilterMenu(_("Exclude via filter:"), L"filter_exclude_small", false); //---------------------------------------------------------------------------------------------------- + if (!selection.empty()) { if (m_bpButtonShowExcluded->isActive() && !selection[0]->isActive()) @@ -2295,7 +2233,7 @@ void MainDialog::onMainGridContextRim(bool leftSide) menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false); //---------------------------------------------------------------------------------------------------- - //CONTEXT_EXTERNAL_APP + if (!globalCfg.gui.externelApplications.empty()) { menu.addSeparator(); @@ -2319,16 +2257,25 @@ void MainDialog::onMainGridContextRim(bool leftSide) menu.addItem(description, openApp, nullptr, !selection.empty()); } } + //---------------------------------------------------------------------------------------------------- - //CONTEXT_DELETE_FILES + + std::vector itemSelectionLeft = getGridSelection(true, false); + std::vector itemSelectionRight = getGridSelection(false, true); + vector_remove_if(itemSelectionLeft, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + vector_remove_if(itemSelectionRight, [](const FileSystemObject* fsObj) { return fsObj->isEmpty(); }); + menu.addSeparator(); - menu.addItem(_("Delete") + L"\tDel", [this] - { - deleteSelectedFiles( - getGridSelection(true, false), - getGridSelection(false, true)); - }, nullptr, !selection.empty()); + menu.addItem(_("Copy to...") + L"\tCtrl+T", [&] { copyToAlternateFolder(itemSelectionLeft, itemSelectionRight); }, nullptr, + !itemSelectionLeft.empty() || !itemSelectionRight.empty()); + + //---------------------------------------------------------------------------------------------------- + + menu.addSeparator(); + + menu.addItem(_("Delete") + L"\tDel", [&] { deleteSelectedFiles(itemSelectionLeft, itemSelectionRight); }, nullptr, + !itemSelectionLeft.empty() || !itemSelectionRight.empty()); menu.popup(*this); } @@ -2561,7 +2508,7 @@ void MainDialog::OnCompSettingsContext(wxMouseEvent& event) auto setVariant = [&](CompareVariant var) { currentCfg.mainCfg.cmpConfig.compareVar = var; - applyCompareConfig(true); //true: setDefaultViewType + applyCompareConfig(true /*setDefaultViewType*/); }; auto currentVar = getConfig().mainCfg.cmpConfig.compareVar; @@ -2596,7 +2543,7 @@ void MainDialog::OnSyncSettingsContext(wxMouseEvent& event) void MainDialog::onNaviPanelFilesDropped(FileDropEvent& event) { - loadConfiguration(event.getFiles()); + loadConfiguration(event.getPaths()); event.Skip(); } @@ -2706,22 +2653,22 @@ void MainDialog::removeObsoleteCfgHistoryItems(const std::vector& filep auto getMissingFilesAsync = [filepaths]() -> std::vector { - //boost::this_thread::sleep_for(boost::chrono::seconds(5)); + //std::this_thread::sleep_for(std::chrono::seconds(5)); //check existence of all config files in parallel! - std::list> fileEx; + std::list> fileEx; for (const Zstring& filepath : filepaths) fileEx.push_back(zen::runAsync([=] { return fileExists(filepath); })); //potentially slow network access => limit maximum wait time! - wait_for_all_timed(fileEx.begin(), fileEx.end(), boost::chrono::milliseconds(1000)); + wait_for_all_timed(fileEx.begin(), fileEx.end(), std::chrono::milliseconds(1000)); std::vector missingFiles; auto itFut = fileEx.begin(); - for (auto it = filepaths.begin(); it != filepaths.end(); ++it, (void)++itFut) //void: prevent ADL from dragging in boost's ,-overload: "MSVC warning C4913: user defined binary operator ',' exists but no overload could convert all operands" - if (itFut->is_ready() && !itFut->get()) //remove only files that are confirmed to be non-existent + for (auto it = filepaths.begin(); it != filepaths.end(); ++it, ++itFut) + if (isReady(*itFut) && !itFut->get()) //remove only files that are confirmed to be non-existent missingFiles.push_back(*it); return missingFiles; @@ -3224,11 +3171,11 @@ void MainDialog::OnClose(wxCloseEvent& event) void MainDialog::onCheckRows(CheckRowsEvent& event) { - std::set selectedRows; + std::vector selectedRows; const size_t rowLast = std::min(event.rowLast_, gridDataView->rowsOnView()); //consider dummy rows for (size_t i = event.rowFirst_; i < rowLast; ++i) - selectedRows.insert(i); + selectedRows.push_back(i); if (!selectedRows.empty()) { @@ -3240,11 +3187,11 @@ void MainDialog::onCheckRows(CheckRowsEvent& event) void MainDialog::onSetSyncDirection(SyncDirectionEvent& event) { - std::set selectedRows; + std::vector selectedRows; const size_t rowLast = std::min(event.rowLast_, gridDataView->rowsOnView()); //consider dummy rows for (size_t i = event.rowFirst_; i < rowLast; ++i) - selectedRows.insert(i); + selectedRows.push_back(i); if (!selectedRows.empty()) { @@ -3350,19 +3297,19 @@ void MainDialog::updateGuiDelayedIf(bool condition) void MainDialog::showConfigDialog(SyncConfigPanel panelToShow) { - const CompConfig cmpCfgOld = currentCfg.mainCfg.cmpConfig; - const FilterConfig filterCfgOld = currentCfg.mainCfg.globalFilter; - const SyncConfig syncCfgOld = currentCfg.mainCfg.syncCfg; - - MiscGlobalCfg miscCfg = + MiscGlobalCfg miscCfgTmp = { currentCfg.handleError, - currentCfg.mainCfg.onCompletion, globalCfg.gui.onCompletionHistory, globalCfg.gui.onCompletionHistoryMax }; + const CompConfig cmpCfgOld = currentCfg.mainCfg.cmpConfig; + const FilterConfig filterCfgOld = currentCfg.mainCfg.globalFilter; + const SyncConfig syncCfgOld = currentCfg.mainCfg.syncCfg; + const MiscGlobalCfg miscCfgOld = miscCfgTmp; + if (showSyncConfigDlg(this, panelToShow, nullptr, @@ -3371,20 +3318,30 @@ void MainDialog::showConfigDialog(SyncConfigPanel panelToShow) nullptr, currentCfg.mainCfg.syncCfg, currentCfg.mainCfg.cmpConfig.compareVar, - &miscCfg, + &miscCfgTmp, _("Synchronization Settings")) == ReturnSyncConfig::BUTTON_OKAY) { if (currentCfg.mainCfg.cmpConfig != cmpCfgOld) - applyCompareConfig(true); //true: setDefaultViewType + applyCompareConfig(true /*setDefaultViewType*/); if (currentCfg.mainCfg.globalFilter != filterCfgOld) { updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter + applyFilterConfig(); //re-apply filter } if (currentCfg.mainCfg.syncCfg != syncCfgOld) applySyncConfig(); + + if (miscCfgTmp != miscCfgOld) + { + currentCfg.handleError = miscCfgTmp.handleError; + currentCfg.mainCfg.onCompletion = miscCfgTmp.onCompletionCommand; + globalCfg.gui.onCompletionHistory = miscCfgTmp.onCompletionHistory; + //miscCfgTmp.onCompletionHistoryMax + + updateUnsavedCfgStatus(); //usually included by: updateGui(); + } } } @@ -3395,7 +3352,7 @@ void MainDialog::OnGlobalFilterContext(wxMouseEvent& event) { currentCfg.mainCfg.globalFilter = FilterConfig(); updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter + applyFilterConfig(); //re-apply filter }; auto copyFilter = [&] { filterCfgOnClipboard = make_unique(currentCfg.mainCfg.globalFilter); }; auto pasteFilter = [&] @@ -3404,7 +3361,7 @@ void MainDialog::OnGlobalFilterContext(wxMouseEvent& event) { currentCfg.mainCfg.globalFilter = *filterCfgOnClipboard; updateGlobalFilterButton(); //refresh global filter icon - applyFilterConfig(); //re-apply filter + applyFilterConfig(); //re-apply filter } }; @@ -3569,7 +3526,7 @@ void MainDialog::OnCompare(wxCommandEvent& event) //wxBusyCursor dummy; -> redundant: progress already shown in progress dialog! wxWindow* oldFocus = wxWindow::FindFocus(); - ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();); //e.g. keep focus on main grid after pressing F5 + ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus()); //e.g. keep focus on main grid after pressing F5 int scrollPosX = 0; int scrollPosY = 0; @@ -3581,14 +3538,14 @@ void MainDialog::OnCompare(wxCommandEvent& event) clearGrid(); //avoid memory peak by clearing old data first - disableAllElements(true); //CompareStatusHandler will internally process Window messages, so avoid unexpected callbacks! + disableAllElements(true); //StatusHandlerTemporaryPanel will internally process Window messages, so avoid unexpected callbacks! auto app = wxTheApp; //fix lambda/wxWigets/VC fuck up ZEN_ON_SCOPE_EXIT(app->Yield(); enableAllElements()); //ui update before enabling buttons again: prevent strange behaviour of delayed button clicks try { - //class handling status display and error messages - CompareStatusHandler statusHandler(*this); + //handle status display and error messages + StatusHandlerTemporaryPanel statusHandler(*this); const std::vector cmpConfig = extractCompareCfg(getConfig().mainCfg, globalCfg.fileTimeTolerance); @@ -3768,18 +3725,18 @@ void MainDialog::OnStartSync(wxCommandEvent& event) const auto& guiCfg = getConfig(); - disableAllElements(false); //SyncStatusHandler will internally process Window messages, so avoid unexpected callbacks! + disableAllElements(false); //StatusHandlerFloatingDialog will internally process Window messages, so avoid unexpected callbacks! ZEN_ON_SCOPE_EXIT(enableAllElements()); //class handling status updates and error messages - SyncStatusHandler statusHandler(this, //throw GuiAbortProcess - globalCfg.lastSyncsLogFileSizeMax, - currentCfg.handleError, - globalCfg.automaticRetryCount, - globalCfg.automaticRetryDelay, - xmlAccess::extractJobName(activeCfgFilename), - guiCfg.mainCfg.onCompletion, - globalCfg.gui.onCompletionHistory); + StatusHandlerFloatingDialog statusHandler(this, //throw GuiAbortProcess + globalCfg.lastSyncsLogFileSizeMax, + currentCfg.handleError, + globalCfg.automaticRetryCount, + globalCfg.automaticRetryDelay, + xmlAccess::extractJobName(activeCfgFilename), + guiCfg.mainCfg.onCompletion, + globalCfg.gui.onCompletionHistory); //wxBusyCursor dummy; -> redundant: progress already shown in progress dialog! @@ -3895,13 +3852,13 @@ void MainDialog::OnSwapSides(wxCommandEvent& event) { //swap directory names: FolderPairEnh fp1st = firstFolderPair->getValues(); - std::swap(fp1st.dirpathPhraseLeft, fp1st.dirpathPhraseRight); + std::swap(fp1st.folderPathPhraseLeft_, fp1st.folderPathPhraseRight_); firstFolderPair->setValues(fp1st); for (FolderPairPanel* panel : additionalFolderPairs) { FolderPairEnh fp = panel->getValues(); - std::swap(fp.dirpathPhraseLeft, fp.dirpathPhraseRight); + std::swap(fp.folderPathPhraseLeft_, fp.folderPathPhraseRight_); panel->setValues(fp); } diff --git a/FreeFileSync/Source/ui/main_dlg.h b/FreeFileSync/Source/ui/main_dlg.h index 7d62a61b..6be6bee6 100644 --- a/FreeFileSync/Source/ui/main_dlg.h +++ b/FreeFileSync/Source/ui/main_dlg.h @@ -54,8 +54,8 @@ private: bool startComparison); ~MainDialog(); - friend class CompareStatusHandler; - friend class SyncStatusHandler; + friend class StatusHandlerTemporaryPanel; + friend class StatusHandlerFloatingDialog; friend class ManualDeletionHandler; friend class FolderPairFirst; friend class FolderPairPanel; @@ -114,6 +114,10 @@ private: void setSyncDirManually(const std::vector& selection, zen::SyncDirection direction); void setFilterManually(const std::vector& selection, bool setIncluded); void copySelectionToClipboard(const std::vector& gridRefs); + + void copyToAlternateFolder(const std::vector& selectionLeft, + const std::vector& selectionRight); + void deleteSelectedFiles(const std::vector& selectionLeft, const std::vector& selectionRight); @@ -128,10 +132,10 @@ private: void processAsync2(Fun doAsync, Fun2 evalOnGui) { asyncTasks.add2(doAsync, evalOnGui); timerForAsyncTasks.Start(50); /*timer interval in [ms] */ } //status bar supports one of the following two states at a time: - void setStatusBarFullText(const wxString& msg); void setStatusBarFileStatistics(size_t filesOnLeftView, size_t foldersOnLeftView, size_t filesOnRightView, size_t foldersOnRightView, std::uint64_t filesizeLeftView, std::uint64_t filesizeRightView); + //void setStatusBarFullText(const wxString& msg); - void flashStatusInformation(const wxString& msg); //temporarily show different status (only valid for setStatusBarFullText) + void flashStatusInformation(const wxString& msg); //temporarily show different status (only valid for setStatusBarFileStatistics) void restoreStatusInformation(); //called automatically after a few seconds //events @@ -149,7 +153,7 @@ private: void OnGlobalFilterContext (wxMouseEvent& event) override; void OnViewButtonRightClick(wxMouseEvent& event) override; - void applyCompareConfig(bool setDefaultViewType = false); + void applyCompareConfig(bool setDefaultViewType); //context menu handler methods void onMainGridContextL(zen::GridClickEvent& event); diff --git a/FreeFileSync/Source/ui/on_completion_box.cpp b/FreeFileSync/Source/ui/on_completion_box.cpp index 27be3904..e2ba96ab 100644 --- a/FreeFileSync/Source/ui/on_completion_box.cpp +++ b/FreeFileSync/Source/ui/on_completion_box.cpp @@ -80,8 +80,6 @@ OnCompletionBox::OnCompletionBox(wxWindow* parent, const wxValidator& validator, const wxString& name) : wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name), - history_(nullptr), - historyMax_(0), defaultCommands(getDefaultCommands()) { //##################################### diff --git a/FreeFileSync/Source/ui/on_completion_box.h b/FreeFileSync/Source/ui/on_completion_box.h index 5085735b..c787ffe2 100644 --- a/FreeFileSync/Source/ui/on_completion_box.h +++ b/FreeFileSync/Source/ui/on_completion_box.h @@ -51,8 +51,8 @@ private: void setValueAndUpdateList(const std::wstring& value); - std::vector* history_; - size_t historyMax_; + std::vector* history_ = nullptr; + size_t historyMax_ = 0; const std::vector> defaultCommands; }; diff --git a/FreeFileSync/Source/ui/progress_indicator.cpp b/FreeFileSync/Source/ui/progress_indicator.cpp index 86abc40e..7e9ce1ed 100644 --- a/FreeFileSync/Source/ui/progress_indicator.cpp +++ b/FreeFileSync/Source/ui/progress_indicator.cpp @@ -253,15 +253,16 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow() } break; + case ProcessCallback::PHASE_SYNCHRONIZING: case ProcessCallback::PHASE_COMPARING_CONTENT: { - auto objectsCurrent = syncStat_->getObjectsCurrent(ProcessCallback::PHASE_COMPARING_CONTENT); - auto objectsTotal = syncStat_->getObjectsTotal (ProcessCallback::PHASE_COMPARING_CONTENT); - auto dataCurrent = syncStat_->getDataCurrent (ProcessCallback::PHASE_COMPARING_CONTENT); - auto dataTotal = syncStat_->getDataTotal (ProcessCallback::PHASE_COMPARING_CONTENT); + const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase()); + const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase()); + const std::int64_t dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase()); + const std::int64_t dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase()); //add both data + obj-count, to handle "deletion-only" cases - const double fraction = dataTotal + objectsTotal == 0 ? 0 : std::max(0.0, 1.0 * (dataCurrent + objectsCurrent) / (dataTotal + objectsTotal)); + const double fraction = dataTotal + itemsTotal == 0 ? 0 : std::max(0.0, 1.0 * (dataCurrent + itemsCurrent) / (dataTotal + itemsTotal)); //dialog caption, taskbar setTitle(fractionToString(fraction) + wxT(" - ") + _("Comparing content...")); @@ -275,7 +276,7 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow() m_gauge2->SetValue(numeric::round(fraction * GAUGE_FULL_RANGE)); //remaining objects and bytes for file comparison - setText(*m_staticTextItemsRemaining, toGuiString(objectsTotal - objectsCurrent), &layoutChanged); + setText(*m_staticTextItemsRemaining, toGuiString(itemsTotal - itemsCurrent), &layoutChanged); setText(*m_staticTextDataRemaining, L"(" + filesizeToShortString(dataTotal - dataCurrent) + L")", &layoutChanged); //remaining time and speed: only visible during binary comparison @@ -286,7 +287,7 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow() timeLastSpeedEstimateMs = timeNowMs; if (numeric::dist(binCompStartMs, timeNowMs) >= 1000) //discard stats for first second: probably messy - perf->addSample(objectsCurrent, dataCurrent, timeNowMs); + perf->addSample(itemsCurrent, dataCurrent, timeNowMs); //remaining time: display with relative error of 10% - based on samples taken every 0.5 sec only //-> call more often than once per second to correctly show last few seconds countdown, but don't call too often to avoid occasional jitter @@ -299,10 +300,6 @@ void CompareProgressDialog::Pimpl::updateStatusPanelNow() } } break; - - case ProcessCallback::PHASE_SYNCHRONIZING: - assert(false); - break; } //time elapsed @@ -728,7 +725,7 @@ private: includedTypes |= TYPE_INFO; msgView->updateView(includedTypes); //update MVC "model" - m_gridMessages->Refresh(); //update MVC "view" + m_gridMessages->Refresh(); //update MVC "view" } void onGridButtonEvent(wxKeyEvent& event) @@ -1209,7 +1206,9 @@ SyncProgressDialogImpl::SyncProgressDialogImpl(long style, //wxF { static_assert(IsSameType::value || IsSameType::value, ""); +#ifndef ZEN_MAC assert((IsSameType::value == !parentFrame)); +#endif //finish construction of this dialog: this->SetMinSize(wxSize(470, 280)); //== minimum size! no idea why SetMinSize() is not used... @@ -1268,7 +1267,7 @@ SyncProgressDialogImpl::SyncProgressDialogImpl(long style, //wxF curveDataBytes = std::make_shared(); curveDataItems = std::make_shared(); - const int xLabelHeight = this->GetCharHeight() + 2 * 1/*border*/; //use same height for both graphs to make sure they stretch evenly + const int xLabelHeight = this->GetCharHeight() + 2 * 1 /*border*/; //use same height for both graphs to make sure they stretch evenly const int yLabelWidth = 70; pnl.m_panelGraphBytes->setAttributes(Graph2D::MainAttributes(). setLabelX(Graph2D::X_LABEL_BOTTOM, xLabelHeight, std::make_shared(true)). @@ -1694,7 +1693,7 @@ void SyncProgressDialogImpl::updateGuiInt(bool allowYield) { wxTheApp->Yield(); //receive UI message that end pause OR forceful termination! //*first* refresh GUI (removing flicker) before sleeping! - boost::this_thread::sleep_for(boost::chrono::milliseconds(UI_UPDATE_INTERVAL)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(UI_UPDATE_INTERVAL)); } //after SyncProgressDialogImpl::OnClose() called wxWindow::Destroy() on OS X this instance is instantly toast! if (wereDead) @@ -1868,10 +1867,10 @@ void SyncProgressDialogImpl::processHasFinished(SyncResult resul case ProcessCallback::PHASE_COMPARING_CONTENT: case ProcessCallback::PHASE_SYNCHRONIZING: { - const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase()); - const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase()); - const std::int64_t dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase()); - const std::int64_t dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase()); + const int itemsCurrent = syncStat_->getObjectsCurrent(syncStat_->currentPhase()); + const int itemsTotal = syncStat_->getObjectsTotal (syncStat_->currentPhase()); + const std::int64_t dataCurrent = syncStat_->getDataCurrent (syncStat_->currentPhase()); + const std::int64_t dataTotal = syncStat_->getDataTotal (syncStat_->currentPhase()); assert(dataCurrent <= dataTotal); //set overall speed (instead of current speed) @@ -2140,9 +2139,19 @@ SyncProgressDialog* createProgressDialog(zen::AbortCallback& abortCb, std::vector& onCompletionHistory) { if (parentWindow) //sync from GUI + { + //due to usual "wxBugs", wxDialog on OS X does not float on its parent; wxFrame OTOH does => hack! + //https://groups.google.com/forum/#!topic/wx-users/J5SjjLaBOQE +#ifdef ZEN_MAC + return new SyncProgressDialogImpl(wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT, + [&](wxFrame& progDlg) { return parentWindow; }, + abortCb, notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, onCompletion, onCompletionHistory); +#else return new SyncProgressDialogImpl(wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER, [&](wxDialog& progDlg) { return parentWindow; }, - abortCb, notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, onCompletion, onCompletionHistory); + abortCb, notifyWindowTerminate, syncStat, parentWindow, showProgress, jobName, onCompletion, onCompletionHistory); +#endif + } else //FFS batch job { auto dlg = new SyncProgressDialogImpl(wxDEFAULT_FRAME_STYLE, diff --git a/FreeFileSync/Source/ui/progress_indicator.h b/FreeFileSync/Source/ui/progress_indicator.h index d86ef14d..92741ccd 100644 --- a/FreeFileSync/Source/ui/progress_indicator.h +++ b/FreeFileSync/Source/ui/progress_indicator.h @@ -33,7 +33,7 @@ private: }; -//SyncStatusHandler will internally process Window messages => disable GUI controls to avoid unexpected callbacks! +//StatusHandlerFloatingDialog will internally process Window messages => disable GUI controls to avoid unexpected callbacks! struct SyncProgressDialog { diff --git a/FreeFileSync/Source/ui/small_dlgs.cpp b/FreeFileSync/Source/ui/small_dlgs.cpp index 5319454c..4642f3ad 100644 --- a/FreeFileSync/Source/ui/small_dlgs.cpp +++ b/FreeFileSync/Source/ui/small_dlgs.cpp @@ -21,6 +21,7 @@ #include #include "gui_generated.h" #include "custom_grid.h" +#include "folder_selector.h" #include "../algorithm.h" #include "../synchronization.h" #include "../lib/help_provider.h" @@ -179,6 +180,8 @@ SftpSetupDlg::SftpSetupDlg(wxWindow* parent, Zstring& folderPathPhrase) : SftpSe const Zstring serverRelPath = res.second; m_textCtrlServer ->ChangeValue(utfCvrtTo(login.server)); + if (login.port > 0) + m_textCtrlPort->ChangeValue(numberTo(login.port)); m_textCtrlUserName ->ChangeValue(utfCvrtTo(login.username)); m_textCtrlPasswordHidden->ChangeValue(utfCvrtTo(login.password)); m_textCtrlServerPath ->ChangeValue(utfCvrtTo(serverRelPath)); @@ -213,12 +216,14 @@ void SftpSetupDlg::OnOkay(wxCommandEvent& event) { SftpLoginInfo login = {}; login.server = utfCvrtTo(m_textCtrlServer ->GetValue()); + login.port = stringTo (m_textCtrlPort ->GetValue()); //0 if empty login.username = utfCvrtTo(m_textCtrlUserName->GetValue()); login.password = utfCvrtTo((m_checkBoxShowPassword->GetValue() ? m_textCtrlPasswordVisible : m_textCtrlPasswordHidden)->GetValue()); Zstring serverRelPath = utfCvrtTo(m_textCtrlServerPath->GetValue()); trim(login.server); + trim(login.username); trim(serverRelPath); folderPathPhraseOut = assembleSftpFolderPathPhrase(login, serverRelPath); //noexcept @@ -237,6 +242,135 @@ ReturnSmallDlg::ButtonPressed zen::showSftpSetupDialog(wxWindow* parent, Zstring //######################################################################################## +class CopyToDialog : public CopyToDlgGenerated +{ +public: + CopyToDialog(wxWindow* parent, + const std::vector& rowsOnLeft, + const std::vector& rowsOnRight, + Zstring& lastUsedPath, + const std::shared_ptr& folderHistory, + bool& keepRelPaths, + bool& overwriteIfExists); + +private: + void OnOK (wxCommandEvent& event) override; + void OnCancel(wxCommandEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + void OnClose (wxCloseEvent& event) override { EndModal(ReturnSmallDlg::BUTTON_CANCEL); } + + Zstring& outLastUsedPath; + bool& outKeepRelPaths; + bool& outOverwriteIfExists; + + std::unique_ptr targetFolder; //always bound + std::shared_ptr folderHistory_; +}; + + +CopyToDialog::CopyToDialog(wxWindow* parent, + const std::vector& rowsOnLeft, + const std::vector& rowsOnRight, + Zstring& lastUsedPath, + const std::shared_ptr& folderHistory, + bool& keepRelPaths, + bool& overwriteIfExists) : + CopyToDlgGenerated(parent), + outLastUsedPath(lastUsedPath), + outKeepRelPaths(keepRelPaths), + outOverwriteIfExists(overwriteIfExists), + folderHistory_(folderHistory) +{ +#ifdef ZEN_WIN + new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" + wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! +#endif + + setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOK).setCancel(m_buttonCancel)); + + setMainInstructionFont(*m_staticTextHeader); + + m_bitmapCopyTo->SetBitmap(getResourceImage(L"copy_to")); + + targetFolder = make_unique(*this, *m_buttonSelectFolder, *m_bpButtonSelectSftp, *m_directoryTarget, nullptr /*staticText*/, nullptr /*wxWindow*/); + + m_directoryTarget->init(folderHistory_); + +#ifndef __WXGTK__ //wxWidgets holds portability promise by supporting multi-line controls...not + m_textCtrlFileList->SetMaxLength(0); //allow large entries! +#endif + /* + There is a nasty bug on wxGTK under Ubuntu: If a multi-line wxTextCtrl contains so many lines that scrollbars are shown, + it re-enables all windows that are supposed to be disabled during the current modal loop! + This only affects Ubuntu/wxGTK! No such issue on Debian/wxGTK or Suse/wxGTK + => another Unity problem like the following? + http://trac.wxwidgets.org/ticket/14823 "Menu not disabled when showing modal dialogs in wxGTK under Unity" + */ + + const std::pair selectionInfo = zen::getSelectedItemsAsString(rowsOnLeft, rowsOnRight); + + const wxString header = _P("Copy the following item to another folder?", + "Copy the following %x items to another folder?", selectionInfo.second); + m_staticTextHeader->SetLabel(header); + m_staticTextHeader->Wrap(460); //needs to be reapplied after SetLabel() + + m_textCtrlFileList->ChangeValue(selectionInfo.first); + + //----------------- set config --------------------------------- + targetFolder ->setPath(lastUsedPath); + m_checkBoxKeepRelPath ->SetValue(keepRelPaths); + m_checkBoxOverwriteIfExists->SetValue(overwriteIfExists); + //----------------- /set config -------------------------------- + + GetSizer()->SetSizeHints(this); //~=Fit() + SetMinSize() + //=> works like a charm for GTK2 with window resizing problems and title bar corruption; e.g. Debian!!! + + m_buttonOK->SetFocus(); +} + + +void CopyToDialog::OnOK(wxCommandEvent& event) +{ + //------- parameter validation (BEFORE writing output!) ------- + if (trimCpy(targetFolder->getPath()).empty()) + { + showNotificationDialog(this, DialogInfoType::INFO, PopupDialogCfg().setMainInstructions(_("Please enter a target folder."))); + //don't show error icon to follow "Windows' encouraging tone" + m_directoryTarget->SetFocus(); + return; + } + //------------------------------------------------------------- + + outLastUsedPath = targetFolder->getPath(); + outKeepRelPaths = m_checkBoxKeepRelPath->GetValue(); + outOverwriteIfExists = m_checkBoxOverwriteIfExists->GetValue(); + + folderHistory_->addItem(outLastUsedPath); + + EndModal(ReturnSmallDlg::BUTTON_OKAY); +} + + +ReturnSmallDlg::ButtonPressed zen::showCopyToDialog(wxWindow* parent, + const std::vector& rowsOnLeft, + const std::vector& rowsOnRight, + Zstring& lastUsedPath, + std::vector& folderPathHistory, + size_t historySizeMax, + bool& keepRelPaths, + bool& overwriteIfExists) +{ + + auto folderHistory = std::make_shared(folderPathHistory, historySizeMax); + + CopyToDialog dlg(parent, rowsOnLeft, rowsOnRight, lastUsedPath, folderHistory, keepRelPaths, overwriteIfExists); + const auto rc = static_cast(dlg.ShowModal()); + + folderPathHistory = folderHistory->getList(); //unconditionally write path history: support manual item deletion + cancel + return rc; +} + +//######################################################################################## + class DeleteDialog : public DeleteDlgGenerated { public: @@ -279,7 +413,7 @@ DeleteDialog::DeleteDialog(wxWindow* parent, m_checkBoxUseRecycler->SetValue(useRecycleBin); -#ifndef __WXGTK__ //wxWidgets holds portability promise by not supporting for multi-line controls...not +#ifndef __WXGTK__ //wxWidgets holds portability promise by supporting multi-line controls...not m_textCtrlFileList->SetMaxLength(0); //allow large entries! #endif @@ -300,8 +434,8 @@ void DeleteDialog::updateGui() wxWindowUpdateLocker dummy(this); //leads to GUI corruption problems on Linux/OS X! #endif - const std::pair delInfo = zen::deleteFromGridAndHDPreview(rowsToDeleteOnLeft, - rowsToDeleteOnRight); + const std::pair delInfo = zen::getSelectedItemsAsString(rowsToDeleteOnLeft, + rowsToDeleteOnRight); wxString header; if (m_checkBoxUseRecycler->GetValue()) { @@ -318,8 +452,7 @@ void DeleteDialog::updateGui() m_buttonOK->SetLabel(_("Delete")); } m_staticTextHeader->SetLabel(header); - //it seems like Wrap() needs to be reapplied after SetLabel() - m_staticTextHeader->Wrap(460); + m_staticTextHeader->Wrap(460); //needs to be reapplied after SetLabel() m_textCtrlFileList->ChangeValue(delInfo.first); /* @@ -361,10 +494,7 @@ ReturnSmallDlg::ButtonPressed zen::showDeleteDialog(wxWindow* parent, const std::vector& rowsOnRight, bool& useRecycleBin) { - DeleteDialog confirmDeletion(parent, - rowsOnLeft, - rowsOnRight, - useRecycleBin); + DeleteDialog confirmDeletion(parent, rowsOnLeft, rowsOnRight, useRecycleBin); return static_cast(confirmDeletion.ShowModal()); } @@ -498,18 +628,17 @@ OptionsDlg::OptionsDlg(wxWindow* parent, xmlAccess::XmlGlobalSettings& globalSet #endif setStandardButtonLayout(*bSizerStdButtons, StdButtons().setAffirmative(m_buttonOkay).setCancel(m_buttonCancel)); - warn_static("remove after test") - //#ifdef ZEN_MAC - // SetTitle(_("Preferences")); //follow OS conventions - //#endif +#ifdef ZEN_MAC + SetTitle(replaceCpy(_("&Preferences"), L"&", L"")); //follow OS conventions +#endif //setMainInstructionFont(*m_staticTextHeader); m_gridCustomCommand->SetTabBehaviour(wxGrid::Tab_Leave); - m_bitmapSettings ->SetBitmap (getResourceImage(L"settings")); - m_bpButtonAddRow ->SetBitmapLabel(getResourceImage(L"item_add")); - m_bpButtonRemoveRow ->SetBitmapLabel(getResourceImage(L"item_remove")); + m_bitmapSettings ->SetBitmap (getResourceImage(L"settings")); + m_bpButtonAddRow ->SetBitmapLabel(getResourceImage(L"item_add")); + m_bpButtonRemoveRow->SetBitmapLabel(getResourceImage(L"item_remove")); setBitmapTextLabel(*m_buttonResetDialogs, getResourceImage(L"reset_dialogs").ConvertToImage(), m_buttonResetDialogs->GetLabel()); m_checkBoxFailSafe ->SetValue(globalSettings.failsafeFileCopy); diff --git a/FreeFileSync/Source/ui/small_dlgs.h b/FreeFileSync/Source/ui/small_dlgs.h index 8b890f83..d45e1688 100644 --- a/FreeFileSync/Source/ui/small_dlgs.h +++ b/FreeFileSync/Source/ui/small_dlgs.h @@ -28,6 +28,15 @@ void showAboutDialog(wxWindow* parent); ReturnSmallDlg::ButtonPressed showFilterDialog(wxWindow* parent, FilterConfig& filter, const wxString& caption); +ReturnSmallDlg::ButtonPressed showCopyToDialog(wxWindow* parent, + const std::vector& rowsOnLeft, + const std::vector& rowsOnRight, + Zstring& lastUsedPath, + std::vector& folderPathHistory, + size_t historySizeMax, + bool& keepRelPaths, + bool& overwriteIfExists); + ReturnSmallDlg::ButtonPressed showDeleteDialog(wxWindow* parent, const std::vector& rowsOnLeft, const std::vector& rowsOnRight, diff --git a/FreeFileSync/Source/ui/sorting.h b/FreeFileSync/Source/ui/sorting.h index 0f8dfb22..83d06c1a 100644 --- a/FreeFileSync/Source/ui/sorting.h +++ b/FreeFileSync/Source/ui/sorting.h @@ -131,9 +131,9 @@ template inline bool lessFiletime(const FileSystemObject& a, const FileSystemObject& b) { if (a.isEmpty()) - return false; //empty rows always last + return false; //empty rows always last else if (b.isEmpty()) - return true; //empty rows always last + return true; //empty rows always last const FilePair* fileObjA = dynamic_cast(&a); const FilePair* fileObjB = dynamic_cast(&b); @@ -144,7 +144,7 @@ bool lessFiletime(const FileSystemObject& a, const FileSystemObject& b) if (!fileObjA && !linkObjA) return false; //directories last else if (!fileObjB && !linkObjB) - return true; //directories last + return true; //directories last const std::int64_t dateA = fileObjA ? fileObjA->getLastWriteTime() : linkObjA->getLastWriteTime(); const std::int64_t dateB = fileObjB ? fileObjB->getLastWriteTime() : linkObjB->getLastWriteTime(); @@ -158,14 +158,14 @@ template inline bool lessExtension(const FileSystemObject& a, const FileSystemObject& b) { if (a.isEmpty()) - return false; //empty rows always last + return false; //empty rows always last else if (b.isEmpty()) - return true; //empty rows always last + return true; //empty rows always last if (dynamic_cast(&a)) return false; //directories last else if (dynamic_cast(&b)) - return true; //directories last + return true; //directories last auto getExtension = [&](const FileSystemObject& fsObj) -> Zstring { diff --git a/FreeFileSync/Source/ui/sync_cfg.cpp b/FreeFileSync/Source/ui/sync_cfg.cpp index 950e8f4e..a4aa7f30 100644 --- a/FreeFileSync/Source/ui/sync_cfg.cpp +++ b/FreeFileSync/Source/ui/sync_cfg.cpp @@ -212,7 +212,7 @@ ConfigDialog::ConfigDialog(wxWindow* parent, miscCfgOut(miscCfg), handleDeletion(DELETE_TO_RECYCLER), // onGuiError(ON_GUIERROR_POPUP), //dummy init - versioningFolder(*m_panelVersioning, *m_buttonSelectDirVersioning, *m_bpButtonSelectSftp, *m_versioningFolder/*, m_staticTextResolvedPath*/) + versioningFolder(*m_panelVersioning, *m_buttonSelectDirVersioning, *m_bpButtonSelectSftp, *m_versioningFolder, nullptr /*staticText*/, nullptr /*wxWindow*/) { #ifdef ZEN_WIN new zen::MouseMoveWindow(*this); //allow moving main dialog by clicking (nearly) anywhere...; ownership passed to "this" @@ -387,12 +387,15 @@ void ConfigDialog::onLocalKeyEvent(wxKeyEvent& event) //process key events witho { case WXK_F6: m_notebook->ChangeSelection(static_cast(SyncConfigPanel::COMPARISON)); + m_buttonOkay->SetFocus(); return; //handled! case WXK_F7: m_notebook->ChangeSelection(static_cast(SyncConfigPanel::FILTER)); + m_buttonOkay->SetFocus(); return; case WXK_F8: m_notebook->ChangeSelection(static_cast(SyncConfigPanel::SYNC)); + m_buttonOkay->SetFocus(); return; } @@ -740,7 +743,7 @@ void toggleDeletionPolicy(DeletionPolicy& deletionPolicy) void ConfigDialog::setSyncOptions(const SyncOptions& so) { - directionCfg = so.syncCfg.directionCfg; //make working copy; ownership *not* on GUI + directionCfg = so.syncCfg.directionCfg; //make working copy; ownership *not* on GUI handleDeletion = so.syncCfg.handleDeletion; versioningFolder.setPath(so.syncCfg.versioningFolderPhrase); diff --git a/FreeFileSync/Source/ui/sync_cfg.h b/FreeFileSync/Source/ui/sync_cfg.h index b560c7ac..98b22181 100644 --- a/FreeFileSync/Source/ui/sync_cfg.h +++ b/FreeFileSync/Source/ui/sync_cfg.h @@ -29,16 +29,24 @@ enum class SyncConfigPanel SYNC = 2, // }; -struct MiscGlobalCfg +struct MiscGlobalCfg //don't use references to allow distinct copies { - xmlAccess::OnGuiError& handleError; //in/out param - - Zstring& onCompletionCommand; // - std::vector& onCompletionHistory; + xmlAccess::OnGuiError handleError; //in/out param + Zstring onCompletionCommand; // + std::vector onCompletionHistory; size_t onCompletionHistoryMax; }; +inline +bool operator==(const MiscGlobalCfg& lhs, const MiscGlobalCfg& rhs) +{ + return lhs.handleError == rhs.handleError && + lhs.onCompletionCommand == rhs.onCompletionCommand && + lhs.onCompletionHistory == rhs.onCompletionHistory && + lhs.onCompletionHistoryMax == rhs.onCompletionHistoryMax; +} + ReturnSyncConfig::ButtonPressed showSyncConfigDlg(wxWindow* parent, SyncConfigPanel panelToShow, bool* useAlternateCmpCfg, //optional parameter diff --git a/FreeFileSync/Source/ui/taskbar.cpp b/FreeFileSync/Source/ui/taskbar.cpp index a41eb1fe..b12d6a06 100644 --- a/FreeFileSync/Source/ui/taskbar.cpp +++ b/FreeFileSync/Source/ui/taskbar.cpp @@ -36,14 +36,24 @@ public: if (!win7OrLater()) //check *before* trying to load DLL throw TaskbarNotAvailable(); + freeString_ = DllFun(getDllName(), funName_freeString); setStatus_ = DllFun(getDllName(), funName_setStatus); setProgress_ = DllFun(getDllName(), funName_setProgress); - if (!assocWindow || !setStatus_ || !setProgress_) + if (!assocWindow || !freeString_ || !setStatus_ || !setProgress_) throw TaskbarNotAvailable(); } - ~Pimpl() { setStatus_(assocWindow, tbseven::STATUS_NOPROGRESS); } + ~Pimpl() + { + const wchar_t* errorMsg = nullptr; + setStatus_(assocWindow, tbseven::STATUS_NOPROGRESS, errorMsg); + if (errorMsg) + { + ZEN_ON_SCOPE_EXIT(freeString_(errorMsg)); + assert(false); + } + } void setStatus(Status status) { @@ -64,16 +74,30 @@ public: break; } - setStatus_(assocWindow, tbSevenStatus); + const wchar_t* errorMsg = nullptr; + setStatus_(assocWindow, tbSevenStatus, errorMsg); + if (errorMsg) + { + ZEN_ON_SCOPE_EXIT(freeString_(errorMsg)); + assert(false); + } } void setProgress(double fraction) { - setProgress_(assocWindow, fraction * 100000, 100000); + const wchar_t* errorMsg = nullptr; + setProgress_(assocWindow, fraction * 100000, 100000, errorMsg); + if (errorMsg) + { + ZEN_ON_SCOPE_EXIT(freeString_(errorMsg)); + assert(false); + } } private: void* const assocWindow; //HWND + + DllFun freeString_; DllFun setStatus_; DllFun setProgress_; }; diff --git a/FreeFileSync/Source/ui/tree_view.h b/FreeFileSync/Source/ui/tree_view.h index aa7f07b0..1c511135 100644 --- a/FreeFileSync/Source/ui/tree_view.h +++ b/FreeFileSync/Source/ui/tree_view.h @@ -116,9 +116,9 @@ private: firstFileId(nullptr) {} std::uint64_t bytesGross; - std::uint64_t bytesNet; //bytes for files on view in this directory only + std::uint64_t bytesNet; //bytes for files on view in this directory only int itemCountGross; - int itemCountNet; //number of files on view for in this directory only + int itemCountNet; //number of files on view for in this directory only std::vector subDirs; FileSystemObject::ObjectId firstFileId; //weak pointer to first FilePair or SymlinkPair diff --git a/FreeFileSync/Source/ui/wx_form_build_hide_warnings.h b/FreeFileSync/Source/ui/wx_form_build_hide_warnings.h deleted file mode 100644 index 679fb62f..00000000 --- a/FreeFileSync/Source/ui/wx_form_build_hide_warnings.h +++ /dev/null @@ -1,22 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * -// ************************************************************************** - -#ifndef WX_FORM_BUILD_230948324234234 -#define WX_FORM_BUILD_230948324234234 - -//pamper over wxFormBuilder "sub-optimal" code - -#ifdef __GNUC__ - #pragma GCC diagnostic ignored "-Wunused-variable" - #ifndef __clang__ //clang seems to define __GNUC__, but doesn't support this warning - #pragma GCC diagnostic ignored "-Wunused-but-set-variable" - #endif - -#elif defined _MSC_VER - #pragma warning(disable: 4189) -#endif - -#endif //WX_FORM_BUILD_230948324234234 diff --git a/FreeFileSync/Source/version/version.h b/FreeFileSync/Source/version/version.h index 0ac9ee9f..9f098a22 100644 --- a/FreeFileSync/Source/version/version.h +++ b/FreeFileSync/Source/version/version.h @@ -3,7 +3,7 @@ namespace zen { -const wchar_t ffsVersion[] = L"7.2"; //internal linkage! +const wchar_t ffsVersion[] = L"7.3"; //internal linkage! const wchar_t FFS_VERSION_SEPERATOR = L'.'; } diff --git a/wx+/file_drop.h b/wx+/file_drop.h index 2feef6e2..c9f2469c 100644 --- a/wx+/file_drop.h +++ b/wx+/file_drop.h @@ -28,7 +28,7 @@ namespace zen /* 1. setup a window to emit EVENT_DROP_FILE: - - simple file system paths: setupFileDrop + - simple file system paths: setupFileDrop - any shell paths with validation: setupShellItemDrop 2. register events: @@ -64,14 +64,14 @@ const wxEventType EVENT_DROP_FILE = impl::createNewEventType(); class FileDropEvent : public wxCommandEvent { public: - FileDropEvent(const std::vector& filesDropped) : wxCommandEvent(EVENT_DROP_FILE), filesDropped_(filesDropped) {} + FileDropEvent(const std::vector& droppedPaths) : wxCommandEvent(EVENT_DROP_FILE), droppedPaths_(droppedPaths) {} - const std::vector& getFiles() const { return filesDropped_; } + const std::vector& getPaths() const { return droppedPaths_; } private: wxEvent* Clone() const override { return new FileDropEvent(*this); } - const std::vector filesDropped_; + const std::vector droppedPaths_; }; typedef void (wxEvtHandler::*FileDropEventFunction)(FileDropEvent&); diff --git a/wx+/grid.cpp b/wx+/grid.cpp index 7573fcb9..b24fabdc 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -40,7 +40,15 @@ const int GridData::COLUMN_GAP_LEFT = 4; namespace { -//------------ Grid Constants -------------------------------- +//------------------------------ Grid Parameters -------------------------------- +wxColor getColorLabelText() { return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); } + +wxColor getColorLabelGradientFrom () { return wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); } +wxColor getColorLabelGradientTo () { return wxColour(200, 200, 200); } //light grey + +wxColor getColorLabelGradientFocusFrom() { return getColorLabelGradientFrom(); } +wxColor getColorLabelGradientFocusTo () { return getColorSelectionGradientFrom(); } + const double MOUSE_DRAG_ACCELERATION = 1.5; //unit: [rows / (pixel * sec)] -> same value as Explorer! const int DEFAULT_COL_LABEL_BORDER = 6; //top + bottom border in addition to label height //const int COLUMN_LABEL_BORDER = GridData::COLUMN_GAP_LEFT; @@ -50,12 +58,6 @@ const int ROW_LABEL_BORDER = 3; const int COLUMN_RESIZE_TOLERANCE = 6; //unit [pixel] const int COLUMN_FILL_GAP_TOLERANCE = 10; //enlarge column to fill full width when resizing -const wxColor COLOR_LABEL_GRADIENT_FROM = *wxWHITE; -const wxColor COLOR_LABEL_GRADIENT_TO = wxColour(200, 200, 200); //light grey - -const wxColor COLOR_LABEL_GRADIENT_FROM_FOCUS = COLOR_LABEL_GRADIENT_FROM; -const wxColor COLOR_LABEL_GRADIENT_TO_FOCUS = getColorSelectionGradientFrom(); - const wxColor colorGridLine = wxColour(192, 192, 192); //light grey const bool fillGapAfterColumns = true; //draw rows/column label to fill full window width; may become an instance variable some time? @@ -202,7 +204,7 @@ wxRect GridData::drawColumnLabelBorder(wxDC& dc, const wxRect& rect) //returns r //draw border (with gradient) { wxDCPenChanger dummy(dc, wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID)); - dc.GradientFillLinear(wxRect(rect.GetTopRight(), rect.GetBottomRight()), COLOR_LABEL_GRADIENT_FROM, dc.GetPen().GetColour(), wxSOUTH); + dc.GradientFillLinear(wxRect(rect.GetTopRight(), rect.GetBottomRight()), getColorLabelGradientFrom(), dc.GetPen().GetColour(), wxSOUTH); dc.DrawLine(rect.GetBottomLeft(), rect.GetBottomRight() + wxPoint(1, 0)); } @@ -213,15 +215,15 @@ wxRect GridData::drawColumnLabelBorder(wxDC& dc, const wxRect& rect) //returns r void GridData::drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool highlighted) { if (highlighted) - dc.GradientFillLinear(rect, COLOR_LABEL_GRADIENT_FROM_FOCUS, COLOR_LABEL_GRADIENT_TO_FOCUS, wxSOUTH); + dc.GradientFillLinear(rect, getColorLabelGradientFocusFrom(), getColorLabelGradientFocusTo(), wxSOUTH); else //regular background gradient - dc.GradientFillLinear(rect, COLOR_LABEL_GRADIENT_FROM, COLOR_LABEL_GRADIENT_TO, wxSOUTH); //clear overlapping cells + dc.GradientFillLinear(rect, getColorLabelGradientFrom(), getColorLabelGradientTo(), wxSOUTH); //clear overlapping cells } void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const wxString& text) { - wxDCTextColourChanger dummy(dc, *wxBLACK); //accessibility: always set both foreground AND background colors! + wxDCTextColourChanger dummy(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! drawTextLabelFitting(dc, text, rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); } @@ -384,17 +386,17 @@ private: { const wxRect& clientRect = GetClientRect(); - dc.GradientFillLinear(clientRect, COLOR_LABEL_GRADIENT_FROM, COLOR_LABEL_GRADIENT_TO, wxSOUTH); + dc.GradientFillLinear(clientRect, getColorLabelGradientFrom(), getColorLabelGradientTo(), wxSOUTH); dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW), 1, wxSOLID)); { - wxDCPenChanger dummy(dc, COLOR_LABEL_GRADIENT_FROM); + wxDCPenChanger dummy(dc, getColorLabelGradientFrom()); dc.DrawLine(clientRect.GetTopLeft(), clientRect.GetTopRight()); } - dc.GradientFillLinear(wxRect(clientRect.GetBottomLeft (), clientRect.GetTopLeft ()), COLOR_LABEL_GRADIENT_FROM, dc.GetPen().GetColour(), wxSOUTH); - dc.GradientFillLinear(wxRect(clientRect.GetBottomRight(), clientRect.GetTopRight()), COLOR_LABEL_GRADIENT_FROM, dc.GetPen().GetColour(), wxSOUTH); + dc.GradientFillLinear(wxRect(clientRect.GetBottomLeft (), clientRect.GetTopLeft ()), getColorLabelGradientFrom(), dc.GetPen().GetColour(), wxSOUTH); + dc.GradientFillLinear(wxRect(clientRect.GetBottomRight(), clientRect.GetTopRight()), getColorLabelGradientFrom(), dc.GetPen().GetColour(), wxSOUTH); dc.DrawLine(clientRect.GetBottomLeft(), clientRect.GetBottomRight()); @@ -470,12 +472,11 @@ private: void render(wxDC& dc, const wxRect& rect) override { - /* IsEnabled() vs IsThisEnabled() since wxWidgets 2.9.5: - void wxWindowBase::NotifyWindowOnEnableChange(), called from bool wxWindowBase::Enable(), has this buggy exception of NOT - refreshing child elements when disabling a IsTopLevel() dialog, e.g. when showing a modal dialog. + void wxWindowBase::NotifyWindowOnEnableChange(), called from bool wxWindowBase::Enable(), fails to refresh + child elements when disabling a IsTopLevel() dialog, e.g. when showing a modal dialog. The unfortunate effect on XP for using IsEnabled() when rendering the grid is that the user can move the modal dialog and *draw* with it on the background while the grid refreshes as disabled incrementally! @@ -513,8 +514,8 @@ private: void drawRowLabel(wxDC& dc, const wxRect& rect, size_t row) { //clearArea(dc, rect, getColorRowLabel()); - dc.GradientFillLinear(rect, COLOR_LABEL_GRADIENT_FROM, COLOR_LABEL_GRADIENT_TO, wxEAST); //clear overlapping cells - wxDCTextColourChanger dummy3(dc, *wxBLACK); //accessibility: always set both foreground AND background colors! + dc.GradientFillLinear(rect, getColorLabelGradientFrom(), getColorLabelGradientTo(), wxEAST); //clear overlapping cells + wxDCTextColourChanger dummy3(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors! //label text wxRect textRect = rect; @@ -673,9 +674,9 @@ private: if (activeMove && activeMove->isRealMove()) { if (col + 1 == activeMove->refColumnTo()) //handle pos 1, 2, .. up to "at end" position - dc.GradientFillLinear(wxRect(rect.GetTopRight(), rect.GetBottomRight() + wxPoint(-2, 0)), COLOR_LABEL_GRADIENT_FROM, *wxBLUE, wxSOUTH); + dc.GradientFillLinear(wxRect(rect.GetTopRight(), rect.GetBottomRight() + wxPoint(-2, 0)), getColorLabelGradientFrom(), *wxBLUE, wxSOUTH); else if (col == activeMove->refColumnTo() && col == 0) //pos 0 - dc.GradientFillLinear(wxRect(rect.GetTopLeft(), rect.GetBottomLeft() + wxPoint(2, 0)), COLOR_LABEL_GRADIENT_FROM, *wxBLUE, wxSOUTH); + dc.GradientFillLinear(wxRect(rect.GetTopLeft(), rect.GetBottomLeft() + wxPoint(2, 0)), getColorLabelGradientFrom(), *wxBLUE, wxSOUTH); } } } @@ -2050,6 +2051,13 @@ void Grid::scrollTo(size_t row) } + bool Grid::Enable(bool enable) + { + Refresh(); + return wxScrolledWindow::Enable(enable); + } + + size_t Grid::getGridCursor() const { return mainWin_->getCursor(); diff --git a/wx+/grid.h b/wx+/grid.h index 76ee383a..8523b698 100644 --- a/wx+/grid.h +++ b/wx+/grid.h @@ -192,7 +192,8 @@ public: void scrollTo(size_t row); void Refresh(bool eraseBackground = true, const wxRect* rect = nullptr) override; - bool Enable( bool enable = true) override { Refresh(); return wxScrolledWindow::Enable(enable); } + bool Enable(bool enable = true) override; + //############################################################################################################ private: @@ -234,11 +235,11 @@ private: std::vector get() const { - std::vector selection; + std::vector result; for (size_t row = 0; row < rowSelectionValue.size(); ++row) if (rowSelectionValue[row] != 0) - selection.push_back(row); - return selection; + result.push_back(row); + return result; } void selectAll() { selectRange(0, rowSelectionValue.size(), true); } diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp index 9d4f2396..7383f620 100644 --- a/wx+/image_resources.cpp +++ b/wx+/image_resources.cpp @@ -42,10 +42,9 @@ class GlobalResources public: static GlobalResources& instance() { -#if defined _MSC_VER && _MSC_VER > 1800 -#error remove warning +#if defined _MSC_VER && _MSC_VER < 1900 +#error function scope static initialization is not yet thread-safe! #endif - //caveat: function scope static initialization is not thread-safe in VS 2010! => but we wouldn't use wxWidgets in combination with multithreading anyway! static GlobalResources inst; return inst; } diff --git a/wx+/tooltip.cpp b/wx+/tooltip.cpp index 91298db4..ea9852d3 100644 --- a/wx+/tooltip.cpp +++ b/wx+/tooltip.cpp @@ -73,7 +73,7 @@ void Tooltip::show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp) } tipWindow->GetSizer()->SetSizeHints(tipWindow); //~=Fit() + SetMinSize() - //Linux: Fit() seems to be somewhat broken => this needs to be called EVERY time inside show, not only if text or bmp change + //Linux: Fit() seems to be broken => this needs to be called EVERY time inside show, not only if text or bmp change const wxPoint newPos = wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft ? mousePos - wxPoint(30 + tipWindow->GetSize().GetWidth(), 0) : diff --git a/zen/async_task.h b/zen/async_task.h index 5c6f7f6e..d8f489a3 100644 --- a/zen/async_task.h +++ b/zen/async_task.h @@ -11,7 +11,6 @@ #include #include "thread.h" #include "scope_guard.h" -//#include "type_tools.h" namespace zen { @@ -19,25 +18,25 @@ namespace zen class AsyncTasks { public: - AsyncTasks() : inRecursion(false) {} + AsyncTasks() {} template - void add(Fun doAsync, Fun2 evalOnGui) - //equivalent to "evalOnGui(doAsync())" - // -> doAsync: the usual thread-safety requirements apply! + void add(Fun runAsync, Fun2 evalOnGui) + //equivalent to "evalOnGui(runAsync())" + // -> runAsync: the usual thread-safety requirements apply! // -> evalOnGui: no thread-safety concerns, but must only reference variables with greater-equal lifetime than the AsyncTask instance! { tasks.push_back(zen::runAsync([=]() -> std::function { - auto result = doAsync(); + auto result = runAsync(); return [=]{ evalOnGui(result); }; })); } template - void add2(Fun doAsync, Fun2 evalOnGui) //for evalOnGui taking no parameters + void add2(Fun runAsync, Fun2 evalOnGui) //for evalOnGui taking no parameters { - tasks.push_back(zen::runAsync([doAsync, evalOnGui]() -> std::function { doAsync(); return [evalOnGui]{ evalOnGui(); }; })); + tasks.push_back(zen::runAsync([runAsync, evalOnGui]() -> std::function { runAsync(); return [evalOnGui]{ evalOnGui(); }; })); } void evalResults() //call from gui thread repreatedly @@ -47,9 +46,9 @@ public: inRecursion = true; ZEN_ON_SCOPE_EXIT(inRecursion = false); - tasks.remove_if([](boost::unique_future>& ft) -> bool + tasks.remove_if([](std::future>& ft) -> bool { - if (ft.is_ready()) + if (isReady(ft)) { (ft.get())(); return true; @@ -62,8 +61,11 @@ public: bool empty() const { return tasks.empty(); } private: - bool inRecursion; - std::list>> tasks; + AsyncTasks (const AsyncTasks&) = delete; + AsyncTasks& operator=(const AsyncTasks&) = delete; + + bool inRecursion = false; + std::list>> tasks; }; } diff --git a/zen/dir_watcher.cpp b/zen/dir_watcher.cpp index e93e2b06..4abf3c0a 100644 --- a/zen/dir_watcher.cpp +++ b/zen/dir_watcher.cpp @@ -7,7 +7,7 @@ #include "dir_watcher.h" #include #include -#include "thread.h" //includes +#include "thread.h" #include "scope_guard.h" #ifdef ZEN_WIN @@ -16,8 +16,11 @@ #include "long_path_prefix.h" #elif defined ZEN_LINUX + #include #include - #include + #include //fcntl + #include //close + #include //NAME_MAX #include "file_traverser.h" #elif defined ZEN_MAC @@ -37,7 +40,7 @@ public: //context of worker thread void addChanges(const char* buffer, DWORD bytesWritten, const Zstring& dirpath) //throw () { - boost::lock_guard dummy(lockAccess); + std::lock_guard dummy(lockAccess); if (bytesWritten == 0) //according to docu this may happen in case of internal buffer overflow: report some "dummy" change changedFiles.emplace_back(DirWatcher::ACTION_CREATE, L"Overflow."); @@ -89,7 +92,7 @@ public: ////context of main thread //void addChange(const Zstring& dirpath) //throw () //{ - // boost::lock_guard dummy(lockAccess); + // std::lock_guard dummy(lockAccess); // changedFiles.insert(dirpath); //} @@ -97,7 +100,7 @@ public: //context of main thread void fetchChanges(std::vector& output) //throw FileError { - boost::lock_guard dummy(lockAccess); + std::lock_guard dummy(lockAccess); //first check whether errors occurred in thread if (errorInfo) @@ -115,7 +118,7 @@ public: //context of worker thread void reportError(const std::wstring& msg, const std::wstring& description, DWORD errorCode) //throw() { - boost::lock_guard dummy(lockAccess); + std::lock_guard dummy(lockAccess); ErrorInfo newInfo = { copyStringTo(msg), copyStringTo(description), errorCode }; errorInfo = make_unique(newInfo); @@ -124,7 +127,7 @@ public: private: typedef Zbase BasicWString; //thread safe string class for UI texts - boost::mutex lockAccess; + std::mutex lockAccess; std::vector changedFiles; struct ErrorInfo @@ -174,13 +177,13 @@ public: ::CloseHandle(hDir); } - void operator()() //thread entry + void operator()() const //thread entry { std::vector buffer(64 * 1024); //needs to be aligned on a DWORD boundary; maximum buffer size restricted by some networks protocols (according to docu) for (;;) { - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption //actual work OVERLAPPED overlapped = {}; @@ -244,7 +247,7 @@ public: ::SleepEx(50, // __in DWORD dwMilliseconds, true); // __in BOOL bAlertable - boost::this_thread::interruption_point(); + interruptionPoint(); //throw ThreadInterruption } guardAio.dismiss(); @@ -271,7 +274,7 @@ class HandleVolumeRemoval public: HandleVolumeRemoval(HANDLE hDir, const Zstring& displayPath, - boost::thread& worker) : + InterruptibleThread& worker) : notificationHandle(registerFolderRemovalNotification(hDir, //throw FileError displayPath, [this] { this->onRequestRemoval (); }, //noexcept! @@ -307,7 +310,7 @@ private: void onRemovalFinished() { operationComplete = true; } //noexcept! DeviceNotificationHandle* notificationHandle; - boost::thread& worker_; + InterruptibleThread& worker_; bool removalRequested; bool operationComplete; }; @@ -316,7 +319,7 @@ private: struct DirWatcher::Pimpl { - boost::thread worker; + InterruptibleThread worker; std::shared_ptr shared; std::unique_ptr volRemoval; }; @@ -330,7 +333,7 @@ DirWatcher::DirWatcher(const Zstring& dirPath) : //throw FileError ReadChangesAsync reader(dirPath, pimpl_->shared); //throw FileError pimpl_->volRemoval = zen::make_unique(reader.getDirHandle(), dirPath, pimpl_->worker); //throw FileError - pimpl_->worker = boost::thread(std::move(reader)); + pimpl_->worker = InterruptibleThread(std::move(reader)); } @@ -339,10 +342,8 @@ DirWatcher::~DirWatcher() if (pimpl_->worker.joinable()) //= thread::detach() precondition! -> may already be joined by HandleVolumeRemoval::onRequestRemoval() { pimpl_->worker.interrupt(); - //if (pimpl_->worker.joinable()) pimpl_->worker.join(); -> we don't have time to wait... will take ~50ms anyway - pimpl_->worker.detach(); //we have to be explicit since C++11: [thread.thread.destr] ~thread() calls std::terminate() if joinable()!!! + pimpl_->worker.detach(); //we don't have time to wait... will take ~50ms anyway: } - //caveat: exitting the app may simply kill this thread! } @@ -355,13 +356,13 @@ std::vector DirWatcher::getChanges(const std::functionvolRemoval->requestReceived()) { - const boost::chrono::steady_clock::time_point endTime = boost::chrono::steady_clock::now() + boost::chrono::seconds(15); + const std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + std::chrono::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::chrono::steady_clock::now() < endTime) + while (!pimpl_->volRemoval->finished() && std::chrono::steady_clock::now() < endTime) { processGuiMessages(); //DBT_DEVICEREMOVECOMPLETE message is sent here! - boost::this_thread::sleep_for(boost::chrono::milliseconds(50)); //throw boost::thread_interrupted + std::this_thread::sleep_for(std::chrono::milliseconds(50)); } output.emplace_back(ACTION_DELETE, baseDirPath); //report removal as change to main directory diff --git a/zen/file_access.cpp b/zen/file_access.cpp index 09a1eb07..84d3b264 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -434,26 +434,29 @@ void renameFile_sub(const Zstring& pathSource, const Zstring& pathTarget) //thro if (lastError == ERROR_NOT_SAME_DEVICE) throw ErrorDifferentVolume(errorMsg, errorDescr); - else if (lastError == ERROR_ALREADY_EXISTS || //-> used on Win7 x64 + if (lastError == ERROR_ALREADY_EXISTS || //-> used on Win7 x64 lastError == ERROR_FILE_EXISTS) //-> used by XP??? throw ErrorTargetExisting(errorMsg, errorDescr); - else - throw FileError(errorMsg, errorDescr); + throw FileError(errorMsg, errorDescr); } #elif defined ZEN_LINUX || defined ZEN_MAC - if (::rename(pathSource.c_str(), pathTarget.c_str()) != 0) + //rename() will never fail with EEXIST, but always overwrite! + //=> OS X: no solution + //=> Linux: renameat2() with RENAME_NOREPLACE -> still new, probably buggy + const bool alreadyExists = somethingExists(pathTarget); //we have to let go of atomicity! + + if (alreadyExists || ::rename(pathSource.c_str(), pathTarget.c_str()) != 0) { - const int lastError = errno; //copy before directly or indirectly making other system calls! + const int lastError = alreadyExists ? EEXIST : errno; //copy before directly or indirectly making other system calls! const std::wstring errorMsg = replaceCpy(replaceCpy(_("Cannot move file %x to %y."), L"%x", L"\n" + fmtPath(pathSource)), L"%y", L"\n" + fmtPath(pathTarget)); const std::wstring errorDescr = formatSystemError(L"rename", lastError); if (lastError == EXDEV) throw ErrorDifferentVolume(errorMsg, errorDescr); - else if (lastError == EEXIST) - throw ErrorTargetExisting(errorMsg, errorDescr); - else - throw FileError(errorMsg, errorDescr); + if (lastError == EEXIST) + throw ErrorTargetExisting(errorMsg, errorDescr); + throw FileError(errorMsg, errorDescr); } #endif } @@ -2039,12 +2042,6 @@ DWORD CALLBACK copyCallbackInternal(LARGE_INTEGER totalFileSize, return PROGRESS_CONTINUE; } -#if defined _MSC_VER && _MSC_VER > 1800 - #error get rid! -#endif -const bool supportNonEncryptedDestination = winXpOrLater(); //encrypted destination is not supported with Windows 2000 -//caveat: function scope static initialization is not thread-safe in VS 2010! -> still not sufficient if multiple threads access during static init!!! - InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileError, ErrorTargetExisting, ErrorFileLocked, ErrorFallbackToCopyAsBackupStream const Zstring& targetFile, @@ -2062,8 +2059,8 @@ InSyncAttributes copyFileWindowsDefault(const Zstring& sourceFile, //throw FileE DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS; - if (supportNonEncryptedDestination) - copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION; //allow copying from encrypted to non-encrypted location + //encrypted destination is not supported with Windows 2000! -> whatever + copyFlags |= COPY_FILE_ALLOW_DECRYPTED_DESTINATION; //allow copying from encrypted to non-encrypted location //if (vistaOrLater()) //see http://blogs.technet.com/b/askperf/archive/2007/05/08/slow-large-file-copy-issues.aspx // copyFlags |= COPY_FILE_NO_BUFFERING; //no perf difference at worst, improvement for large files (20% in test NTFS -> NTFS) diff --git a/zen/format_unit.cpp b/zen/format_unit.cpp index 5f529f9c..9624458c 100644 --- a/zen/format_unit.cpp +++ b/zen/format_unit.cpp @@ -190,7 +190,10 @@ public: private: static const IntegerFormat& getInst() { - static IntegerFormat inst; //not threadsafe in MSVC until C++11, but not required right now +#if defined _MSC_VER && _MSC_VER < 1900 +#error function scope static initialization is not yet thread-safe! +#endif + static IntegerFormat inst; return inst; } @@ -276,14 +279,6 @@ std::wstring zen::ffs_Impl::includeNumberSeparator(const std::wstring& number) } -#ifdef ZEN_WIN -namespace -{ -const bool useNewLocalTimeCalculation = zen::vistaOrLater(); -} -#endif - - std::wstring zen::utcToLocalTimeString(std::int64_t utcTime) { auto errorMsg = [&] { return _("Error") + L" (time_t: " + numberTo(utcTime) + L")"; }; @@ -293,6 +288,11 @@ std::wstring zen::utcToLocalTimeString(std::int64_t utcTime) SYSTEMTIME systemTimeLocal = {}; +#if defined _MSC_VER && _MSC_VER < 1900 +#error function scope static initialization is not yet thread-safe! +#endif + static const bool useNewLocalTimeCalculation = zen::vistaOrLater(); + //http://msdn.microsoft.com/en-us/library/ms724277(VS.85).aspx if (useNewLocalTimeCalculation) //DST conversion like in Windows 7: NTFS stays fixed, but FAT jumps by one hour { diff --git a/zen/guid.h b/zen/guid.h index 2ebfa132..d4b59eb4 100644 --- a/zen/guid.h +++ b/zen/guid.h @@ -10,7 +10,7 @@ #include #include -#ifdef __GNUC__ //boost should start cleaning this mess up +#ifdef __GNUC__ //boost should clean this mess up #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wuninitialized" diff --git a/zen/long_path_prefix.h b/zen/long_path_prefix.h index f7ceb5e7..3db2722b 100644 --- a/zen/long_path_prefix.h +++ b/zen/long_path_prefix.h @@ -122,7 +122,6 @@ Zstring zen::ntPathToWin32Path(const Zstring& path) //noexcept const DWORD charsWritten = ::GetEnvironmentVariable(L"SystemRoot", //_In_opt_ LPCTSTR lpName, &buf[0], //_Out_opt_ LPTSTR lpBuffer, bufSize); //_In_ DWORD nSize - if (0 < charsWritten && charsWritten < bufSize) return replaceCpy(path, L"\\SystemRoot\\", appendSeparator(Zstring(&buf[0], charsWritten)), false); } diff --git a/zen/process_priority.cpp b/zen/process_priority.cpp index c5932900..577e33a6 100644 --- a/zen/process_priority.cpp +++ b/zen/process_priority.cpp @@ -5,7 +5,6 @@ // ************************************************************************** #include "process_priority.h" -//#include "sys_error.h" #include "i18n.h" #ifdef ZEN_WIN diff --git a/zen/recycler.cpp b/zen/recycler.cpp index 6cd34a17..75083d57 100644 --- a/zen/recycler.cpp +++ b/zen/recycler.cpp @@ -187,7 +187,7 @@ bool zen::recycleBinExists(const Zstring& dirpath, const std::function& &recInfo); //__inout LPSHQUERYRBINFO pSHQueryRBInfo }); - while (ft.wait_for(boost::chrono::milliseconds(50)) != boost::future_status::ready) + while (ft.wait_for(std::chrono::milliseconds(50)) != std::future_status::ready) if (onUpdateGui) onUpdateGui(); //may throw! diff --git a/zen/scope_guard.h b/zen/scope_guard.h index 8477c7ee..5e917853 100644 --- a/zen/scope_guard.h +++ b/zen/scope_guard.h @@ -8,8 +8,7 @@ #define ZEN_SCOPEGUARD_8971632487321434 #include -//#include //std::decay -//#include +#include //std::decay //best of Zen, Loki and C++11 diff --git a/zen/stl_tools.h b/zen/stl_tools.h index bd76e264..685f5118 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -9,7 +9,7 @@ #include #include -#include +#include "type_tools.h" //enhancements for @@ -22,6 +22,9 @@ void vector_remove_if(V& vec, Predicate p); template void vector_append(V& vec, const W& vec2); +template +void removeDuplicates(V& v); + template void set_append(V& s, const W& s2); @@ -72,6 +75,14 @@ void vector_remove_if(V& vec, Predicate p) } +template inline +void removeDuplicates(V& v) +{ + std::sort(v.begin(), v.end()); + v.erase(std::unique(v.begin(), v.end()), v.end()); +} + + template inline void vector_append(V& vec, const W& vec2) { diff --git a/zen/string_base.h b/zen/string_base.h index f4ca5f2e..1bf8ed68 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -195,11 +195,10 @@ private: struct Descriptor { Descriptor(size_t len, size_t cap) : - refCount(1), length (static_cast(len)), capacity(static_cast(cap)) { static_assert(ATOMIC_INT_LOCK_FREE == 2, ""); } //2: "the types are always lock-free" - std::atomic refCount; + std::atomic refCount { 1 }; //std:atomic is uninitialized by default! std::uint32_t length; std::uint32_t capacity; //allocated size without null-termination }; @@ -222,11 +221,13 @@ public: Zbase(const Char* source); //implicit conversion from a C-string Zbase(const Char* source, size_t length); Zbase(const Zbase& source); - Zbase(Zbase&& tmp); //make noexcept in C++11 + Zbase(Zbase&& tmp) noexcept; explicit Zbase(Char source); //dangerous if implicit: Char buffer[]; return buffer[0]; ups... forgot &, but not a compiler error! - //allow explicit construction from different string type, prevent ambiguity via SFINAE - template explicit Zbase(const S& other, typename S::value_type = 0); - ~Zbase(); //make noexcept in C++11 + +//allow explicit construction from different string type, prevent ambiguity via SFINAE +//template explicit Zbase(const S& other, typename S::value_type = 0); + + ~Zbase(); //operator const Char* () const; //NO implicit conversion to a C-string!! Many problems... one of them: if we forget to provide operator overloads, it'll just work with a Char*... @@ -263,11 +264,11 @@ public: Zbase& assign(const Char* source, size_t len); Zbase& append(const Char* source, size_t len); void resize(size_t newSize, Char fillChar = 0); - void swap(Zbase& other); //make noexcept in C++11 + void swap(Zbase& other); void push_back(Char val) { operator+=(val); } //STL access Zbase& operator=(const Zbase& source); - Zbase& operator=(Zbase&& tmp); //make noexcept in C++11 + Zbase& operator=(Zbase&& tmp) noexcept; Zbase& operator=(const Char* source); Zbase& operator=(Char source); Zbase& operator+=(const Zbase& other); @@ -377,14 +378,14 @@ Zbase::Zbase(const Zbase& source) template class SP, class AP> inline -Zbase::Zbase(Zbase&& tmp) +Zbase::Zbase(Zbase&& tmp) noexcept { rawStr = tmp.rawStr; tmp.rawStr = nullptr; //usually nullptr would violate the class invarants, but it is good enough for the destructor! //caveat: do not increment ref-count of an unshared string! We'd lose optimization opportunity of reusing its memory! } - +/* template class SP, class AP> template inline Zbase::Zbase(const S& other, typename S::value_type) @@ -394,11 +395,13 @@ Zbase::Zbase(const S& other, typename S::value_type) std::copy(other.c_str(), other.c_str() + sourceLen, rawStr); rawStr[sourceLen] = 0; } - +*/ template class SP, class AP> inline Zbase::~Zbase() { + static_assert(noexcept(this->~Zbase()), ""); //has exception spec of compiler-generated destructor by default + this->destroy(rawStr); //rawStr may be nullptr; see move constructor! } @@ -650,7 +653,7 @@ Zbase& Zbase::operator=(const Zbase& o template class SP, class AP> inline -Zbase& Zbase::operator=(Zbase&& tmp) +Zbase& Zbase::operator=(Zbase&& tmp) noexcept { swap(tmp); //don't use unifying assignment but save one move-construction in the r-value case instead! return *this; diff --git a/zen/string_tools.h b/zen/string_tools.h index c04adf96..9708464e 100644 --- a/zen/string_tools.h +++ b/zen/string_tools.h @@ -18,7 +18,7 @@ #include "stl_tools.h" #include "string_traits.h" - + //enhance arbitray string class with useful non-member functions: namespace zen { @@ -48,11 +48,11 @@ template void replace ( S& str, const T& oldT template S replaceCpy(const S& str, const T& oldTerm, const U& newTerm, bool replaceAll = true); //high-performance conversion between numbers and strings -template S printNumber(const T& format, const Num& number); //format a single number using std::snprintf() - template S numberTo(const Num& number); template Num stringTo(const S& str); +template S printNumber(const T& format, const Num& number); //format a single number using std::snprintf() + //string to string conversion: converts string-like type into char-compatible target string class template T copyStringTo(const S& str); diff --git a/zen/string_traits.h b/zen/string_traits.h index 5f91bdc4..add53d3a 100644 --- a/zen/string_traits.h +++ b/zen/string_traits.h @@ -7,6 +7,7 @@ #ifndef STRING_TRAITS_HEADER_813274321443234 #define STRING_TRAITS_HEADER_813274321443234 +#include //strlen #include "type_tools.h" //uniform access to string-like types, both classes and character arrays @@ -143,19 +144,22 @@ struct GetCharType : ResultType::CharTy namespace implementation { +//strlen/wcslen are vectorized since VS14 CTP3 +inline size_t cStringLength(const char* str) { return std::strlen(str); } +inline size_t cStringLength(const wchar_t* str) { return std::wcslen(str); } + +//no significant perf difference for "comparison" test case between cStringLength/wcslen: +#if 0 template inline -size_t cStringLength(const C* str) //naive implementation seems somewhat faster than "optimized" strlen/wcslen! +size_t cStringLength(const C* str) { -#if defined _MSC_VER && _MSC_VER > 1800 - static_assert(false, "strlen/wcslen are vectorized in VS14 CTP3 -> test again!"); -#endif - static_assert(IsSameType::value || IsSameType::value, ""); size_t len = 0; while (*str++ != 0) ++len; return len; } +#endif template ::isStringClass>::Type> inline const typename GetCharType::Type* strBegin(const S& str) //SFINAE: T must be a "string" diff --git a/zen/symlink_target.h b/zen/symlink_target.h index c8c8c4be..aa320dfe 100644 --- a/zen/symlink_target.h +++ b/zen/symlink_target.h @@ -25,7 +25,7 @@ namespace zen { #ifdef ZEN_WIN - bool isSymlink(const WIN32_FIND_DATA& data); //*not* a simple FILE_ATTRIBUTE_REPARSE_POINT check! + bool isSymlink(const WIN32_FIND_DATA& data); //checking FILE_ATTRIBUTE_REPARSE_POINT is insufficient! bool isSymlink(DWORD fileAttributes, DWORD reparseTag); #endif @@ -162,8 +162,7 @@ Zstring getResolvedFilePath_impl(const Zstring& linkPath) //throw FileError const SysDllFun getFinalPathNameByHandle(L"kernel32.dll", "GetFinalPathNameByHandleW"); if (!getFinalPathNameByHandle) throw FileError(replaceCpy(_("Cannot determine final path for %x."), L"%x", fmtPath(linkPath)), replaceCpy(_("Cannot find system function %x."), L"%x", L"\"GetFinalPathNameByHandleW\"")); - - + const HANDLE hFile = ::CreateFile(applyLongPathPrefix(linkPath).c_str(), //_In_ LPCTSTR lpFileName, 0, //_In_ DWORD dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //_In_ DWORD dwShareMode, diff --git a/zen/thread.h b/zen/thread.h index 6d647de8..a3b8760b 100644 --- a/zen/thread.h +++ b/zen/thread.h @@ -4,39 +4,62 @@ // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** -#ifndef BOOST_THREAD_WRAP_H_78963234 -#define BOOST_THREAD_WRAP_H_78963234 - -//temporary solution until C++11 thread becomes fully available (considering std::thread's non-interruptibility and std::async craziness, this may be NEVER) -#include - -//workaround this pathetic boost thread warning mess -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wswitch-enum" - #pragma GCC diagnostic ignored "-Wstrict-aliasing" - #pragma GCC diagnostic ignored "-Wredundant-decls" - #pragma GCC diagnostic ignored "-Wshadow" - #ifndef __clang__ //clang defines __GNUC__, but doesn't support this warning - #pragma GCC diagnostic ignored "-Wunused-local-typedefs" - #endif -#endif -#ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4702 4913) //unreachable code; user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used -#endif +#ifndef STD_THREAD_WRAP_H_7896323423432 +#define STD_THREAD_WRAP_H_7896323423432 -#include - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif -#ifdef _MSC_VER - #pragma warning(pop) -#endif +#include +#include +#include +#include namespace zen { +class InterruptionStatus; + + +class InterruptibleThread +{ +public: + InterruptibleThread() {} + InterruptibleThread (InterruptibleThread&& tmp) = default; + InterruptibleThread& operator=(InterruptibleThread&& tmp) = default; + + template + InterruptibleThread(Function f); + + bool joinable () const { return stdThread.joinable(); } + void interrupt(); + void join () { stdThread.join(); } + void detach () { stdThread.detach(); } + + template + bool tryJoinFor(const std::chrono::duration& relTime) + { + if (threadCompleted.wait_for(relTime) == std::future_status::ready) + { + stdThread.join(); //runs thread-local destructors => this better be fast!!! + return true; + } + return false; + } + +private: + std::thread stdThread; + std::shared_ptr intStatus_; + std::future threadCompleted; +}; + +//context of worker thread: +void interruptionPoint(); //throw ThreadInterruption + +template +void interruptibleWait(std::condition_variable& cv, std::unique_lock& lock, Predicate pred); //throw ThreadInterruption + +template +void interruptibleSleep(const std::chrono::duration& relTime); //throw ThreadInterruption + +//------------------------------------------------------------------------------------------ + /* std::async replacement without crappy semantics: 1. guaranteed to run asynchronously @@ -45,16 +68,20 @@ std::async replacement without crappy semantics: Example: Zstring dirpath = ... auto ft = zen::runAsync([=](){ return zen::dirExists(dirpath); }); - if (ft.wait_for(boost::chrono::milliseconds(200)) == boost::future_status::ready && ft.get()) + if (ft.wait_for(std::chrono::milliseconds(200)) == std::future_status::ready && ft.get()) //dir exising */ template -auto runAsync(Function fun) -> boost::unique_future; +auto runAsync(Function fun) -> std::future; //wait for all with a time limit: return true if *all* results are available! template bool wait_for_all_timed(InputIterator first, InputIterator last, const Duration& wait_duration); +template inline +bool isReady(const std::future& f) { return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; } +//------------------------------------------------------------------------------------------ + //wait until first job is successful or all failed: substitute until std::when_any is available template class GetFirstResult @@ -77,6 +104,7 @@ private: size_t jobsTotal_; }; +//------------------------------------------------------------------------------------------ //value associated with mutex and guaranteed protected access: template @@ -89,7 +117,7 @@ public: template void access(Function fun) { - boost::lock_guard dummy(lockValue); + std::lock_guard dummy(lockValue); fun(value_); } @@ -97,7 +125,7 @@ private: Protected (const Protected&) = delete; Protected& operator=(const Protected&) = delete; - boost::mutex lockValue; + std::mutex lockValue; T value_; }; @@ -110,22 +138,15 @@ private: //###################### implementation ###################### -#ifndef BOOST_HAS_THREADS - #error just some paranoia check... -#endif template inline -auto runAsync(Function fun) -> boost::unique_future +auto runAsync(Function fun) -> std::future { typedef decltype(fun()) ResultType; -#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK //mirror "boost/thread/future.hpp", hopefully they know what they're doing - boost::packaged_task pt(std::move(fun)); -#else - boost::packaged_task pt(std::move(fun)); -#endif + std::packaged_task pt(std::move(fun)); auto fut = pt.get_future(); - boost::thread(std::move(pt)).detach(); //we have to explicitly detach since C++11: [thread.thread.destr] ~thread() calls std::terminate() if joinable()!!! + std::thread(std::move(pt)).detach(); //we have to explicitly detach since C++11: [thread.thread.destr] ~thread() calls std::terminate() if joinable()!!! return fut; } @@ -133,9 +154,9 @@ auto runAsync(Function fun) -> boost::unique_future template inline bool wait_for_all_timed(InputIterator first, InputIterator last, const Duration& duration) { - const boost::chrono::steady_clock::time_point endTime = boost::chrono::steady_clock::now() + duration; + const std::chrono::steady_clock::time_point endTime = std::chrono::steady_clock::now() + duration; for (; first != last; ++first) - if (first->wait_until(endTime) != boost::future_status::ready) + if (first->wait_until(endTime) != std::future_status::ready) return false; //time elapsed return true; } @@ -155,27 +176,26 @@ public: void reportFinished(std::unique_ptr&& result) { { - boost::lock_guard dummy(lockResult); + std::lock_guard dummy(lockResult); ++jobsFinished; if (!result_) result_ = std::move(result); } - conditionJobDone.notify_all(); //instead of notify_one(); workaround bug: https://svn.boost.org/trac/boost/ticket/7796 - //condition handling, see: http://www.boost.org/doc/libs/1_43_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref + conditionJobDone.notify_all(); //better notify all, considering bugs like: https://svn.boost.org/trac/boost/ticket/7796 } //context: main thread template bool waitForResult(size_t jobsTotal, const Duration& duration) { - boost::unique_lock dummy(lockResult); - return conditionJobDone.wait_for(dummy, duration, [&] { return this->jobDone(jobsTotal); }); //throw boost::thread_interrupted + std::unique_lock dummy(lockResult); + return conditionJobDone.wait_for(dummy, duration, [&] { return this->jobDone(jobsTotal); }); } std::unique_ptr getResult(size_t jobsTotal) { - boost::unique_lock dummy(lockResult); - conditionJobDone.wait(dummy, [&] { return this->jobDone(jobsTotal); }); //throw boost::thread_interrupted + std::unique_lock dummy(lockResult); + conditionJobDone.wait(dummy, [&] { return this->jobDone(jobsTotal); }); #ifndef NDEBUG assert(!returnedResult); @@ -191,10 +211,10 @@ private: bool returnedResult; #endif - boost::mutex lockResult; + std::mutex lockResult; size_t jobsFinished; // std::unique_ptr result_; //our condition is: "have result" or "jobsFinished == jobsTotal" - boost::condition_variable conditionJobDone; + std::condition_variable conditionJobDone; }; @@ -207,8 +227,7 @@ template template inline void GetFirstResult::addJob(Fun f) //f must return a std::unique_ptr containing a value on success { - auto asyncResult = this->asyncResult_; //capture member variable, not "this"! - boost::thread t([asyncResult, f] { asyncResult->reportFinished(f()); }); + std::thread t([asyncResult = this->asyncResult_, f = std::move(f)] { asyncResult->reportFinished(f()); }); ++jobsTotal_; t.detach(); //we have to be explicit since C++11: [thread.thread.destr] ~thread() calls std::terminate() if joinable()!!! } @@ -221,6 +240,158 @@ bool GetFirstResult::timedWait(const Duration& duration) const { return async template inline std::unique_ptr GetFirstResult::get() const { return asyncResult_->getResult(jobsTotal_); } + +//------------------------------------------------------------------------------------------ + +//thread_local with non-POD seems to cause memory leaks on VS 14 => pointer only is fine: +#ifdef _MSC_VER + #define ZEN_THREAD_LOCAL_SPECIFIER __declspec(thread) +#elif defined __GNUC__ || defined __clang__ + #define ZEN_THREAD_LOCAL_SPECIFIER __thread +#else + #error "game over" +#endif + + +class ThreadInterruption {}; + + +class InterruptionStatus +{ +public: + //context of InterruptibleThread instance: + void interrupt() + { + interrupted = true; + + { + std::lock_guard dummy(lockSleep); //needed! makes sure the following signal is not lost! + //usually we'd make "interrupted" non-atomic, but this is already given due to interruptibleWait() handling + } + conditionSleepInterruption.notify_all(); + + std::lock_guard dummy(lockConditionPtr); + if (activeCondition) + activeCondition->notify_all(); //signal may get lost! + //alternative design locking the cv's mutex here could be dangerous: potential for dead lock! + } + + //context of worker thread: + void checkInterruption() //throw ThreadInterruption + { + if (interrupted) + throw ThreadInterruption(); + } + + //context of worker thread: + template + void interruptibleWait(std::condition_variable& cv, std::unique_lock& lock, Predicate pred) //throw ThreadInterruption + { + setConditionVar(&cv); + ZEN_ON_SCOPE_EXIT(setConditionVar(nullptr)); + + //"interrupted" is not protected by cv's mutex => signal may get lost!!! => add artifical time out to mitigate! CPU: 0.25% vs 0% for longer time out! + while (!cv.wait_for(lock, std::chrono::milliseconds(1), [&] { return this->interrupted || pred(); })) + ; + + checkInterruption(); //throw ThreadInterruption + } + + //context of worker thread: + template + void interruptibleSleep(const std::chrono::duration& relTime) //throw ThreadInterruption + { + std::unique_lock lock(lockSleep); + if (conditionSleepInterruption.wait_for(lock, relTime, [&] { return static_cast(this->interrupted); })) + throw ThreadInterruption(); + } + +private: + void setConditionVar(std::condition_variable* cv) + { + std::lock_guard dummy(lockConditionPtr); + activeCondition = cv; + } + + std::atomic interrupted{ false }; //std:atomic is uninitialized by default! + + std::condition_variable* activeCondition = nullptr; + std::mutex lockConditionPtr; //serialize pointer access (only!) + + std::condition_variable conditionSleepInterruption; + std::mutex lockSleep; +}; + + +namespace impl +{ +inline +InterruptionStatus*& refThreadLocalInterruptionStatus() +{ + static ZEN_THREAD_LOCAL_SPECIFIER InterruptionStatus* threadLocalInterruptionStatus = nullptr; + return threadLocalInterruptionStatus; +} +} + +//context of worker thread: +inline +void interruptionPoint() //throw ThreadInterruption +{ + assert(impl::refThreadLocalInterruptionStatus()); + if (impl::refThreadLocalInterruptionStatus()) + impl::refThreadLocalInterruptionStatus()->checkInterruption(); //throw ThreadInterruption +} + + +//context of worker thread: +template inline +void interruptibleWait(std::condition_variable& cv, std::unique_lock& lock, Predicate pred) //throw ThreadInterruption +{ + assert(impl::refThreadLocalInterruptionStatus()); + if (impl::refThreadLocalInterruptionStatus()) + impl::refThreadLocalInterruptionStatus()->interruptibleWait(cv, lock, pred); + else + cv.wait(lock, pred); +} + +//context of worker thread: +template inline +void interruptibleSleep(const std::chrono::duration& relTime) //throw ThreadInterruption +{ + assert(impl::refThreadLocalInterruptionStatus()); + if (impl::refThreadLocalInterruptionStatus()) + impl::refThreadLocalInterruptionStatus()->interruptibleSleep(relTime); + else + std::this_thread::sleep_for(relTime); +} + + +template inline +InterruptibleThread::InterruptibleThread(Function f) : intStatus_(std::make_shared()) +{ + std::promise pFinished; + threadCompleted = pFinished.get_future(); + + stdThread = std::thread([f = std::move(f), + intStatus = this->intStatus_, + pFinished = std::move(pFinished)]() mutable + { + assert(!impl::refThreadLocalInterruptionStatus()); + impl::refThreadLocalInterruptionStatus() = intStatus.get(); + ZEN_ON_SCOPE_EXIT(impl::refThreadLocalInterruptionStatus() = nullptr); + ZEN_ON_SCOPE_EXIT(pFinished.set_value()); + + try + { + f(); //throw ThreadInterruption + } + catch (ThreadInterruption&) {} + }); +} + + +inline +void InterruptibleThread::interrupt() { intStatus_->interrupt(); } } -#endif //BOOST_THREAD_WRAP_H_78963234 +#endif //STD_THREAD_WRAP_H_7896323423432 diff --git a/zen/zstring.cpp b/zen/zstring.cpp index 8dcd4736..e2a756e6 100644 --- a/zen/zstring.cpp +++ b/zen/zstring.cpp @@ -43,22 +43,12 @@ time per call | function #ifdef ZEN_WIN namespace { -//warning: LOCALE_INVARIANT is NOT available with Windows 2000, so we have to make yet another distinction... -const LCID ZSTRING_INVARIANT_LOCALE = zen::winXpOrLater() ? - LOCALE_INVARIANT : - MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); //see: http://msdn.microsoft.com/en-us/goglobal/bb688122.aspx - //try to call "CompareStringOrdinal" for low-level string comparison: unfortunately available not before Windows Vista! //by a factor ~3 faster than old string comparison using "LCMapString" typedef int (WINAPI* CompareStringOrdinalFunc)(LPCWSTR lpString1, int cchCount1, LPCWSTR lpString2, int cchCount2, BOOL bIgnoreCase); const SysDllFun compareStringOrdinal = SysDllFun(L"kernel32.dll", "CompareStringOrdinal"); //watch for dependencies in global namespace!!! -//caveat: function scope static initialization is not thread-safe in VS 2010! -#if defined _MSC_VER && _MSC_VER > 1800 - #error not true anymore -#endif - } @@ -92,7 +82,7 @@ int cmpFilePath(const Zchar* lhs, size_t lhsLen, const Zchar* rhs, size_t rhsLen auto copyToUpperCase = [&](const wchar_t* strIn, wchar_t* strOut) { //faster than CharUpperBuff + wmemcpy or CharUpper + wmemcpy and same speed like ::CompareString() - if (::LCMapString(ZSTRING_INVARIANT_LOCALE, //__in LCID Locale, + if (::LCMapString(LOCALE_INVARIANT, //__in LCID Locale, LCMAP_UPPERCASE, //__in DWORD dwMapFlags, strIn, //__in LPCTSTR lpSrcStr, static_cast(minSize), //__in int cchSrc, @@ -138,13 +128,15 @@ Zstring makeUpperCopy(const Zstring& str) Zstring output; output.resize(len); + //LOCALE_INVARIANT is NOT available with Windows 2000 -> ok + //use Windows' upper case conversion: faster than ::CharUpper() - if (::LCMapString(ZSTRING_INVARIANT_LOCALE, //__in LCID Locale, - LCMAP_UPPERCASE, //__in DWORD dwMapFlags, - str.c_str(), //__in LPCTSTR lpSrcStr, - len, //__in int cchSrc, - &*output.begin(), //__out LPTSTR lpDestStr, - len) == 0) //__in int cchDest + if (::LCMapString(LOCALE_INVARIANT, //__in LCID Locale, + LCMAP_UPPERCASE, //__in DWORD dwMapFlags, + str.c_str(), //__in LPCTSTR lpSrcStr, + len, //__in int cchSrc, + &*output.begin(), //__out LPTSTR lpDestStr, + len) == 0) //__in int cchDest throw std::runtime_error("Error comparing strings (LCMapString). " + std::string(__FILE__) + ":" + numberTo(__LINE__)); return output; -- cgit