diff options
155 files changed, 35060 insertions, 14476 deletions
diff --git a/Application.cpp b/Application.cpp index eced6f8e..b1a4775f 100644 --- a/Application.cpp +++ b/Application.cpp @@ -19,6 +19,7 @@ #include "library/resources.h" #include "shared/standardPaths.h" #include "shared/localization.h" +#include "shared/appMain.h" #ifdef FFS_LINUX #include <gtk/gtk.h> @@ -46,6 +47,22 @@ void Application::OnStartApplication(wxIdleEvent& event) { Disconnect(wxEVT_IDLE, wxIdleEventHandler(Application::OnStartApplication), NULL, this); + struct HandleAppExit //wxWidgets app exit handling is a bit weird... we want the app to exit only if the logical main window is closed + { + HandleAppExit() + { + wxTheApp->SetExitOnFrameDelete(false); //avoid popup-windows from becoming temporary top windows leading to program exit after closure + } + + ~HandleAppExit() + { + if (!FreeFileSync::AppMainWindow::mainWindowWasSet()) + wxTheApp->ExitMainLoop(); //quit application, if no main window was set (batch silent mode) + } + + } dummy; + + //if appname is not set, the default is the executable's name! SetAppName(wxT("FreeFileSync")); @@ -83,21 +100,18 @@ void Application::OnStartApplication(wxIdleEvent& event) catch (const xmlAccess::XmlError& error) { if (wxFileExists(FreeFileSync::getGlobalConfigFile())) - { //show messagebox and continue - SetExitOnFrameDelete(false); //prevent error messagebox from becoming top-level window + { + //show messagebox and continue if (error.getSeverity() == xmlAccess::XmlError::WARNING) wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING); else wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); - SetExitOnFrameDelete(true); } //else: globalSettings already has default values } //set program language - SetExitOnFrameDelete(false); //prevent error messagebox from becoming top-level window CustomLocale::getInstance().setLanguage(globalSettings.programLanguage); - SetExitOnFrameDelete(true); if (!cfgFilename.empty()) @@ -112,9 +126,6 @@ void Application::OnStartApplication(wxIdleEvent& event) case xmlAccess::XML_BATCH_CONFIG: //start in commandline mode runBatchMode(cfgFilename, globalSettings); - - if (wxApp::GetTopWindow() == NULL) //if no windows are shown, program won't exit automatically - ExitMainLoop(); break; case xmlAccess::XML_GLOBAL_SETTINGS: @@ -145,9 +156,9 @@ int Application::OnRun() { //unfortunately it's not always possible to display a message box in this erroneous situation, however (non-stream) file output always works! wxFile safeOutput(FreeFileSync::getLastErrorTxtFile(), wxFile::write); - safeOutput.Write(wxString::From8BitData(e.what())); + safeOutput.Write(wxString::FromAscii(e.what())); - wxMessageBox(wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + wxMessageBox(wxString::FromAscii(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); return -9; } @@ -178,6 +189,9 @@ void Application::runGuiMode(const wxString& cfgFileName, xmlAccess::XmlGlobalSe MainDialog* frame = new MainDialog(NULL, cfgFileName, settings); frame->SetIcon(*GlobalResources::getInstance().programIcon); //set application icon frame->Show(); + + //notify about (logical) application main window + FreeFileSync::AppMainWindow::setMainWindow(frame); } @@ -205,17 +219,12 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet try //begin of synchronization process (all in one try-catch block) { - //set error handling for comparison: DON'T allow ignoring errors! Aborted file traversing can lead to data-loss when synchronizing! - const OnError compareErrHandling = batchCfg.handleError == ON_ERROR_IGNORE ? - ON_ERROR_EXIT : //in GUI mode ON_ERROR_EXIT means "showPopups = true" which is okay - batchCfg.handleError; - //class handling status updates and error messages std::auto_ptr<BatchStatusHandler> statusHandler; //delete object automatically if (batchCfg.silent) - statusHandler.reset(new BatchStatusHandlerSilent(compareErrHandling, batchCfg.logFileDirectory, returnValue)); + statusHandler.reset(new BatchStatusHandlerSilent(batchCfg.handleError, batchCfg.logFileDirectory, returnValue)); else - statusHandler.reset(new BatchStatusHandlerGui(compareErrHandling, returnValue)); + statusHandler.reset(new BatchStatusHandlerGui(batchCfg.handleError, returnValue)); //COMPARE DIRECTORIES FreeFileSync::FolderComparison folderCmp; @@ -229,9 +238,6 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet batchCfg.mainCfg.compareVar, folderCmp); - //set error handling for synchronization - statusHandler->setErrorStrategy(batchCfg.handleError); - //check if there are files/folders to be sync'ed at all if (!synchronizationNeeded(folderCmp)) { diff --git a/BUILD/Changelog.txt b/BUILD/Changelog.txt index 826950b0..391fc306 100644 --- a/BUILD/Changelog.txt +++ b/BUILD/Changelog.txt @@ -2,6 +2,24 @@ |FreeFileSync| -------------- +Changelog v3.0 +-------------- +New synchronization mode: <Automatic> +Consolidated batch mode error handling +Fixed crash when comparing multiple pairs by content +Fixed calculation of remaining objects +Fixed swapping grids +Show scanned files when traversing with filter enabled +New default filter values +New macros %time%, %date% for creating time-stamped directories +Avoid corrupted data when program is terminated unexpectedly +Prevent deletion when source-directory (temporarily) is not accessible +Native Unicode support for Linux build +Added Romanian translation +Added Turkish translation +Updated translation files + + Changelog v2.3 -------------- New filter and sync configuration at folder pair level @@ -13,7 +31,7 @@ Removed performance penalty when using include filters Improved filter syntax for strings beginning with wildcards Default handling for conflict files now configurable New option to show all hidden dialogs again -Fixed issue with makros %nameCo, %dirCo +Fixed issue with macros %nameCo, %dirCo New option in *.ffs_gui/ffs_batch files: Verify copied files Use Windows Volume Shadow Copy for shared and locked files(new) More detailed information in *.cvs export diff --git a/BUILD/Compress with UPX.cmd b/BUILD/Compress with UPX.cmd deleted file mode 100644 index c5f7dda2..00000000 --- a/BUILD/Compress with UPX.cmd +++ /dev/null @@ -1 +0,0 @@ -C:\Programme\C++\UPX\upx -9 --compress-icons=0 %1
\ No newline at end of file diff --git a/BUILD/Languages/chinese_simple.lng b/BUILD/Languages/chinese_simple.lng index cf9b3e11..6f41da3c 100644 --- a/BUILD/Languages/chinese_simple.lng +++ b/BUILD/Languages/chinese_simple.lng @@ -27,7 +27,7 @@ %x directories %x 目录 %x files, -%x 文件, +%x 个文件, %x is not a valid FreeFileSync batch file! %x ä¸æ˜¯æœ‰æ•ˆçš„ FreeFileSync 批处ç†æ–‡ä»¶ %x of %y rows in view @@ -69,9 +69,9 @@ &Load configuration åŠ è½½é…ç½®(&L) &New - +新建(&N) &No -å¦ +å¦(&N) &OK 确定(&O) &Pause @@ -85,15 +85,15 @@ &Save ä¿å˜(&S) &Yes -是 +是(&Y) (Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".) - +(请注æ„åªæœ‰FAT/FAT32分区å—æ¤é—®é¢˜å½±å“!\nåœ¨æ‰€æœ‰å…¶ä»–æƒ…å†µä¸‹ä½ å¯ç¦ç”¨\"忽略一å°æ—¶å·®å¼‚\"这一选项.) , . - Other side's counterpart to %dir - +- å¦ä¸€ä¾§å‚ç…§ %dir - Other side's counterpart to %name - +- å¦ä¸€ä¾§å‚ç…§ %name - conflict - å†²çª - conflict (same date, different size) @@ -138,6 +138,8 @@ 2. 使用通é…符‘*’和‘?’. 3. Exclude files directly on main grid via context menu. 3. 通过å³é”®èœå•åœ¨ä¸»ç½‘æ ¼æŽ’é™¤æ–‡ä»¶. +<Automatic> +自动 <Directory> <目录> <Last session> @@ -146,6 +148,8 @@ <多选> A newer version of FreeFileSync is available: FreeFileSync 有新版å¯ç”¨: +ATTENTION: Failed directory access can lead to file deletions! +请注æ„:失败的目录å˜å–ä¼šå¯¼è‡´æ–‡ä»¶åˆ é™¤! Abort requested: Waiting for current operation to finish... å–消请求: æ£åœ¨ç‰å¾…当å‰æ“作完æˆ... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp 装é…一个批处ç†æ–‡ä»¶ç”¨äºŽè‡ªåŠ¨åŒæ¥. è¦å¼€å§‹æ‰¹å¤„ç†æ¨¡å¼åªéœ€ç®€å•åœ°å°†æ‰¹å¤„ç†æ–‡ä»¶åä¼ é€ç»™FreeFileSyncå¯æ‰§è¡Œæ–‡ä»¶:FreeFileSync.exe <batchfile>. 这个也å¯ä»¥å®‰æŽ’在您的æ“作系统的计划任务ä¸. Auto-adjust columns 自动调整æ 宽 +Automatic mode +è‡ªåŠ¨æ¨¡å¼ Batch execution 批处ç†æ‰§è¡Œ Batch file created successfully! @@ -176,12 +182,20 @@ Batch job 批处ç†ä½œä¸š Big thanks for localizing FreeFileSync goes out to: éžå¸¸æ„Ÿè°¢ä»¥ä¸‹æœ¬åœ°åŒ– FreeFileSync 的工作人员: +Both sides have changed since last synchronization! +在最åŽçš„åŒæ¥ä¹‹åŽä¸¤è¾¹å‡å·²æ”¹å˜! Browse æµè§ˆ Build: å¼€å‘: Cancel å–消 +Cannot determine sync-direction: Changed filter settings! +ä¸èƒ½ç¡®å®šåŒæ¥æ–¹å‘: 过滤器设置已改å˜! +Cannot determine sync-direction: No change since last synchronization! +ä¸èƒ½ç¡®å®šåŒæ¥æ–¹å‘: 在最åŽåŒæ¥ä¹‹åŽæ²¡æœ‰æ”¹å˜! +Category +分类 Change direction 改å˜æ–¹å‘ Check all @@ -211,7 +225,7 @@ Comparing content of files %x Comparing content... æ£åœ¨æ¯”较文件内容... Comparing files by content failed. - +按文件内容比较失败. Comparison Result 比较结果 Comparison settings @@ -237,7 +251,7 @@ Confirm Conflict detected: 检测到冲çª: Conflicts/files that cannot be categorized - +冲çª/文件ä¸èƒ½è¢«å½’ç±» Continue ç»§ç» Conversion error: @@ -263,7 +277,7 @@ Could not determine volume name for file: Could not initialize directory monitoring: ä¸èƒ½åˆå§‹åŒ–目录监视: Could not read values for the following XML nodes: - +ä¸èƒ½ä»Žå¦‚下XML节点读å–数值: Create a batch job 创建一个批处ç†ä½œä¸š Creating folder %x @@ -277,19 +291,19 @@ Customize columns Customize... 自定义... D-Click - +åŒå‡» DECISION TREE 决ç–æ ‘ Data remaining: 剩余数æ®: Data verification error: Source and target file have different content! - +æ•°æ®æ ¡éªŒé”™è¯¯:æºæ–‡ä»¶å’Œç›®æ ‡æ–‡ä»¶å†…容ä¸åŒ! Date 日期 Delay 延时 Delay between detection of changes and execution of commandline in seconds - +在检测和执行命令行之间的延时秒数 Delete files/folders existing on left side only åˆ é™¤ä»…åœ¨å·¦ä¾§å˜åœ¨çš„文件/文件夹 Delete files/folders existing on right side only @@ -311,7 +325,7 @@ Deleting folder %x Deletion handling åˆ é™¤å¤„ç† Description - +æè¿° Directories are dependent! Be careful when setting up synchronization rules: 目录有ä¾èµ–性ï¼åœ¨è®¾ç«‹åŒæ¥è§„则时请å°å¿ƒ: Directories to watch @@ -376,6 +390,8 @@ Error reading file attributes: 读å–文件属性出错: Error reading file: 读å–文件出错: +Error reading from synchronization database: +从åŒæ¥æ•°æ®åº“ä¸è¯»å–时出错: Error resolving symbolic link: 解决符å·é“¾æŽ¥å‡ºé”™: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: 写文件属性出错: Error writing file: 写入文件出错: -Error: Source directory does not exist anymore: -错误:æºç›®å½•å·²ç»ä¸å˜åœ¨: +Error writing to synchronization database: +å‘åŒæ¥æ•°æ®åº“ä¸å†™å…¥æ—¶å‡ºé”™: +Source directory does not exist anymore: +æºç›®å½•å·²ç»ä¸å˜åœ¨: Example 例如 Exclude @@ -403,7 +421,7 @@ Exit immediately and set returncode < 0 Exit with RC < 0 退出并设置返回ç <0 External applications - +å¤–éƒ¨åº”ç”¨ç¨‹åº Feedback and suggestions are welcome at: 欢迎在下é¢æ出å馈æ„è§å’Œå»ºè®®: File %x has an invalid date! @@ -431,17 +449,17 @@ Files are found equal if\n - filesize\n - last write time and date\nare Files remaining: 剩余文件: Files that are equal on both sides - +ä¸¤è¾¹æ–‡ä»¶ç›¸åŒ Files that exist on both sides and have different content 两侧都有并且内容ä¸åŒçš„文件 Files that exist on both sides, left one is newer 两侧都有,左侧较新的文件 Files that exist on both sides, right one is newer 两侧都有,å³ä¾§è¾ƒæ–°çš„文件 +Files/folders found: +找到的文件/文件夹数: Files/folders remaining: 文件/文件夹剩余: -Files/folders scanned: -文件/文件夹已扫æ: Files/folders that exist on left side only 仅在左侧å˜åœ¨çš„文件/文件夹 Files/folders that exist on right side only @@ -457,7 +475,7 @@ Filter view Folder Comparison and Synchronization 文件夹比较与åŒæ¥ Free disk space available: - +å¯ç”¨ç£ç›˜ç©ºé—´: FreeFileSync - Folder Comparison and Synchronization FreeFileSync - 文件夹比较与åŒæ¥ FreeFileSync Batch Job @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync 已是最新! Full path 完整路径 +Generating database... +æ£åœ¨ç”Ÿæˆæ•°æ®åº“... Generating file list... 生æˆæ–‡ä»¶åˆ—表... Global settings @@ -479,7 +499,7 @@ Global settings Help 帮助 Hidden dialogs: - +éšè—对è¯æ¡†: Hide all error and warning messages éšè—所有错误与è¦å‘Šä¿¡æ¯ Hide conflicts @@ -505,9 +525,9 @@ Hide files that will be deleted on the left side Hide files that will be deleted on the right side éšè—将在å³ä¾§è¢«åˆ 除的文件 Hide files that will be overwritten on left side - +éšè—将在左侧被覆盖的文件 Hide files that will be overwritten on right side - +éšè—将在å³ä¾§è¢«è¦†ç›–的文件 Hide files that won't be copied éšè—å°†ä¸ä¼šè¢«å¤åˆ¶çš„文件 Hide filtered items @@ -536,20 +556,24 @@ Include temporarily 暂时包括 Include: *.doc;*.zip;*.exe\nExclude: temp\\* 包括: *.doc;*.zip;*.exe\n排除temp\\* +Incompatible synchronization database format: +ä¸å…¼å®¹çš„åŒæ¥æ•°æ®åº“æ ¼å¼: Info ä¿¡æ¯ Information ä¿¡æ¯ +Initial synchronization. Please verify default copy-directions! +åˆå§‹åŒ–åŒæ¥. è¯·æ ¡å¯¹é»˜è®¤çš„å¤åˆ¶æ–¹å‘! Integrate external applications into context menu. The following macros are available: - +集æˆå¤–部应用程åºåˆ°å³é”®èœå•. 如下å®å¯ç”¨: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) åˆå§‹åŒ–回收站是ä¸å¤§å¯èƒ½äº†!\n\nä¼°è®¡ä½ ä½¿ç”¨çš„ä¸æ˜¯Windows系统.\nå¦‚æžœä½ æƒ³åŒ…å«æ¤ç‰¹æ€§,请è”系作者. :) Leave as unresolved conflict - +é—ç•™ä¸ºæœªè§£å†³çš„å†²çª Left 左侧 Legend - +图例 Load configuration from file ä»Žæ–‡ä»¶åŠ è½½é…ç½® Load configuration history (press DEL to delete items) @@ -569,15 +593,17 @@ Move column down Move column up 上移一行 Move files to a user-defined directory. - +移动文件到用户定义的目录 Moving %x to Recycle Bin 移动 %x 到回收站 Moving file %x to user-defined directory %y - +移动文件 %x 到用户定义目录 %y Moving folder %x to user-defined directory %y - +移动文件夹 %x 到用户定义目录 %y Multiple... - +å€æ•°... +No database file existing yet: +还没有数æ®åº“文件å˜åœ¨: Not enough free disk space available in: 没有足够的å¯ç”¨ç£ç›˜ç©ºé—´ç”¨äºŽ: Nothing to synchronize according to configuration! @@ -591,7 +617,13 @@ Number of files that will be overwritten OK 确定 Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. - +åªæœ‰é€šè¿‡è¿‡æ»¤çš„文件/文件夹能被选择用于åŒæ¥. 过滤ä¸çš„路径å‡ä¸ºåŒæ¥åŸºç¡€æ–‡ä»¶å¤¹çš„相对路径. +Open directly +直接打开 +Open with Explorer +用Explorer打开 +Open with Konqueror +用Konqueror打开 Operation aborted! æ“作已å–消! Operation: @@ -615,7 +647,7 @@ Question Quit 退出 Re-enable all hidden dialogs? - +é‡æ–°å¯ç”¨æ‰€æœ‰éšè—的对è¯æ¡†? RealtimeSync - Automated Synchronization 实时åŒæ¥ - 自动åŒæ¥ RealtimeSync configuration @@ -623,7 +655,7 @@ RealtimeSync configuration Relative path 相对路径 Remove alternate settings - +移除替æ¢è®¾ç½® Remove folder åˆ é™¤æ–‡ä»¶å¤¹ Remove folder pair @@ -632,8 +664,6 @@ Report translation error 报告翻译错误 Reset é‡ç½® -Result -结果 Right å³ä¾§ S&ave configuration @@ -651,9 +681,9 @@ Scanning: Select a folder 选择一个文件夹 Select alternate filter settings - +选择替æ¢è¿‡æ»¤è®¾ç½® Select alternate synchronization settings - +选择替æ¢åŒæ¥è®¾ç½® Select logfile directory: 选择日志ä¿å˜ä½ç½®: Select variant: @@ -683,13 +713,13 @@ 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 overwritten on left side - +显示将在左侧被覆盖的文件 Show files that will be overwritten on right side - +显示将在å³ä¾§è¢«è¦†ç›–的文件 Show files that won't be copied 显示将ä¸è¢«å¤åˆ¶çš„文件 Show hidden dialogs - +显示éšè—的对è¯æ¡† Show popup æ˜¾ç¤ºå¼¹å‡ºçª—å£ Show popup on errors or warnings @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ åŒæ¥æ‰€æœ‰ .doc, .zipå’Œ .exe 文件, 除了\"temp\"ä¸çš„一切. Synchronize both sides simultaneously: Copy new or updated files in both directions. åŒæ—¶åŒæ¥ä¸¤ä¾§: åŒå‘å¤åˆ¶æ–°çš„或更新的文件. +Synchronize both sides using a database. Deletions are detected automatically. +使用数æ®åº“åŒæ¥ä¸¤ä¾§. åˆ é™¤ä¼šè¢«è‡ªåŠ¨æ£€æµ‹åˆ°. Synchronize... åŒæ¥... Synchronizing... @@ -779,13 +811,15 @@ Use Recycle Bin Use Recycle Bin when deleting or overwriting files. å½“åˆ é™¤æˆ–è¦†ç›–æ–‡ä»¶æ—¶ä½¿ç”¨å›žæ”¶ç«™. User-defined directory - +用户定义目录 User-defined directory for deletion was not specified! - +ç”¨äºŽåˆ é™¤çš„ç”¨æˆ·å®šä¹‰ç›®å½•æ²¡æœ‰æŒ‡å®š! +Using default synchronization directions. Please recheck. +使用默认的åŒæ¥æ–¹å‘. 请é‡æ–°æ£€æŸ¥. Variant å˜åŒ– Verifying file %x - +æ ¡éªŒæ–‡ä»¶ %x Volume name %x not part of filename %y! å·å %x 并éžæ–‡ä»¶å %y 的一部分! Warning @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree 当以æ¤é€‰é¡¹å¼€å§‹æ¯”è¾ƒæ—¶ä»¥ä¸‹å†³å®šæ ‘è¢«å¤„ç†: You can ignore the error to consider not existing directories as empty. 您å¯å¿½ç•¥æ¤é”™è¯¯è€Œå°†ä¸å˜åœ¨çš„目录视为空. +You can ignore the error to skip current folder pair. +ä½ å¯å¿½ç•¥æ¤é”™è¯¯ä»¥è·³è¿‡å½“å‰æ–‡ä»¶å¤¹å¯¹. You may try to synchronize remaining items again (WITHOUT having to re-compare)! 您å¯èƒ½ä¼šå°è¯•å†æ¬¡åŒæ¥å‰©ä½™çš„项目(而ä¸å¿…é‡æ–°æ¯”较)! different diff --git a/BUILD/Languages/chinese_traditional.lng b/BUILD/Languages/chinese_traditional.lng index 08b20ee5..a84ca562 100644 --- a/BUILD/Languages/chinese_traditional.lng +++ b/BUILD/Languages/chinese_traditional.lng @@ -31,9 +31,9 @@ %x is not a valid FreeFileSync batch file! %x ä¸æ˜¯ä¸€å€‹æœ‰æ•ˆçš„ FreeFileSync æ‰¹æ¬¡æª”ï¼ %x of %y rows in view -顯示 %x 之 %y è¡Œ +顯示 %y 之 %x è¡Œ %x of 1 row in view -顯示 %x 之 1 è¡Œ +顯示 1 之 %x è¡Œ &Abort å–消(&A) &About... @@ -138,6 +138,8 @@ 2. 使用è¬ç”¨å—元‘*’和‘?’。 3. Exclude files directly on main grid via context menu. 3. 經由內容é¸å–®ç›´æŽ¥åœ¨ä¸»è¦ç¶²æ ¼æŽ’除檔案。 +<Automatic> +<自動> <Directory> <目錄> <Last session> @@ -146,6 +148,8 @@ <多é‡é¸æ“‡> A newer version of FreeFileSync is available: 有較新版本的 FreeFileSync å¯ç”¨ï¼š +ATTENTION: Failed directory access can lead to file deletions! +注æ„:目錄讀å–失敗å¯èƒ½æœƒå°Žè‡´æª”æ¡ˆåˆªé™¤ï¼ Abort requested: Waiting for current operation to finish... ä¸æ¢è«‹æ±‚:æ£åœ¨ç‰å¾…ç›®å‰æ“作完æˆ... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp 組åˆä¸€å€‹ç”¨æ–¼è‡ªå‹•åŒæ¥çš„批次檔。若è¦é–‹å§‹æ‰¹æ¬¡è™•ç†æ¨¡å¼ï¼Œåªéœ€ç°¡å–®çš„將批次檔å傳é€ç»™ FreeFileSync å¯åŸ·è¡Œæª”:FreeFileSync.exe <batchfile>。這個也å¯ä»¥å®‰æŽ’åœ¨ä½ çš„ä½œæ¥ç³»çµ±çš„計畫任務ä¸ã€‚ Auto-adjust columns 自動調整欄寬 +Automatic mode +è‡ªå‹•æ¨¡å¼ Batch execution 批次處ç†åŸ·è¡Œ Batch file created successfully! @@ -176,12 +182,20 @@ Batch job 批次處ç†ä½œæ¥ Big thanks for localizing FreeFileSync goes out to: éžå¸¸æ„Ÿè¬ FreeFileSync 當地語系化的工作人員: +Both sides have changed since last synchronization! +自上次åŒæ¥å¾Œï¼Œå…©é‚Šå‡å·²æ›´æ”¹éŽï¼ Browse ç€è¦½ Build: 建立: Cancel å–消 +Cannot determine sync-direction: Changed filter settings! +ä¸èƒ½åˆ¤æ–·åŒæ¥æ–¹å‘:已更改篩é¸å™¨è¨å®šï¼ +Cannot determine sync-direction: No change since last synchronization! +ä¸èƒ½åˆ¤æ–·åŒæ¥æ–¹å‘:自上次åŒæ¥å¾Œï¼Œæ²’有更改éŽï¼ +Category +分類 Change direction æ”¹è®Šæ–¹å‘ Check all @@ -259,7 +273,7 @@ Copying file %x to %y Copying file %x to %y overwriting target æ£åœ¨è¤‡è£½æª”案 %x 覆蓋到目標 %y Could not determine volume name for file: -無法判定æ¤æª”案的å·æ¨™å稱: +無法判斷æ¤æª”案的å·æ¨™å稱: Could not initialize directory monitoring: 無法åˆå§‹åŒ–目錄監測: Could not read values for the following XML nodes: @@ -376,6 +390,8 @@ Error reading file attributes: 讀å–檔案屬性錯誤: Error reading file: 讀å–檔案錯誤: +Error reading from synchronization database: +讀å–åŒæ¥è³‡æ–™åº«éŒ¯èª¤ï¼š Error resolving symbolic link: 解决符號連çµéŒ¯èª¤ï¼š Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: 寫入檔案屬性錯誤: Error writing file: 寫入檔案錯誤: -Error: Source directory does not exist anymore: -錯誤:來æºç›®éŒ„ä¸å˜åœ¨ï¼š +Error writing to synchronization database: +寫入åŒæ¥è³‡æ–™åº«éŒ¯èª¤ï¼š +Source directory does not exist anymore: +來æºç›®éŒ„ä¸å˜åœ¨ï¼š Example 例如 Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer 檔案å˜åœ¨æ–¼å…©é‚Šï¼Œå·¦é‚Šæª”案較新 Files that exist on both sides, right one is newer 檔案å˜åœ¨æ–¼å…©é‚Šï¼Œå³é‚Šæª”案較新 +Files/folders found: +找到的檔案/資料夾: Files/folders remaining: 剩餘的檔案/資料夾: -Files/folders scanned: -已掃瞄的檔案/資料夾: Files/folders that exist on left side only åªå˜åœ¨æ–¼å·¦é‚Šçš„檔案/資料夾 Files/folders that exist on right side only @@ -449,7 +467,7 @@ Files/folders that exist on right side only Filter 篩é¸å™¨ Filter active: Press again to deactivate -篩é¸å™¨å•Ÿå‹•ï¼šå†æŒ‰ä¸€æ¬¡æœƒåœç”¨ +篩é¸å™¨å•Ÿç”¨ï¼šå†æŒ‰ä¸€æ¬¡æœƒåœç”¨ Filter files 篩é¸æª”案 Filter view @@ -469,9 +487,11 @@ FreeFileSync 批次檔 FreeFileSync configuration FreeFileSync é…ç½® FreeFileSync is up to date! -FreeFileSync æ˜¯æœ€æ–°ç‰ˆæœ¬ï¼ +FreeFileSync å·²æ˜¯æœ€æ–°ç‰ˆæœ¬ï¼ Full path 完整路徑 +Generating database... +產生資料庫... Generating file list... 產生檔案清單... Global settings @@ -536,14 +556,18 @@ Include temporarily 暫時包括 Include: *.doc;*.zip;*.exe\nExclude: temp\\* 包括:*.doc;*.zip;*.exe\n排除temp\\* +Incompatible synchronization database format: +åŒæ¥è³‡æ–™åº«æ ¼å¼ä¸ç›¸å®¹ï¼š Info è¨Šæ¯ Information è¨Šæ¯ +Initial synchronization. Please verify default copy-directions! +åˆå§‹åŒ–åŒæ¥ã€‚è«‹é©—è‰é è¨çš„複製方å‘ï¼ Integrate external applications into context menu. The following macros are available: æ•´åˆä¸Šä¸‹æ–‡åŠŸèƒ½è¡¨ä¸çš„外部應用程å¼ã€‚å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„巨集: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) -ä¸èƒ½åˆå§‹åŒ–資æºå›žæ”¶ç’ï¼\n\nå¯èƒ½ä½ 使用的ä¸æ˜¯Windows系統。\nå¦‚æžœä½ æƒ³åŒ…æ‹¬æ¤åŠŸèƒ½ï¼Œè«‹è¯ç¹«ä½œè€…。:) +ä¸èƒ½åˆå§‹åŒ–資æºå›žæ”¶ç’ï¼\n\nå¯èƒ½ä½ 使用的ä¸æ˜¯ Windows 系統。\nå¦‚æžœä½ æƒ³åŒ…æ‹¬æ¤åŠŸèƒ½ï¼Œè«‹è¯ç¹«ä½œè€…。:) Leave as unresolved conflict ä¿ç•™çµ¦æœªè§£æ±ºçš„è¡çª Left @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y 移動資料夾 %x 到自定義資料夾 %y Multiple... 多個... +No database file existing yet: +ç›®å‰é‚„沒有資料庫檔案: Not enough free disk space available in: æ²’æœ‰è¶³å¤ çš„å¯ç”¨ç©ºé–“: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK 確定 Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. åªæœ‰è¢«é¸ä¸ç¯©é¸çš„檔案/目錄會進行åŒæ¥ã€‚篩é¸å™¨å°‡å¥—用到基本åŒæ¥ç›®éŒ„的相å°å稱。 +Open directly +直接開啟 +Open with Explorer +使用檔案總管開啟 +Open with Konqueror +使用 Konqueror é–‹å•Ÿ Operation aborted! ä¸æ¢æ“ä½œï¼ Operation: @@ -607,7 +639,7 @@ Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) i Please fill all empty directory fields. 請填滿所有空白目錄欄ä½ã€‚ Press button to activate filter -按下按鈕以啟動篩é¸å™¨ +按下按鈕以啟用篩é¸å™¨ Published under the GNU General Public License: 在GNU通用公共許å¯è‰ä¸‹ç™¼ä½ˆï¼š Question @@ -623,17 +655,15 @@ RealtimeSync configuration Relative path 相å°è·¯å¾‘ Remove alternate settings -刪除備用è¨å®š +移除備用è¨å®š Remove folder -刪除資料夾 +移除資料夾 Remove folder pair -刪除兩個資料夾 +移除兩個資料夾 Report translation error å›žå ±ç¿»è¯éŒ¯èª¤ Reset é‡ç½® -Result -çµæžœ Right å³é‚Š S&ave configuration @@ -641,7 +671,7 @@ S&ave configuration S&witch view 切æ›æª¢è¦–(&W) Save changes to current configuration? -ä¿å˜å°ç›®å‰é…置的更改嗎? +儲å˜å°ç›®å‰é…置的更改嗎? Save current configuration to file 將目å‰é…置儲å˜åˆ°æª”案 Scanning... @@ -691,9 +721,9 @@ Show files that won't be copied Show hidden dialogs 顯示隱è—çš„å°è©±æ¡† Show popup -顯示快顯功能表 +顯示彈出視窗 Show popup on errors or warnings -在快顯功能表上顯示錯誤或è¦å‘Š +在彈出視窗上顯示錯誤或è¦å‘Šè¨Šæ¯ Significant difference detected: 檢測到顯著的差異: Silent mode @@ -730,10 +760,12 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ åŒæ¥æ‰€æœ‰ .doc, .zip å’Œ .exe 檔案, 除了\"temp\"ä¸çš„一切。 Synchronize both sides simultaneously: Copy new or updated files in both directions. åŒæ™‚é›™å‘åŒæ¥ï¼šé›™å‘複製新的或已更新的檔案。 +Synchronize both sides using a database. Deletions are detected automatically. +é›™å‘åŒæ¥ä½¿ç”¨ä¸€å€‹è³‡æ–™åº«ã€‚自動檢測è¦åˆªé™¤çš„檔案。 Synchronize... åŒæ¥... Synchronizing... -åŒæ¥ä¸... +æ£åœ¨åŒæ¥... System out of memory! 系統記憶體ä¸è¶³ï¼ Target directory already existing! @@ -751,11 +783,11 @@ Time elapsed: Time remaining: 剩餘時間: Total amount of data that will be transferred -å°‡è¢«å‚³è¼¸çš„å…¨éƒ¨è³‡æ–™é‡ +å°‡è¦å‚³è¼¸çš„å…¨éƒ¨è³‡æ–™é‡ Total required free disk space: 全部所需è¦çš„å¯ç”¨ç£ç¢Ÿç©ºé–“: Total time: -總時間: +全部時間: Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes. å°æª”案時差在精確的+/-1å°æ™‚的檔案判斷視為相åŒçš„,以å°æ–¼1å°æ™‚作為è¡çªï¼Œæ˜¯ç‚ºäº†è™•ç†æ—¥å…‰ç¯€ç´„時間的變化。 Two way <-> @@ -763,7 +795,7 @@ Two way <-> Unable to connect to sourceforge.net! 無法連接到 sourceforge.netï¼ Unable to create logfile! -ç„¡æ³•æ–°å»ºæ—¥èªŒæª”æ¡ˆï¼ +ç„¡æ³•æ–°å»ºæ—¥èªŒæª”ï¼ Unable to initialize Recycle Bin! 無法åˆå§‹åŒ–資æºå›žæ”¶ç’ï¼ Uncheck all @@ -782,6 +814,8 @@ User-defined directory 自定義目錄 User-defined directory for deletion was not specified! 未指定è¦åˆªé™¤çš„è‡ªå®šç¾©ç›®éŒ„ï¼ +Using default synchronization directions. Please recheck. +使用é è¨åŒæ¥æ–¹å‘。請é‡æ–°æª¢æŸ¥ã€‚ Variant 變數 Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree 當比å°é–‹å§‹ï¼Œä½¿ç”¨æ¤é¸é …è¨å®šæ™‚,以下決ç–樹將被處ç†ï¼š You can ignore the error to consider not existing directories as empty. ä½ å¯ä»¥å¿½ç•¥è©²éŒ¯èª¤è€Œå°‡ä¸å˜åœ¨çš„目錄視為空目錄。 +You can ignore the error to skip current folder pair. +您å¯ä»¥å¿½ç•¥è·³éŽç›®å‰å…©å€‹è³‡æ–™å¤¾çš„錯誤。 You may try to synchronize remaining items again (WITHOUT having to re-compare)! 您å¯èƒ½æœƒå˜—試å†æ¬¡åŒæ¥å‰©é¤˜é …ç›®(ä¸ç”¨é‡æ–°æ¯”å°)ï¼ different diff --git a/BUILD/Languages/czech.lng b/BUILD/Languages/czech.lng index ee1bbc04..1129d5c6 100644 --- a/BUILD/Languages/czech.lng +++ b/BUILD/Languages/czech.lng @@ -81,7 +81,7 @@ U&konÄit &Restore &Obnovit &Retry -&Znovu +&Opakovat &Save &Uložit &Yes @@ -91,9 +91,9 @@ U&konÄit , - Other side's counterpart to %dir -- pouze cesta z opaÄného panelu (protistarna k %dir) +- pouze cesta z opaÄného panelu - Other side's counterpart to %name -- celá cesta nebo jméno souboru z opaÄného panelu (protistrana k %name) +- celá cesta nebo jméno souboru z opaÄného panelu - conflict - konflikt - conflict (same date, different size) @@ -138,6 +138,8 @@ soubor: 1; 2. Můžete použÃt zástupné znaky (wildcard) '*' a '?'. 3. Exclude files directly on main grid via context menu. 3. Můžete použÃt pro vynechávánà souborů pÅ™Ãmo kontextového menu. +<Automatic> +<Automaticky> <Directory> <Adresář> <Last session> @@ -146,6 +148,8 @@ soubor: 1; <vÃcenásobný výbÄ›r> A newer version of FreeFileSync is available: je dostupná novÄ›jÅ¡Ã verze FreeFileSync: +ATTENTION: Failed directory access can lead to file deletions! +POZOR: Chyba pÅ™Ãstupu k adresáři může vést ke smazánà souborů! Abort requested: Waiting for current operation to finish... Požadavek na pÅ™eruÅ¡enÃ: ÄŒekánà na ukonÄenà aktuálnà operace... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp VytvoÅ™enà dávkového souboru pro automatický provoz. Ke spuÅ¡tÄ›nà dávky jednoduÅ¡e jejà jméno zadejte jako parametr pÅ™i spuÅ¡tÄ›nà FreeFileSync: FreeFileSync.exe <batchfile>. Auto-adjust columns Automaticky pÅ™izpůsobit Å¡ÃÅ™ku +Automatic mode +Automatický mód Batch execution SpuÅ¡tÄ›nà dávky Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Dávkový soubor Big thanks for localizing FreeFileSync goes out to: PodÄ›kovánà za pÅ™eklad FreeFileSync: +Both sides have changed since last synchronization! +DoÅ¡lo ke zmÄ›nÄ› obou stran od poslednà synchronizace! Browse Procházet Build: Build: Cancel ZruÅ¡it +Cannot determine sync-direction: Changed filter settings! +Nelze urÄit smÄ›r synchronizace: Změňte nastavenà filtru! +Cannot determine sync-direction: No change since last synchronization! +Nelze urÄit smÄ›r synchronizace: NedoÅ¡lo ke zmÄ›nám od poslednà synchronizace! +Category +Kategorie Change direction ZmÄ›nit akci Check all @@ -289,7 +303,7 @@ Datum Delay ZpoždÄ›nà Delay between detection of changes and execution of commandline in seconds -ZpoždÄ›nà detekce zmÄ›n a suÅ¡tÄ›nà pÅ™Ãkazu v sekundách +ZpoždÄ›nà detekce zmÄ›n a spuÅ¡tÄ›nà pÅ™Ãkazu v sekundách Delete files/folders existing on left side only Smazat soubory/adresáře existujÃcà pouze na levé stranÄ› Delete files/folders existing on right side only @@ -323,7 +337,7 @@ Adresář neexistuje: Do not display visual status information but write to a logfile instead Nezobrazovat informace o stavu ale zapisovat pÅ™Ãmo do souboru záznamů Do not show this dialog again -tento dialog již nezobrazovat +Tento dialog již nezobrazovat Do nothing Nic nedÄ›lat Do you really want to delete the following objects(s)? @@ -376,6 +390,8 @@ Error reading file attributes: Chyba Ätenà atributů souboru: Error reading file: Chyba Ätenà souboru: +Error reading from synchronization database: +Chyba Ätenà synchronizaÄnà databáze: Error resolving symbolic link: Chyba odkazu zástupce: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Chyba zápisu atributů souboru: Error writing file: Chyba zápisu souboru: -Error: Source directory does not exist anymore: -Chyba: Zdrojový adresář již neexistuje: +Error writing to synchronization database: +Chyba zápisu synchronizaÄnà databáze: +Source directory does not exist anymore: +Zdrojový adresář již neexistuje: Example PÅ™Ãklad Exclude @@ -399,9 +417,9 @@ Vynechat doÄasnÄ› Exclude via filter: Vynechat pomocà filtru: Exit immediately and set returncode < 0 -UkoÄit okamžitÄ› a nastavit návratový kód < 0 +UkonÄit okamžitÄ› a nastavit návratový kód < 0 Exit with RC < 0 -UkoÄit s RC < 0 +UkonÄit s RC < 0 External applications Externà aplikace Feedback and suggestions are welcome at: @@ -433,15 +451,15 @@ Zbývá souborů: Files that are equal on both sides Soubory shodné na obou stranách Files that exist on both sides and have different content -Soubory, ketré existujà na obou stranách a liÅ¡Ã se obsahem +Soubory, které existujà na obou stranách a liÅ¡Ã se obsahem Files that exist on both sides, left one is newer Soubory, které existujà na obou stranách, z nichž vlevo je novÄ›jÅ¡Ã Files that exist on both sides, right one is newer -Soubory, které existujé na obou stranách, z nichž vpravo je novÄ›jÅ¡Ã +Soubory, které existujà na obou stranách, z nichž vpravo je novÄ›jÅ¡Ã +Files/folders found: +Nalezené soubory/adresáře: Files/folders remaining: Zbývá souborů/adresářů: -Files/folders scanned: -Zpracované soubory/adresáře: Files/folders that exist on left side only Soubory/adresáře, které existujà pouze vlevo Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync je aktuálnÃ! Full path Plná cesta +Generating database... +Vytvářenà databáze... Generating file list... Vytvářenà seznamu souborů... Global settings @@ -536,12 +556,16 @@ Include temporarily PÅ™idat doÄasnÄ› Include: *.doc;*.zip;*.exe\nExclude: temp\\* PÅ™idat: *.doc;*.zip;*.exe\nVynechat: temp\\* +Incompatible synchronization database format: +Chyba formátu synchronizaÄnà databáze: Info Info Information Informace +Initial synchronization. Please verify default copy-directions! +Prvotnà synchronizace. ProsÃm ověřte základnà nastavenà smÄ›ru synchronizace! Integrate external applications into context menu. The following macros are available: -Integrace externà apilkace do kontextového menu. K dispozici jsou následujÃcà makra: +Integrace externà aplikace do kontextového menu. K dispozici jsou následujÃcà makra: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) Nebylo možné inicializovat KoÅ¡!\n\nPravdÄ›podobnÄ› nepoužÃváte Windows.\nPokud chcete tuto vlastnost využÃvat, kontaktujte autora. :) Leave as unresolved conflict @@ -575,9 +599,11 @@ PÅ™esouvánà %x do KoÅ¡e. Moving file %x to user-defined directory %y PÅ™esouvánà souboru %x do uživatelského adresáře %y Moving folder %x to user-defined directory %y -PÅ™esouvánà adrsáře %x do uživatelského adresáře %y +PÅ™esouvánà adresáře %x do uživatelského adresáře %y Multiple... NÄ›kolikanásobný... +No database file existing yet: +SynchronizaÄnà databáze jeÅ¡tÄ› neexistuje: Not enough free disk space available in: Nedostatek mÃsta na disku: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Pouze soubory/adresáře odpovÃdajÃcà nastavenému filtru budou vybrány pro synchronizaci. Filtr je aplikován relativnÄ›(!) k cestÄ› synchronizovaných adresářů. +Open directly +OtevÅ™Ãt pÅ™Ãmo +Open with Explorer +OtevÅ™Ãt v PrůzkumnÃkovi +Open with Konqueror +OtevÅ™Ãt v ProhlÞeÄi Operation aborted! Operace zruÅ¡ena! Operation: @@ -627,13 +659,11 @@ Odstranit jiné nastavenà Remove folder Odstranit adresář Remove folder pair -Odtsranit dvojici adresářů +Odstranit dvojici adresářů Report translation error Hlásit chyby pÅ™ekladu Reset Resetovat -Result -Výsledek Right Pravý S&ave configuration @@ -727,9 +757,11 @@ Nastavenà synchronizace Synchronization status Stav synchronizace Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\". -Synchronizuj vÅ¡echny soubory .doc, .zip a .exe s výjimkou vÅ¡eho v podadresáři \"temp\" +Synchronizovat vÅ¡echny soubory .doc, .zip a .exe s výjimkou vÅ¡eho v podadresáři \"temp\" Synchronize both sides simultaneously: Copy new or updated files in both directions. -Synchronizuj obÄ› strany zároveň: KopÃruj nové nebo aktualizované soubory z obou adresářů. +Synchronizovat obÄ› strany zároveň: KopÃrovat nové nebo aktualizované soubory z obou adresářů. +Synchronize both sides using a database. Deletions are detected automatically. +Synchronizovat obÄ› strany pomocà databáze. Mazánà je urÄeno automaticky. Synchronize... Synchronizace... Synchronizing... @@ -743,7 +775,7 @@ CÃlový soubor již existuje! The file does not contain a valid configuration: Soubor neobsahuje platnou konfiguraci: This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. -Tato variantra vyhodnotà dva stejnÄ› pojmenované soubory jako shodné pokud majà i stejnou velikost A ZÃROVEŇ i datum a Äas poslednà zmÄ›ny. +Tato varianta vyhodnotà dva stejnÄ› pojmenované soubory jako shodné pokud majà i stejnou velikost A ZÃROVEŇ i datum a Äas poslednà zmÄ›ny. Time ÄŒas Time elapsed: @@ -782,6 +814,8 @@ User-defined directory Uživatelsky definovaný adresář User-defined directory for deletion was not specified! Uživatelsky definovaný adresář pro mazánà nebyl zadán! +Using default synchronization directions. Please recheck. +Použito pÅ™eddefinované nastavenÃ. ProsÃm pÅ™ekontrolujte nastavenÃ. Variant Varianta Verifying file %x @@ -791,11 +825,13 @@ Disk %x nenà souÄástà jména souboru %y! Warning Varovánà Warning: Synchronization failed for %x item(s): -VarovánÃ: Synchornizace se nepovedla pro \"%x\" položek: +VarovánÃ: Synchronizace se nepovedla pro \"%x\" položek: When the comparison is started with this option set the following decision tree is processed: Když je zahájeno porovnávánà s tÃmto nastavenÃm, je použito následujÃcà schéma rozhodovánÃ: You can ignore the error to consider not existing directories as empty. -Chybu považovanà neexistujÃcà adresářů jako prázdných můžete ignorovat. +Pro považovánà neexistujÃcÃch adresářů jako prázdných můžete chybu ignorovat. +You can ignore the error to skip current folder pair. +Pro pÅ™eskoÄenà aktuálnÃho páru adresářů můžete chybu ignorovat. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Můžete se pokusit synchronizovat zbývajÃcà položky (BEZ nutnosti znovuporovnávánÃ)! different diff --git a/BUILD/Languages/dutch.lng b/BUILD/Languages/dutch.lng index 4f694323..2387b089 100644 --- a/BUILD/Languages/dutch.lng +++ b/BUILD/Languages/dutch.lng @@ -138,6 +138,8 @@ 2. U kunt gebruik maken van wildcard karakters zoals '*' en '?'. 3. Exclude files directly on main grid via context menu. 3. Sluit bestanden direct uit in het hoofscherm via een contextmenu +<Automatic> +<Automatisch> <Directory> <Pad> <Last session> @@ -168,6 +170,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Assembleer een batchbestand voor automatische synchronisatie. Om te starten in batchmodus is het voldoende om de bestandsnaam achter de FreeFileSync toepassing te zetten: FreeFileSync.exe <batchbestand>. Het is mogelijk dit in te plannen in de systeemplanner. Auto-adjust columns Kolommen automatisch aanpassen +Automatic mode +Automatische modus Batch execution Batch taak uitvoeren Batch file created successfully! @@ -176,12 +180,20 @@ Batch job Batch taak Big thanks for localizing FreeFileSync goes out to: Extra dank voor het vertalen van FreeFileSync gaat naar: +Both sides have changed since last synchronization! +Beide zijden zijn veranderd sinds de laatste synchronisatie! Browse Map opzoeken Build: Gebouwd: Cancel Annuleren +Cannot determine sync-direction: Changed filter settings! +Kan de synchronisatie-richting niet bepalen: verandering in +Cannot determine sync-direction: No change since last synchronization! +Kan de synchronisatie-richting niet bepalen: geen verandering sinds de laatste synchronisatie! +Category +Categorie Change direction Zijdes omwisselen Check all @@ -376,6 +388,8 @@ Error reading file attributes: Er is een fout opgetreden bij het lezen van de bestands-eigenschappen Error reading file: Er is een fout opgetreden bij het lezen van het bestand: +Error reading from synchronization database: +Er is een fout opgetreden bij het lezen van de synchronisatie-database: Error resolving symbolic link: Er is een fout opgetreden bij het ophalen van een symbolische koppeling: Error starting Volume Shadow Copy Service! @@ -388,8 +402,10 @@ Error writing file attributes: Er is een fout opgetreden bij het schrijven van de bestands-eigenschappen: Error writing file: Er is een fout opgetreden bij het schrijven naar bestand: -Error: Source directory does not exist anymore: -Er is een fout opgetreden. De oorspronkelijke map bestaat niet meer: +Error writing to synchronization database: +Er is een fout opgetreden bij het schrijven naar de synchronisatie-database: +Source directory does not exist anymore: +De oorspronkelijke map bestaat niet meer: Example Voorbeeld Exclude @@ -438,10 +454,10 @@ Files that exist on both sides, left one is newer Bestanden die aan beide kanten bestaan, maar waarvan de linkerkant nieuwer is Files that exist on both sides, right one is newer Bestanden die aan beide kanten bestaan, maar waarvan de rechterkant nieuwer is +Files/folders found: +Gevonden bestanden/mappen: Files/folders remaining: Resterende bestanden/mappen: -Files/folders scanned: -Aantal bestanden/mappen gescand: Files/folders that exist on left side only Bestanden/mappen die alleen aan de linkerkant bestaan Files/folders that exist on right side only @@ -472,6 +488,8 @@ FreeFileSync is up to date! U gebruikt de nieuwste versie van FreeFileSync! Full path Volledige bestandslocatie +Generating database... +Database genereren... Generating file list... Bestandslijst genereren... Global settings @@ -536,10 +554,14 @@ Include temporarily Tijdelijk bijsluiten Include: *.doc;*.zip;*.exe\nExclude: temp\\* Bijsluiten: *.doc;*.zip;*.exe\nUitsluiten: temp\\* +Incompatible synchronization database format: +Opmaak van synchronisatie-database komt niet overeen: Info Info Information Informatie +Initial synchronization. Please verify default copy-directions! +Initiële synchronisatie. Verifieer alstublieft de standaard kopieer-richtingen! Integrate external applications into context menu. The following macros are available: Integreer externe applicaties in het context menu. De volgende macros zijn beschikbaar: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +600,8 @@ Moving folder %x to user-defined directory %y Verplaatsen map %x naar een door de gebruiker gedefinieerde locatie %y Multiple... Meerdere... +No database file existing yet: +Er bestaat nog geen database bestand: Not enough free disk space available in: Niet genoeg schijfruimte beschikbaar op: Nothing to synchronize according to configuration! @@ -592,6 +616,12 @@ OK Oke Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Alleen bestanden /locatie die niet worden gefilterd zullen worden gesynchroniseerd. Het filter word toegepast op de relatieve(!) naam van de basislocatie van de synchronisatie. +Open directly +Direct openen +Open with Explorer +Openen met Explorer +Open with Konqueror +Openen met Konqueror Operation aborted! Operatie afgebroken! Operation: @@ -632,8 +662,6 @@ Report translation error Rapporteer een fout in de vertaling Reset Reset -Result -Resultaat Right Rechts S&ave configuration @@ -730,6 +758,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Synchroniseer alle .doc, .zip en .exe bestanden uitgezonderd alles in submap \"temp\" Synchronize both sides simultaneously: Copy new or updated files in both directions. Synchroniseer beide zijde tegelijkertijd: kopieer nieuwe of geüpdatete bestanden in beide richtingen. +Synchronize both sides using a database. Deletions are detected automatically. +Synchroniseer beide zijdes met gebruik van een database. Verwijderde bestanden worden automatisch opgemerkt. Synchronize... Synchroniseer... Synchronizing... @@ -782,6 +812,8 @@ User-defined directory Door de gebruiker te definiëren locatie User-defined directory for deletion was not specified! Door de gebruiker te definiëren locatie voor verwijderen was niet opgegeven! +Using default synchronization directions. Please recheck. +De standaardrichting voor synchronisatie wordt gebruikt. Alstublieft opnieuw controleren. Variant Variant Verifying file %x @@ -796,6 +828,8 @@ When the comparison is started with this option set the following decision tree Wanneer met deze optie aan de vergelijking wordt gestart zal de volgende vergelijkingsboom worden gebruikt: You can ignore the error to consider not existing directories as empty. U kunt de fout negeren om niet bestaande locaties als leeg te beschouwen. +You can ignore the error to skip current folder pair. +U kunt de foutmelding om de huidige mappencombinatie over te slaan negeren. You may try to synchronize remaining items again (WITHOUT having to re-compare)! U kunt proberen om de resterende bestanden opnieuw te synchroniseren (ZONDER opnieuw te hoeven vergelijken)! different diff --git a/BUILD/Languages/french.lng b/BUILD/Languages/french.lng index ddfe21c2..76216760 100644 --- a/BUILD/Languages/french.lng +++ b/BUILD/Languages/french.lng @@ -138,6 +138,8 @@ 2. Les caractères génériques '*' et '?' sont acceptés. 3. Exclude files directly on main grid via context menu. 3. Exclure les fichiers directement sur le tableau principal à l'aide du menu contextuel. +<Automatic> +<Automatique> <Directory> <Répertoire> <Last session> @@ -168,6 +170,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Créer un fichier de commandespour une synchronisation automatique. Pour démarrer en mode batch, indiquer le nom du fichier à l'exécutable FreeFileSync : freefilesync.exe <fichier de commandes>. Ceci peut aussi être programmé dans le plannificateur de tâches. Auto-adjust columns Auto-ajustement des colonnes +Automatic mode +Mode automatique Batch execution Exécution du fichier de commandes Batch file created successfully! @@ -176,12 +180,20 @@ Batch job Fichier de commandes Big thanks for localizing FreeFileSync goes out to: Pour les traductions de FreeFileSync, un grand merci à : +Both sides have changed since last synchronization! +Les deux côtés ont changé depuis la dernière synchronisation ! Browse Parcourir Build: Créé le : Cancel Annuler +Cannot determine sync-direction: Changed filter settings! +Impossible de déterminer le sens de la synchro : la configuration a été modifiée ! +Cannot determine sync-direction: No change since last synchronization! +Impossible de déterminer le sens de la synchro : Aucune modification depuis la dernière synchro ! +Category +Catégorie Change direction Changer la direction Check all @@ -376,6 +388,8 @@ Error reading file attributes: Erreur lors de la lecture des attributs du fichier : Error reading file: Erreur lors de la lecture du fichier : +Error reading from synchronization database: +Erreur lors de la lecture de la base de données de synchro : Error resolving symbolic link: Erreur lors de la résolution du lien symbolique : Error starting Volume Shadow Copy Service! @@ -388,8 +402,10 @@ Error writing file attributes: Erreur lors de l'écriture des attributs du fichier : Error writing file: Erreur lors de l'écriture du fichier : -Error: Source directory does not exist anymore: -Erreur : le répertoire source n'existe plus : +Error writing to synchronization database: +Erreur lors de l'écriture de la base de données de synchro : +Source directory does not exist anymore: +Le répertoire source n'existe plus : Example Exemple Exclude @@ -438,10 +454,10 @@ Files that exist on both sides, left one is newer Fichiers existants des deux côtés, celui de gauche est plus récent Files that exist on both sides, right one is newer Fichiers existants des deux côtés, celui de droite est plus récent +Files/folders found: +Fichiers/Dossiers trouvés : Files/folders remaining: Fichiers/dossiers restants : -Files/folders scanned: -Fichiers/dossiers analysés : Files/folders that exist on left side only Fichiers/répertoires existants seulement à gauche Files/folders that exist on right side only @@ -472,6 +488,8 @@ FreeFileSync is up to date! FreeFileSync a été mis à jour ! Full path Chemin complet +Generating database... +Génération de la base de données... Generating file list... Génération de la liste des fichiers... Global settings @@ -536,10 +554,14 @@ Include temporarily Inclure temporairement Include: *.doc;*.zip;*.exe\nExclude: temp\\* Inclure : *.doc;*.zip;*.exe\nExclure : temp\\* +Incompatible synchronization database format: +Format de la base de données de synchro incompatible : Info Info Information Information +Initial synchronization. Please verify default copy-directions! +Première synchronisation. Veuillez vérifier le sens de la copie par défaut ! Integrate external applications into context menu. The following macros are available: Inclure les applications externes dans le menu contextuel. Les macros suivantes sont disponibles : It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +600,8 @@ Moving folder %x to user-defined directory %y Déplacement du dossier %x vers le répertoire défini par l'utilisateur %y Multiple... Multiple... +No database file existing yet: +Aucun fichier base de données n'existe actuellement : Not enough free disk space available in: Espace disque insuffisant sur : Nothing to synchronize according to configuration! @@ -592,6 +616,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Seuls les fichiers/répertoires filtrés seront sélectionnés pour la synchronisation. Le filtre sera appliqué au nom relatif (!) pour les répertoires de synchroniqation de base. +Open directly +Ouvrir directement +Open with Explorer +Ouvrir avec Explorer +Open with Konqueror +Ouvrir avec Konqueror Operation aborted! Opération abandonnée ! Operation: @@ -632,8 +662,6 @@ Report translation error Etat d'erreurs de transfert Reset Réinitialiser -Result -Situation Right Droite S&ave configuration @@ -730,6 +758,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Synchroniser rous les fichiers .doc, .zip et .exe sauf ceux du dossier \"temp\". Synchronize both sides simultaneously: Copy new or updated files in both directions. Synchronisation simultanée des deux côtés : Copie des fichiers nouveaux ou mis à jour. +Synchronize both sides using a database. Deletions are detected automatically. +Synchronisation des deux côtés à l'aide d'une base de données. Les suppressions sont détectées automatiquement. Synchronize... Synchroniser... Synchronizing... @@ -782,6 +812,8 @@ User-defined directory Réoertoire défini par l'utilisateur User-defined directory for deletion was not specified! Le réoertoire défini par l'utilisateur pour la suppression n'a pas été indiqué ! +Using default synchronization directions. Please recheck. +Sens de la synchronisation par défaut. Veuillez revérifier. Variant Variante Verifying file %x @@ -796,6 +828,8 @@ When the comparison is started with this option set the following decision tree Lorsque la comparaison démarre avec cette option, l'arbre de décision suivant est exécuté : You can ignore the error to consider not existing directories as empty. Vous pouvez ignorer l'erreur considérant qu'un dossier inexistant est vide. +You can ignore the error to skip current folder pair. +Vous pouvez ignorer l'erreur pour sauter la paire de dossiers courante. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Vous pouvez essayer de synchroniser à nouveau les éléments restants (SANS avoir à les re-comparer) ! different diff --git a/BUILD/Languages/german.lng b/BUILD/Languages/german.lng index 417923e4..23de4e2d 100644 --- a/BUILD/Languages/german.lng +++ b/BUILD/Languages/german.lng @@ -138,6 +138,8 @@ Konfiguration &laden 2. Die Platzhalter '*' und '?' werden unterstützt. 3. Exclude files directly on main grid via context menu. 3. Dateien können direkt über das Kontextmenü im Hauptfenster ausgeschlossen werden. +<Automatic> +<Automatik> <Directory> <Verzeichnis> <Last session> @@ -146,6 +148,8 @@ Konfiguration &laden <Mehrfachauswahl> A newer version of FreeFileSync is available: Eine neuere Version von FreeFileSync ist verfügbar: +ATTENTION: Failed directory access can lead to file deletions! +ACHTUNG: Fehler beim Verzeichniszugriff können zum Löschen von Dateien führen! Abort requested: Waiting for current operation to finish... Abbruch initiiert: Warte, bis aktuelle Operation beendet ist... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Erzeuge eine Batchdatei für die automatisierte Synchronisation. Um den Batch-Modus zu starten, muss nur der Dateiname an die Programmdatei übergeben werden: FreeFileSync.exe <Batchdatei>. Dies kann auch in den Taskplaner des Betriebssystems eingetragen werden. Auto-adjust columns Spalten automatisch anpassen +Automatic mode +Automatik Modus Batch execution Batchlauf Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Batch-Job Big thanks for localizing FreeFileSync goes out to: Vielen Dank für die Lokalisation von FreeFileSync an: +Both sides have changed since last synchronization! +Beide Seiten wurden seit der letzten Synchronisation verändert! Browse Auswählen Build: Build: Cancel Abbrechen +Cannot determine sync-direction: Changed filter settings! +Synchronisationsrichtung konnte nicht bestimmt werden: Filtereinstellungen wurden geändert! +Cannot determine sync-direction: No change since last synchronization! +Synchronisationsrichtung konnte nicht bestimmt werden: Keine Änderungen seit der letzten Synchronisation! +Category +Kategorie Change direction Richtung ändern Check all @@ -376,6 +390,8 @@ Error reading file attributes: Fehler beim Lesen der Dateiattribute: Error reading file: Fehler beim Lesen der Datei: +Error reading from synchronization database: +Fehler beim Lesen der Synchronisationsdatenbank: Error resolving symbolic link: Fehler beim Auflösen des Symbolischen Links: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Fehler beim Schreiben der Dateiattribute: Error writing file: Fehler beim Schreiben der Datei: -Error: Source directory does not exist anymore: -Fehler: Quellverzeichnis existiert nicht mehr: +Error writing to synchronization database: +Fehler beim Schreiben der Synchronisationsdatenbank: +Source directory does not exist anymore: +Quellverzeichnis existiert nicht mehr: Example Beispiel Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Auf beiden Seiten existierende Dateien; linke Datei ist neuer Files that exist on both sides, right one is newer Auf beiden Seiten existierende Dateien; rechte Datei ist neuer +Files/folders found: +Gefundene Dateien/Ordner: Files/folders remaining: Verbliebene Dateien/Ordner: -Files/folders scanned: -Eingelesene Dateien/Ordner: Files/folders that exist on left side only Nur links exisitierende Dateien/Verzeichnisse Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync ist auf dem neuesten Stand! Full path Absoluter Pfad +Generating database... +Erzeuge Synchronisationsdatenbank... Generating file list... Erzeuge Dateiliste... Global settings @@ -536,10 +556,14 @@ Include temporarily Temporär einschließen Include: *.doc;*.zip;*.exe\nExclude: temp\\* Einschließen: *.doc;*.zip;*.exe\nAusschließen: temp\\* +Incompatible synchronization database format: +Inkompatibles Datenbankformat: Info Info Information Information +Initial synchronization. Please verify default copy-directions! +Erstmalige Synchronisation. Bitte die gesetzten Kopierrichtungen überprüfen! Integrate external applications into context menu. The following macros are available: Integriert externe Anwendungen in das Kontextmenu. Die folgenden Makros stehen zur Verfügung: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y Verschiebe Ordner %x in benutzerdefiniertes Verzeichnis %y Multiple... Verschiedene... +No database file existing yet: +Es existiert noch keine Datenbankdatei: Not enough free disk space available in: Nicht genügend freier Speicher verfügbar unter: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Für die Synchronisation werden nur die Dateien/Verzeichnisse berücksichtigt, die den Filtereinstellungen genügen. Der Filter wird dabei auf den Dateinamen relativ(!) zu den Basis-Synchronisationsverzeichnissen angewandt. +Open directly +Direkt öffnen +Open with Explorer +Mit Explorer öffnen +Open with Konqueror +Mit Konqueror öffnen Operation aborted! Vorgang abgebrochen! Operation: @@ -632,8 +664,6 @@ Report translation error Ãœbersetzungsfehler melden Reset Zurücksetzen -Result -Ergebnis Right Rechts S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Alle .doc, .zip und .exe Dateien mit Ausnahme des Verzeichnisses \"temp\" werden synchronisiert. Synchronize both sides simultaneously: Copy new or updated files in both directions. Beide Seiten gleichzeitig synchronisieren: Neue oder aktualisierte Dateien werden in beide Richtungen kopiert. +Synchronize both sides using a database. Deletions are detected automatically. +Beide Seiten mit Hilfe einer Datenbank synchronisieren. Löschungen werden automatisch erkannt. Synchronize... Synchronisieren Synchronizing... @@ -782,6 +814,8 @@ User-defined directory Benutzerdefiniertes Verzeichnis User-defined directory for deletion was not specified! Kein benutzerdefiniertes Verzeichnis zum Löschen angegeben! +Using default synchronization directions. Please recheck. +Benutze die Standard-Synchronisationsrichtungen. Bitte überprüfen. Variant Variante Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Wenn der Vergleich mit dieser Option gestartet wurde, wird folgender Entscheidungsbaum abgearbeitet: You can ignore the error to consider not existing directories as empty. Dieser Fehler kann ignoriert werden, um nicht existierende Verzeichnisse als leer anzusehen. +You can ignore the error to skip current folder pair. +Der Fehler kann ignoriert und das aktuelle Verzeichnispaar übersprungen werden. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Verbliebene Elemente können nochmals synchronisiert werden (OHNE dass ein erneuter Vergleich notwendig ist)! different diff --git a/BUILD/Languages/hungarian.lng b/BUILD/Languages/hungarian.lng index d12fbca8..63c502fb 100644 --- a/BUILD/Languages/hungarian.lng +++ b/BUILD/Languages/hungarian.lng @@ -69,7 +69,7 @@ A(z) %x nem megfelelÅ‘ FreeFileSync kötegelt feladat fájl! &Load configuration &BeállÃtások betöltése &New - +&Új &No &Nem &OK @@ -87,13 +87,13 @@ A(z) %x nem megfelelÅ‘ FreeFileSync kötegelt feladat fájl! &Yes &Igen (Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".) - +(Megjegyzés: Csak a FAT/FAT32 meghajtókat érinti ez a probléma!\nMinden más esetben ki lehet kapcsolni az \"1 órás különbség figyelmen kÃvül hagyása\" beállÃtást.) , . - Other side's counterpart to %dir - +- A %dir másik oldalon szereplÅ‘ párja - Other side's counterpart to %name - +- A %name másik oldalon szereplÅ‘ párja - conflict - ütközés - conflict (same date, different size) @@ -138,6 +138,8 @@ A(z) %x nem megfelelÅ‘ FreeFileSync kötegelt feladat fájl! 2. A csillag ('*') és a kérdÅ‘jel ('?') helyettesÃtÅ‘ karakterek megengedettek. 3. Exclude files directly on main grid via context menu. 3. Fájlok közvetlen kizárása a fÅ‘ listából helyi menü segÃtségével. +<Automatic> + <Directory> <Mappa> <Last session> @@ -168,6 +170,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Egy kötegelt feladat fájl létrehozása az automatizált szinkronizációhoz. Kötegelt feladat módban való indÃtáshoz egyszerűen meg kell adni a fájl nevét a FreeFileSync.exe-nek: FreeFileSync.exe <kötegelt feladat fájl>. Ezt ütemezni is lehet az operációs rendszer feladatkezelÅ‘jével. Auto-adjust columns Oszlopok automatikus igazÃtása +Automatic mode + Batch execution Kötegelt végrehajtás Batch file created successfully! @@ -176,12 +180,20 @@ Batch job Kötegelt feladat Big thanks for localizing FreeFileSync goes out to: Nagy köszönet a FreeFileSync lokalizációjáért\na következÅ‘ személyeknek: +Both sides have changed since last synchronization! + Browse Tallózás Build: Build: Cancel Mégsem +Cannot determine sync-direction: Changed filter settings! + +Cannot determine sync-direction: No change since last synchronization! + +Category + Change direction Irány megváltoztatása Check all @@ -211,7 +223,7 @@ Comparing content of files %x Comparing content... Tartalom összehasonlÃtása... Comparing files by content failed. - +Sikertelen a fájlok összehasonlÃtása tartalom alapján. Comparison Result Az összehasonlÃtás eredménye Comparison settings @@ -237,7 +249,7 @@ MegerÅ‘sÃtés Conflict detected: Ãœtközés történt: Conflicts/files that cannot be categorized - +Kategorizálhatatlan ütközések/fájlok Continue Folytatás Conversion error: @@ -263,7 +275,7 @@ A következÅ‘ fájlnak nem lehet meghatározni a kötetnevét: Could not initialize directory monitoring: A mappafigyelés inicializálása sikertelen: Could not read values for the following XML nodes: - +A következÅ‘ XML-csomópontok értékének beolvasása sikertelen: Create a batch job Kötegelt feladat létrehozása Creating folder %x @@ -277,19 +289,19 @@ Oszlopok testreszabása Customize... Testreszabás... D-Click - +D-Klikk DECISION TREE DÖNTÉSI FA Data remaining: HátralévÅ‘ adat: Data verification error: Source and target file have different content! - +AdatellenÅ‘rzési hiba: A forrás és cél fájl tartalma különbözik! Date Dátum Delay Várakozás Delay between detection of changes and execution of commandline in seconds - +A változások észlelése és a parancssor meghÃvása közötti várakozás másodpercben Delete files/folders existing on left side only Csak a bal oldalon létezÅ‘ fájlok/mappák törlése Delete files/folders existing on right side only @@ -311,7 +323,7 @@ Mappa törlése %x Deletion handling Törlések kezelése Description - +Megjegyzés Directories are dependent! Be careful when setting up synchronization rules: A mappák függenek egymástól! Legyen óvatos, amikor megadja a szinkronizálási szabályokat: Directories to watch @@ -376,6 +388,8 @@ Error reading file attributes: A fájl attribútumainak olvasása sikertelen: Error reading file: A fájl olvasása sikertelen: +Error reading from synchronization database: + Error resolving symbolic link: A szimbolikus link feloldása sikertelen: Error starting Volume Shadow Copy Service! @@ -388,8 +402,10 @@ Error writing file attributes: A fájl attribútumainak Ãrása sikertelen: Error writing file: A fájl Ãrása sikertelen: -Error: Source directory does not exist anymore: -Hiba: A forrásként megadott mappa többé nem létezik: +Error writing to synchronization database: + +Source directory does not exist anymore: +A forrásként megadott mappa többé nem létezik: Example Példa Exclude @@ -403,7 +419,7 @@ Azonnali kilépés és a visszatérési érték < 0 Exit with RC < 0 Kilépés (visszatérési érték < 0) External applications - +KülsÅ‘ alkalmazások Feedback and suggestions are welcome at: A visszajelzéseket és javaslatokat ide várjuk: File %x has an invalid date! @@ -431,17 +447,17 @@ A fájlok megegyezÅ‘ ha\n - a fájlméret\n - az utolsó módosÃtás dátuma\ Files remaining: HátralévÅ‘ fájlok: Files that are equal on both sides - +MegegyezÅ‘ fájlok mindkét oldalon Files that exist on both sides and have different content Mindkét oldalon létezÅ‘ fájlok különbözÅ‘ tartalommal Files that exist on both sides, left one is newer Mindkét oldalon létezÅ‘ fájlok, de a bal oldali újabb Files that exist on both sides, right one is newer Mindkét oldalon létezÅ‘ fájlok, de a jobb oldali újabb +Files/folders found: + Files/folders remaining: HátralévÅ‘ fájlok/mappák: -Files/folders scanned: -Vizsgált fájlok/mappák: Files/folders that exist on left side only Csak a bal oldalon létezÅ‘ fájlok/mappák Files/folders that exist on right side only @@ -457,7 +473,7 @@ SzűrÅ‘ nézet Folder Comparison and Synchronization Mappa összehasonlÃtás és szinkronizáció Free disk space available: - +Szabad lemezterület: FreeFileSync - Folder Comparison and Synchronization FreeFileSync - Mappa összehasonlÃtás és szinkronizáció FreeFileSync Batch Job @@ -472,6 +488,8 @@ FreeFileSync is up to date! A FreeFileSync naprakész! Full path Teljes elérési útvonal +Generating database... + Generating file list... Fájllista generálása... Global settings @@ -479,7 +497,7 @@ Globális beállÃtások Help Súgó Hidden dialogs: - +Rejtett párbeszédablakok: Hide all error and warning messages Összes hibaüzenet és figyelmeztetés elrejtése Hide conflicts @@ -505,9 +523,9 @@ A bal oldalon törlendÅ‘ fájlok elrejtése. Hide files that will be deleted on the right side A jobb oldalon törlendÅ‘ fájlok elrejtése. Hide files that will be overwritten on left side - +A bal oldalon felülÃrandó fájlok elrejtése Hide files that will be overwritten on right side - +A jobb oldalon felülÃrandó fájlok elrejtése Hide files that won't be copied A nem másolandó fájlok elrejtése Hide filtered items @@ -536,20 +554,24 @@ Include temporarily Ideiglenesen tartalmaz Include: *.doc;*.zip;*.exe\nExclude: temp\\* Csatol: *.doc;*.zip;*.exe\nKizár: temp\\* +Incompatible synchronization database format: + Info Információ Information Információ -Integrate external applications into context menu. The following macros are available: +Initial synchronization. Please verify default copy-directions! +Integrate external applications into context menu. The following macros are available: +KülsÅ‘ alkalmazás integrálása a helyi menübe. Az elérhetÅ‘ makrók a következÅ‘k: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) Lehetetlen a Lomtár (Recycle Bin) inicializálása!\n\nValószÃnűleg azért, mert nem Windost használ.\nHa szeretné ezt a funkciót használni, kérjük, lépjen kapcsolatba a szerzÅ‘vel. :) Leave as unresolved conflict - +Feloldatlan ütközésként hagyni Left Bal oldal Legend - +ElÅ‘zmény Load configuration from file BeállÃtások betöltése fájlból Load configuration history (press DEL to delete items) @@ -569,14 +591,16 @@ Oszlop mozgatása lefelé Move column up Oszlop mozgatása felfelé Move files to a user-defined directory. - +Fájlok mozgatása a felhasználó által megadott mappába. Moving %x to Recycle Bin %x mozgatása a Lomtárba Moving file %x to user-defined directory %y - +%x fájl mozgatása a felhasználó által megadott %y mappába Moving folder %x to user-defined directory %y - +%x mappa mozgatása a felhasználó által megadott %y mappába Multiple... +SokszorosÃtás +No database file existing yet: Not enough free disk space available in: Nincs elég szabad lemezterület: @@ -591,6 +615,12 @@ A felülÃrandó fájlok száma OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. +Csak a szűrésnek megfelelÅ‘ fájlok/mappák lesznek kijelölve szinkronizáláshoz. A szűrÅ‘ a szinkronizálás alap mappáihoz relatÃv fájl- és mappanevekre lesz alkalmazva. +Open directly + +Open with Explorer + +Open with Konqueror Operation aborted! Művelet megszakÃtva! @@ -615,7 +645,7 @@ Kérdés Quit Kilépés Re-enable all hidden dialogs? - +Engedélyezzük újra az összes rejtett párbeszédablakot? RealtimeSync - Automated Synchronization RealtimeSync - Automatikus szinkronizálás RealtimeSync configuration @@ -623,7 +653,7 @@ RealtimeSync beállÃtások Relative path RelatÃv útvonal Remove alternate settings - +AlternatÃv beállÃtások eltávolÃtása Remove folder Mappa eltávolÃtása Remove folder pair @@ -632,8 +662,6 @@ Report translation error FordÃtói hiba bejelentése Reset HelyreállÃtás -Result -Eredmény Right Jobb oldal S&ave configuration @@ -651,9 +679,9 @@ Vizsgálat: Select a folder Mappa kiválasztása Select alternate filter settings - +AlternatÃv szűrÅ‘beállÃtások kiválasztása Select alternate synchronization settings - +AlternatÃv szinkronizációs beállÃtások kiválasztása Select logfile directory: Naplófájl mappájának kiválasztása: Select variant: @@ -675,21 +703,21 @@ Csak a bal oldalon létezÅ‘ fájlok mutatása Show files that exist on right side only Csak a jobb oldalon létezÅ‘ fájlok mutatása Show files that will be created on the left side -A bal oldalon létrehozandó fájlok mutatása. +A bal oldalon létrehozandó fájlok mutatása Show files that will be created on the right side -A jobb oldalon létrehozandó fájlok mutatása. +A jobb oldalon létrehozandó fájlok mutatása Show files that will be deleted on the left side -A bal oldalon törlendÅ‘ fájlok mutatása. +A bal oldalon törlendÅ‘ fájlok mutatása Show files that will be deleted on the right side -A jobb oldalon törlendÅ‘ fájlok mutatása. +A jobb oldalon törlendÅ‘ fájlok mutatása Show files that will be overwritten on left side - +A bal oldalon felülÃrandó fájlok mutatása Show files that will be overwritten on right side - +A jobb oldalon felülÃrandó fájlok mutatása Show files that won't be copied A nem másolandó fájlok mutatása Show hidden dialogs - +Rejtett párbeszédablakok mutatása Show popup Felbukkanó ablak mutatása Show popup on errors or warnings @@ -730,6 +758,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Minden .doc, .zip és .exe fájl szinkronizálása a \"temp\" almappában találhatók kivételével. Synchronize both sides simultaneously: Copy new or updated files in both directions. Mindkét oldal szinkronizálása egyszerre: Új és frissÃtett fájlok másolása mindkét irányban. +Synchronize both sides using a database. Deletions are detected automatically. + Synchronize... Szinkronizálás Synchronizing... @@ -737,7 +767,7 @@ Szinkronizálás folyamatban... System out of memory! Nincs elég rendszermemória! Target directory already existing! - +A célmappa már létezik! Target file already existing! A célként megadott fájl már létezik! The file does not contain a valid configuration: @@ -779,13 +809,15 @@ Lomtár (Recycle Bin) használata Use Recycle Bin when deleting or overwriting files. A Lomtár használata fájlok törlésénél vagy felülÃrásánál. User-defined directory - +Felhasználó által megadott mappa User-defined directory for deletion was not specified! +A törléshez nem lett mappa megadva a felhasználó által! +Using default synchronization directions. Please recheck. Variant Variáns Verifying file %x - +%x fájl ellenÅ‘rzése Volume name %x not part of filename %y! A(z) %x kötetnevet nem tartalmazza a(z) %y fájlnév! Warning @@ -796,6 +828,8 @@ When the comparison is started with this option set the following decision tree Ha az összehasonlÃtás ezekkel a beállÃtásokkal lesz elindÃtva, akkor a következÅ‘ döntési fa érvényesül: You can ignore the error to consider not existing directories as empty. Figyelmen kÃvül hagyhatja a hibákat a nem létezÅ‘ mappákat üresnek tekintve. +You can ignore the error to skip current folder pair. + You may try to synchronize remaining items again (WITHOUT having to re-compare)! Meg lehet próbálni újra a megmaradt elemek szinkronizálását (az összehasonlÃtás újbóli elvégzése NÉLKÃœL)! different diff --git a/BUILD/Languages/italian.lng b/BUILD/Languages/italian.lng index ef007fa8..98ebdd4a 100644 --- a/BUILD/Languages/italian.lng +++ b/BUILD/Languages/italian.lng @@ -138,6 +138,8 @@ 2. Sono ammessi i caratteri generici '*' e '?'. 3. Exclude files directly on main grid via context menu. 3. Escludi i file direttamente sulla griglia principale tramite il menu contestuale. +<Automatic> +<Automatico> <Directory> <Directory> <Last session> @@ -168,6 +170,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Componi un file batch per la sincronia automatica. Per partire in modalità batch fai semplicemente seguire il nome del file all'eseguibile di FreeFileSync: FreeFileSync.exe <nomefilebatch>. Puoi anche schedulare l'operazione nelle operazioni pianificate del sistema operativo. Auto-adjust columns Larghezza automatica colonne +Automatic mode +Modalita' automatica Batch execution Esecuzione in batch Batch file created successfully! @@ -176,12 +180,20 @@ Batch job Batch job Big thanks for localizing FreeFileSync goes out to: Per la traduzione di FreeFileSync, un grazie va a: +Both sides have changed since last synchronization! +Entrambi i lati sono cambiati dall'ultima sincronizzazione! Browse Sfoglia Build: Build: Cancel Annulla +Cannot determine sync-direction: Changed filter settings! +Impossibile determinare direzione di sincronia: Impostazioni filtro cambiate! +Cannot determine sync-direction: No change since last synchronization! +Impossibile determinare direzione di sincronia: Nessuna modifica dall'ultima sincronizzazione! +Category +Categoria Change direction Cambia direzione Check all @@ -376,6 +388,8 @@ Error reading file attributes: Errore di lettura degli attributi file: Error reading file: Errore durante la lettura del file: +Error reading from synchronization database: +Errore in lettura dal database di sincronizzione: Error resolving symbolic link: Errore nella risoluzione di collegamento simbolico: Error starting Volume Shadow Copy Service! @@ -388,8 +402,10 @@ Error writing file attributes: Errore nella scrittura degli attributi file: Error writing file: Errore durante la scrittura del file: -Error: Source directory does not exist anymore: -Errore: la directory sorgente non è più esistente: +Error writing to synchronization database: +Errore in scrittura sul database di sincronizzazione: +Source directory does not exist anymore: +La directory sorgente non è più esistente: Example Esempio Exclude @@ -438,10 +454,10 @@ Files that exist on both sides, left one is newer Files esistenti su entrambi i lati, più recenti a sinistra Files that exist on both sides, right one is newer Files esistenti su entrambi i lati, più recenti a destra +Files/folders found: +Files/cartelle trovati: Files/folders remaining: Files/cartelle restanti: -Files/folders scanned: -Files/cartelle analizzati: Files/folders that exist on left side only Files/cartelle esistenti solo a sinistra Files/folders that exist on right side only @@ -467,11 +483,13 @@ FreeFileSync su Sourceforge FreeFileSync batch file FreeFileSync batch file FreeFileSync configuration -FreeFileSync configurazione +Configurazione di FreeFileSync FreeFileSync is up to date! FreeFileSync è aggiornato! Full path Percorso completo +Generating database... +Generazione database... Generating file list... Generazione lista dei file... Global settings @@ -536,10 +554,14 @@ Include temporarily Includi temporaneamente Include: *.doc;*.zip;*.exe\nExclude: temp\\* Includi: *.doc;*.zip;*.exe\nEscludi: temp\\* +Incompatible synchronization database format: +Formato database di sincronizzazione incompatibile: Info Info Information Informazioni +Initial synchronization. Please verify default copy-directions! +Prima sincronizzazione. Verifica il default per le direzioni di copia! Integrate external applications into context menu. The following macros are available: Integra applicazioni esterne nel menu contestuale. Sono disponibili le seguenti macro: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +600,8 @@ Moving folder %x to user-defined directory %y Spostamento di cartella %x nella directory personalizzata %y Multiple... Multiplo... +No database file existing yet: +Database file non ancora esistente: Not enough free disk space available in: Spazio libero su disco insufficiente in: Nothing to synchronize according to configuration! @@ -592,6 +616,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Solo file e directory che passano il filtro saranno selezionati per la sincronizzazione. Il filtro verrà applicato al nome relativo(!) sulla base delle directory di sincronizzazione. +Open directly +Apri direttamente +Open with Explorer +Apri con Explorer +Open with Konqueror +Apri con Konqueror Operation aborted! Operazione abortita! Operation: @@ -632,8 +662,6 @@ Report translation error Segnala errori di traduzione Reset Reset -Result -Risultato Right Destra S&ave configuration @@ -730,6 +758,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Sincronizza tutti i file .doc, .zip e .exe eccetto tutti quelli nella cartella \"temp\". Synchronize both sides simultaneously: Copy new or updated files in both directions. Sincronizza simultaneamente entrambi i lati: Copia file nuovi o aggiornati in entrambe le direzioni. +Synchronize both sides using a database. Deletions are detected automatically. +Sincronizza entrmbi i lati usando un database. Le cancellazioni sono rilevate automaticamente. Synchronize... Sincronizza... Synchronizing... @@ -782,6 +812,8 @@ User-defined directory Directory personalizzata User-defined directory for deletion was not specified! Directory personalizzata per la cancellazione non specificata! +Using default synchronization directions. Please recheck. +Impostate direzioni di sincronizzazione di default. Controllare nuovamente. Variant Variante Verifying file %x @@ -796,6 +828,8 @@ When the comparison is started with this option set the following decision tree Quando questo set di opzioni viene selezionato per la comparazione viene processato il seguente albero di decisioni: You can ignore the error to consider not existing directories as empty. Puoi ignorare l'errore per considerare directory inesistenti come vuote. +You can ignore the error to skip current folder pair. +Puoi ignorare l'errore per saltare la coppia di cartelle corrente. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Puoi provare a sincronizzare di nuovo gli elementi restanti (SENZA doverli ri-comparare) ! different diff --git a/BUILD/Languages/japanese.lng b/BUILD/Languages/japanese.lng index ecd3ccf5..11532097 100644 --- a/BUILD/Languages/japanese.lng +++ b/BUILD/Languages/japanese.lng @@ -138,6 +138,8 @@ 2. ワイルドカード㫠' * ' 㨠' ? ' を使用出æ¥ã¾ã™ã€‚ 3. Exclude files directly on main grid via context menu. 3. コンテã‚ストメニューã‹ã‚‰ç›´æŽ¥ãƒ•ã‚¡ã‚¤ãƒ«ã‚’除外出æ¥ã¾ã™ã€‚ +<Automatic> +<自動> <Directory> <ディレクトリ> <Last session> @@ -146,6 +148,8 @@ <複数é¸æŠž> A newer version of FreeFileSync is available: FreeFileSync ã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™: +ATTENTION: Failed directory access can lead to file deletions! +注æ„: ディレクトリã®ã‚¢ã‚¯ã‚»ã‚¹ã«å¤±æ•—ã—ãŸå ´åˆã€ãƒ•ã‚¡ã‚¤ãƒ«ã¯å‰Šé™¤ã•ã‚Œã¾ã™! Abort requested: Waiting for current operation to finish... ユーザã«ã‚ˆã‚‹ä¸æ–: ç¾åœ¨ã®å‡¦ç†ã‚’終了ã—ã¦ã„ã¾ã™.. ãŠå¾…ã¡ãã ã•ã„... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp 一括ã§åŒæœŸå‡¦ç†ã‚’è¡Œã†ãŸã‚ã®ãƒãƒƒãƒãƒ•ã‚¡ã‚¤ãƒ«ã‚’作æˆã—ã¾ã™ã€‚ 一括モードを開始ã™ã‚‹ã¨ãã¯ã€ãƒ•ã‚¡ã‚¤ãƒ«ã®ãƒ‘スåを実行ファイル\n< FreeFileSync.exe> \nã«ãƒãƒƒãƒãƒ•ã‚¡ã‚¤ãƒ«ã§æ¸¡ã™ã ã‘ã§ã™ã€‚ ã¾ãŸã€ã“ã®æ“作ã¯OSã®ã‚¿ã‚¹ã‚¯ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ©ã‹ã‚‰å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ Auto-adjust columns 列ã®è‡ªå‹•èª¿æ•´ +Automatic mode +自動モード Batch execution 一括処ç†ã‚’実行 Batch file created successfully! @@ -176,12 +182,20 @@ Batch job ä¸€æ‹¬å‡¦ç† Big thanks for localizing FreeFileSync goes out to: FreeFileSync ã®ãƒãƒ¼ã‚«ãƒ©ã‚¤ã‚ºã¸ã®å”力ã«æ„Ÿè¬ã—ã¾ã™: +Both sides have changed since last synchronization! +å‰å›žæœ€å¾Œã®åŒæœŸå‡¦ç†ä»¥é™ã€ä¸¡å´ã¨ã‚‚変更ãŒã‚ã‚Šã¾ã™! Browse å‚ç…§ Build: ビルド: Cancel ä¸æ¢ +Cannot determine sync-direction: Changed filter settings! +åŒæœŸæ–¹å‘を決定ã§ãã¾ã›ã‚“: フィルターè¨å®šãŒå¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™! +Cannot determine sync-direction: No change since last synchronization! +åŒæœŸæ–¹å‘を決定ã§ãã¾ã›ã‚“: å‰å›žæœ€å¾Œã®åŒæœŸå‡¦ç†ä»¥é™ã€å¤‰æ›´ã¯ã‚ã‚Šã¾ã›ã‚“ +Category +カテゴリ Change direction æ–¹å‘を変更 Check all @@ -376,6 +390,8 @@ Error reading file attributes: ファイル属性ã®å–å¾—ã«å¤±æ•—: Error reading file: ファイルèªã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼: +Error reading from synchronization database: +åŒæœŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‹ã‚‰ã®èªã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼: Error resolving symbolic link: シンボリックリンクã®è§£æ±ºã«å¤±æ•—: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: ファイル属性ã®æ›¸ãè¾¼ã¿ã‚¨ãƒ©ãƒ¼: Error writing file: ファイル書ãè¾¼ã¿ã‚¨ãƒ©ãƒ¼: -Error: Source directory does not exist anymore: -エラー: ソースディレクトリãŒå˜åœ¨ã—ã¾ã›ã‚“: +Error writing to synchronization database: +åŒæœŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸ã®æ›¸ãè¾¼ã¿ã‚¨ãƒ©ãƒ¼: +Source directory does not exist anymore: +ソースディレクトリãŒå˜åœ¨ã—ã¾ã›ã‚“: Example 例 Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer 両å´ã«å˜åœ¨ã™ã‚‹ãŒã€å·¦å´ã®æ–¹ãŒã‚ˆã‚Šæ–°ã—ã„ Files that exist on both sides, right one is newer 両å´ã«å˜åœ¨ã™ã‚‹ãŒã€å³å´ã®æ–¹ãŒã‚ˆã‚Šæ–°ã—ã„ +Files/folders found: +発見ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«/フォルダ: Files/folders remaining: -ファイル/フォルダã®ãƒªãƒãƒ¼ãƒ : -Files/folders scanned: -ファイル/フォルダã®ã‚¹ã‚ャン: +リãƒãƒ¼ãƒ ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«/フォルダ: Files/folders that exist on left side only å·¦å´ã®ã¿ã«å˜åœ¨ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«/フォルダ Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync ã¯æœ€æ–°ã§ã™! Full path フルパス +Generating database... +データベースを作æˆä¸... Generating file list... ファイル一覧を作æˆä¸... Global settings @@ -536,10 +556,14 @@ Include temporarily 一時フォルダをå«ã‚ã‚‹ Include: *.doc;*.zip;*.exe\nExclude: temp\\* å«ã‚ã‚‹: *.doc;*.zip;*.exe\n除外: temp\\* +Incompatible synchronization database format: +åŒæœŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›¸å¼ã«äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“: Info æƒ…å ± Information インフォメーション +Initial synchronization. Please verify default copy-directions! +åŒæœŸå‡¦ç†ã®åˆæœŸåŒ–.. デフォルトã®ã‚³ãƒ”ー方å‘ã‚’å†åº¦ç¢ºèªã—ã¦ãã ã•ã„! Integrate external applications into context menu. The following macros are available: 外部ã®ã‚¢ãƒ—リケーションをコンテã‚ストメニューã«çµ±åˆã€ä»¥ä¸‹ã®ãƒžã‚¯ãƒãŒåˆ©ç”¨ã§ãã¾ã™: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y フォルダ %x をユーザ定義ディレクトリ %y ã«ç§»å‹• Multiple... 複数処ç†... +No database file existing yet: +データベースãŒå˜åœ¨ã—ã¾ã›ã‚“: Not enough free disk space available in: 利用å¯èƒ½ãªãƒ‡ã‚£ã‚¹ã‚¯ç©ºã容é‡ãŒè¶³ã‚Šã¾ã›ã‚“: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. フィルターã«é©åˆã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«/ディレクトリã®ã¿åŒæœŸå¯¾è±¡ã«é¸æŠžã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã¯ã€åŒæœŸåŸºæº–ディレクトリã¸ã®ç›¸å¯¾çš„(!)ãªåå‰ã«é©ç”¨ã•ã‚Œã¾ã™ã€‚ +Open directly +ディレクトリを開ã +Open with Explorer +エクスプãƒãƒ¼ãƒ©ã§é–‹ã +Open with Konqueror +Konqueror ã§é–‹ã Operation aborted! æ“作ã®ä¸æ–! Operation: @@ -632,8 +664,6 @@ Report translation error 翻訳エラーã®è©³ç´° Reset リセット -Result -çµæžœ Right å³å´ S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ \"temp\" ã®ã‚µãƒ–フォルダを除ã„ã¦ã€ã™ã¹ã¦ã®.docã€.zipã€ãŠã‚ˆã³.exeファイルをåŒæœŸ Synchronize both sides simultaneously: Copy new or updated files in both directions. 両å´ã‚’åŒæ™‚ã«å‡¦ç†: 両方ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ã‚ˆã‚Šæ–°ã—ã„ファイルをコピー +Synchronize both sides using a database. Deletions are detected automatically. +データベースを利用ã—ã¦ä¸¡å´ã‚’åŒæœŸã€å‰Šé™¤ã•ã‚ŒãŸã‚‚ã®ã¯è‡ªå‹•çš„ã«æ¤œå‡ºã•ã‚Œã¾ã™ã€‚ Synchronize... åŒæœŸå‡¦ç†... Synchronizing... @@ -782,6 +814,8 @@ User-defined directory ユーã§å®šç¾©ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª User-defined directory for deletion was not specified! ユーザ定義ディレクトリãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“! +Using default synchronization directions. Please recheck. +デフォルトã§ä½¿ç”¨ã™ã‚‹åŒæœŸå‡¦ç†æ–¹å‘ (å†ç¢ºèªã—ã¦ãã ã•ã„) Variant 変化 Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree ã“ã®ã‚ªãƒ—ションã§æ¯”較を開始ã—ãŸå ´åˆã¯ã€ä»¥ä¸‹ã®ãƒ„リーã«å¾“ã£ã¦å‡¦ç†ãŒè¡Œã‚ã‚Œã¾ã™: You can ignore the error to consider not existing directories as empty. æ—¢å˜ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒç©ºã§ã¯ãªã„ã¨ã„ã†ã‚¨ãƒ©ãƒ¼ã¯ç„¡è¦–ã§ãã¾ã™ã€‚ +You can ignore the error to skip current folder pair. +ã“ã®ãƒ•ã‚©ãƒ«ãƒ€ãƒšã‚¢ã®ã‚¨ãƒ©ãƒ¼ã‚’無視ã—ã¦ã‚¹ã‚ップã§ãã¾ã™ã€‚ You may try to synchronize remaining items again (WITHOUT having to re-compare)! 残ã£ã¦ã„るファイルã¯ã€å†ã³åŒæœŸã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ (å†æ¯”較ã¨ã¯åˆ¥ã®å‹•ä½œ)! different diff --git a/BUILD/Languages/polish.lng b/BUILD/Languages/polish.lng index 14474715..65ac1a5b 100644 --- a/BUILD/Languages/polish.lng +++ b/BUILD/Languages/polish.lng @@ -138,6 +138,8 @@ 2. Użyj wieloznacznika (wildcard) '*' i '?'. 3. Exclude files directly on main grid via context menu. 3. Wyklucz pliki i foldery używajÄ…c prawego przycisku myszki. +<Automatic> +<Automatycznie> <Directory> <Katalog> <Last session> @@ -146,6 +148,8 @@ <zaznaczone elementy> A newer version of FreeFileSync is available: DostÄ™pna jest nowa wersja FreeFileSync: +ATTENTION: Failed directory access can lead to file deletions! +UWAGA: Niepoprawny dostÄ™p do katalogu może spowodować utratÄ™ pliku! Abort requested: Waiting for current operation to finish... Żądanie przerwania: Czekaj na koniec aktualnie wykonywanego zadania... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Twórz plik wsadowy dla automatyzacji procesu. By rozpocząć prace w tym trybie zwyczajnie uruchom plik klikajÄ…c dwa razy lub dodaj go do zadaÅ„ zaplanowanych Twojego systemu. Plik wsadowy może być również przekazywany jako parametr do programu w postaci: FreeFileSync.exe <plikwsadowy>. Auto-adjust columns Autodopasowanie kolumn +Automatic mode +Tryb automatyczny Batch execution Uruchomienie pliku wsadowego Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Plik wsadowy Big thanks for localizing FreeFileSync goes out to: PodziÄ™kowania za tÅ‚umaczenie FreeFileSync: +Both sides have changed since last synchronization! +Obie strony ulegÅ‚y zmianie od ostatniej synchronizacji! Browse PrzeglÄ…daj Build: Buduj: Cancel Anuluj +Cannot determine sync-direction: Changed filter settings! +Nie można okreÅ›lik kierunku synchronizacji: Zmieniono ustawienia filtra! +Cannot determine sync-direction: No change since last synchronization! +Nie można okreÅ›lik kierunku synchronizacji: Brak zmian od ostatniej synchronizacji! +Category +Kategoria Change direction ZmieÅ„ kierunek Check all @@ -376,6 +390,8 @@ Error reading file attributes: BÅ‚Ä…d odczytu atrybutów pliku: Error reading file: BÅ‚Ä…d odczytu pliku: +Error reading from synchronization database: +BÅ‚Ä…d odczytu z bazy danych synchronizacji: Error resolving symbolic link: BÅ‚Ä…d odczytu dowiÄ…zania symbolicznego: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: BÅ‚Ä…d zapisu atrybutów pliku: Error writing file: BÅ‚Ä…d zapisu pliku: -Error: Source directory does not exist anymore: -BÅ‚Ä…d: Katalog źródÅ‚owy nie istnieje: +Error writing to synchronization database: +BÅ‚Ä…d zapisu do bazy danych synchronizacji: +Source directory does not exist anymore: +Katalog źródÅ‚owy nie istnieje: Example PrzykÅ‚ad Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Pliki, które istniejÄ… po obu stronach, lewa strona jest nowsza Files that exist on both sides, right one is newer Pliki, które istniejÄ… po obu stronach, prawa strona jest nowsza +Files/folders found: +Znalezione pliki/katalogi: Files/folders remaining: PozostaÅ‚e Pliki/katalogi: -Files/folders scanned: -Przeskanowane Pliki/katalogi: Files/folders that exist on left side only Pliki/katalogi istniejÄ…ce tylko po lewej stronie Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync jest już uaktualniony! Full path PeÅ‚na scieżka +Generating database... +Generowanie bazy danych... Generating file list... Generowanie listy plików... Global settings @@ -536,10 +556,14 @@ Include temporarily DoÅ‚Ä…cz tymczasowo Include: *.doc;*.zip;*.exe\nExclude: temp\\* DoÅ‚Ä…cz: *.doc;*.zip;*.exe\nWyklucz: temp\\* +Incompatible synchronization database format: +Niepoprawny format bazy danych dla synchronizacji: Info Info Information Informacja +Initial synchronization. Please verify default copy-directions! +WstÄ™pna synchronizacja. Sprawdź domyÅ›lne kierunki synchronizacji! Integrate external applications into context menu. The following macros are available: DoÅ‚Ä…cz zewnÄ™trznÄ… aplikacjÄ™ do menu kontekstowego. DostÄ™pne macra: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y Przenoszenie folderu %x do katalogu użytkownika %y Multiple... Wiele... +No database file existing yet: +Brak pliku bazy danych: Not enough free disk space available in: Brak wystarczajÄ…cej przestrzeni dyskowej na: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Tylko pliki/katalogi zaakceptowane przez filtr bÄ™dÄ… synchronizowane. Filtr dziaÅ‚a dla nazw nazw relatywnych(!) wzglÄ™dem katalogu bazowego. +Open directly +Otwórz bezpoÅ›rednio +Open with Explorer +Otwórz za pomocÄ… Explorer +Open with Konqueror +Otwórz za pomocÄ… Konqueror Operation aborted! Operacja przerwana! Operation: @@ -632,8 +664,6 @@ Report translation error ZgÅ‚oÅ› bÅ‚Ä…d w tÅ‚umaczeniu Reset Resetuj -Result -Rezultat Right Prawy S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Synchronizuj wszystkie pliki .doc, .zip i exe z wyjÄ…tkiem folderu \"temp\" Synchronize both sides simultaneously: Copy new or updated files in both directions. Synchronizuj obie strony jednoczeÅ›nie: Kopiuj nowe albo uaktualniaj w obu folderach. +Synchronize both sides using a database. Deletions are detected automatically. +Synchronizuj strony przy użyciu bazy danych. UsuniÄ™cia wykrywane sÄ… automatycznie. Synchronize... Synchronizuj... Synchronizing... @@ -782,6 +814,8 @@ User-defined directory Katalog użytkownika User-defined directory for deletion was not specified! Katalog użytkownika dla elementów usuniÄ™tych nie zostaÅ‚ okreÅ›lony! +Using default synchronization directions. Please recheck. +Ustawione sÄ… domyÅ›lne kierunki synchronizacji. Sprawdź ponownie. Variant Wariant Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Gdy porównywanie z zaznaczonÄ… opcjÄ… jest w toku, podejmowane sÄ… nastÄ™pujÄ…ce dezyje: You can ignore the error to consider not existing directories as empty. Możesz zignorować ten bÅ‚Ä…d i uznać nieistniejÄ…cy katalog za pusty. +You can ignore the error to skip current folder pair. +Możesz zignorować problem i przejść do aktualnej pary folderów. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Możesz spróbować synchronizować pozostaÅ‚e elementy ponownie (bez koniecznoÅ›ci ponownego porównywania)! different diff --git a/BUILD/Languages/portuguese.lng b/BUILD/Languages/portuguese.lng index 97d6b758..c36fd259 100644 --- a/BUILD/Languages/portuguese.lng +++ b/BUILD/Languages/portuguese.lng @@ -87,7 +87,7 @@ &Yes &Sim (Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".) -(Apenas as drives FAT/FAT32 são afectadas por esta causa! \nPara todas as outras situações pode desactivar a opção \"ignorar diferença de 1 hora\".) +(Apenas as drives FAT/FAT32 são afectadas por este problema! \nPara todas as outras situações pode desactivar a opção \"ignorar diferença de 1 hora\".) , - Other side's counterpart to %dir @@ -138,6 +138,8 @@ 2. Usar '*' e '?' como caracteres de procura. 3. Exclude files directly on main grid via context menu. 3. Excluir ficheiros directamente da grelha através do menu de contexto. +<Automatic> +<Automático> <Directory> <Directório> <Last session> @@ -146,6 +148,8 @@ <Selecção Múltipla> A newer version of FreeFileSync is available: Mais recente versão do FreeFileSync disponÃvel: +ATTENTION: Failed directory access can lead to file deletions! +ATENÇÃO: Falha no acesso ao directório pode levar à eliminação de ficheiros! Abort requested: Waiting for current operation to finish... Abortar pedido: À espera do fim da operação... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Criar um batch para sincronização automática. Para iniciar o modo batch, passar o nome do ficheiro para o executável do FreeFileSync: FreeFileSync.exe <ficheiro batch>. Também pode ser calendarizado no programador de tarefas. Auto-adjust columns Auto ajustar colunas +Automatic mode +Modo automático Batch execution Execução do batch Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Ficheiro Batch Big thanks for localizing FreeFileSync goes out to: Pela tradução de FreeFileSync, um agradecimento a: +Both sides have changed since last synchronization! +Ambos os lados tiveram alterações desde a última sincronização! Browse Procurar Build: Criado: Cancel Cancelar +Cannot determine sync-direction: Changed filter settings! +Não é possÃvel determinar a direcção de sincronização: Alterações na configuração do filtro! +Cannot determine sync-direction: No change since last synchronization! +Não é possÃvel determinar a direcção de sincronização: Não há alterações desde a última sincronização! +Category +Categoria Change direction Mudar direcção Check all @@ -223,7 +237,7 @@ Configuração Configuration loaded! Configuração carregada! Configuration overview: -Parâmetros de configuração: +Parametros de configuração: Configuration saved! Configuração guardada! Configure filter @@ -376,6 +390,8 @@ Error reading file attributes: Erro ao ler atributos do ficheiro: Error reading file: Erro de leitura de ficheiro: +Error reading from synchronization database: +Erro ao ler a base de dados de sincronização: Error resolving symbolic link: Erro na resolução do link simbólico: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Erro na escrita dos atributos do ficheiro: Error writing file: Erro de escrita no ficheiro: -Error: Source directory does not exist anymore: -Erro: A pasta de origem já não existe: +Error writing to synchronization database: +Erro na escrita da base de dados de sincronização: +Source directory does not exist anymore: +A pasta de origem já não existe: Example Exemplo Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Ficheiros existentes dos dois lados, à esquerda é mais recente Files that exist on both sides, right one is newer Ficheiros existentes dos dois lados, à direita é mais recente +Files/folders found: +Ficheiros/pastas encontrados: Files/folders remaining: Ficheiros/pastas restantes: -Files/folders scanned: -Ficheiros/pastas analisados: Files/folders that exist on left side only Ficheiros/pastas existentes somente à esquerda Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync está actualizado! Full path Caminho completo +Generating database... +A gerar base de dados... Generating file list... A gerar lista ficheiros... Global settings @@ -536,10 +556,14 @@ Include temporarily Incluir temporariamente Include: *.doc;*.zip;*.exe\nExclude: temp\\* Incluir: *.doc;*.zip;*.exe\nExcluir: temp\\* +Incompatible synchronization database format: +Formato de base de dados de sincronização incompatÃvel: Info Info Information Informação +Initial synchronization. Please verify default copy-directions! +Sincronização inicial. Verifique as direcções de cópia iniciais! 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: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y A mover pasta %x para o directório %y Multiple... Multiplo... +No database file existing yet: +Base de dados inexistente: Not enough free disk space available in: Não há espaço livre suficiente em: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Apenas ficheiros/directórios que passem o filtro serão seleccionados para sincronização. O filtro será aplicado ao nome relativo(!) ao directório base de sincronização. +Open directly +Abrir +Open with Explorer +Abrir com o Explorer +Open with Konqueror +Abrir com o Konqueror Operation aborted! Operação abortada! Operation: @@ -632,8 +664,6 @@ Report translation error Informar um erro de tradução Reset Reiniciar -Result -Resultado Right Direita S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Sincronizar todos os ficheiros .doc, .zip e .exe excepto os da pasta \"temp\". Synchronize both sides simultaneously: Copy new or updated files in both directions. Sincronizar ambos os lados simultaneamente: Copiar os ficheiros novos ou mais recentes em ambas as direcções. +Synchronize both sides using a database. Deletions are detected automatically. +Sincronizar ambos os lados usando uma base de dados. Eliminações são detectadas automaticamente. Synchronize... Sincronizar... Synchronizing... @@ -782,6 +814,8 @@ User-defined directory Directório definido pelo utilizador User-defined directory for deletion was not specified! Directório para eliminação não foi especificado! +Using default synchronization directions. Please recheck. +Direcção de sincronização inicial em uso. Verifique de novo. Variant Variável Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Usar a seguinte árvore de decisão quando inicia com estas opções de comparação: You can ignore the error to consider not existing directories as empty. Pode ignorar o erro para considerar directórios não existentes como vazios. +You can ignore the error to skip current folder pair. +Pode ignorar o erro para saltar o par de pastas actual. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Pode tentar sincronizar os restantes elementos outra vez (SEM TER QUE comparar de novo) ! different diff --git a/BUILD/Languages/portuguese_br.lng b/BUILD/Languages/portuguese_br.lng index 0839d747..99d6d708 100644 --- a/BUILD/Languages/portuguese_br.lng +++ b/BUILD/Languages/portuguese_br.lng @@ -138,6 +138,8 @@ 2. Usar '*' e '?' como caracteres coringa. 3. Exclude files directly on main grid via context menu. 3. Excluir arquivos diretamente do grid principal através do menu de contexto. +<Automatic> +<Automático> <Directory> <Diretório> <Last session> @@ -168,6 +170,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Monta um arquivo batch para sincronização automatizada. Para iniciar o modo batch, passar o nome do arquivo para o executável do FreeFileSync: FreeFileSync.exe <arquivo batch>. Também pode ser programado no Agendador de Tarefas do sistema operacional. Auto-adjust columns Autoajustar colunas +Automatic mode +Modo automático Batch execution Execução do batch Batch file created successfully! @@ -176,12 +180,20 @@ Batch job Arquivo Batch Big thanks for localizing FreeFileSync goes out to: Pela tradução do FreeFileSync, um agradecimento a: +Both sides have changed since last synchronization! +Ambos os lados foram alterados desde a última sincronização! Browse Procurar Build: Criado: Cancel Cancelar +Cannot determine sync-direction: Changed filter settings! +Não foi possÃvel determinar a direção de sicronização: Configurações do filtro alteradas! +Cannot determine sync-direction: No change since last synchronization! +Não foi possÃvel determinar a direção de sicronização: Nenhuma alteração desde a última sincronização! +Category +Categoria Change direction Inverter sentido Check all @@ -376,6 +388,8 @@ Error reading file attributes: Erro ao ler atributos do arquivo: Error reading file: Erro ao ler arquivo: +Error reading from synchronization database: +Erro ao ler do banco de dados de sincronização: Error resolving symbolic link: Erro na resolução de link simbólico: Error starting Volume Shadow Copy Service! @@ -388,8 +402,10 @@ Error writing file attributes: Erro ao escrever atributos do arquivo: Error writing file: Erro ao escrever arquivo: -Error: Source directory does not exist anymore: -Erro: Diretório de origem não existe mais: +Error writing to synchronization database: +Erro ao escrever no banco de dados de sincronização: +Source directory does not exist anymore: +Diretório de origem não existe mais: Example Exemplo Exclude @@ -438,10 +454,10 @@ Files that exist on both sides, left one is newer Arquivos que existem nos dois lados, sendo à esquerda mais recentes Files that exist on both sides, right one is newer Arquivos que existem nos dois lados, sendo à direita mais recentes +Files/folders found: +Arquivos/pastas encontrados: Files/folders remaining: Arquivos/pastas restantes: -Files/folders scanned: -Arquivos/pastas analisados: Files/folders that exist on left side only Arquivos/pastas que existem somente à esquerda Files/folders that exist on right side only @@ -472,6 +488,8 @@ FreeFileSync is up to date! FreeFileSync está atualizado! Full path Caminho completo +Generating database... +Gerando banco de dados... Generating file list... Gerando lista de arquivos... Global settings @@ -536,10 +554,14 @@ Include temporarily Incluir temporariamente Include: *.doc;*.zip;*.exe\nExclude: temp\\* Incluir: *.doc;*.zip;*.exe\nExcluir: temp\\* +Incompatible synchronization database format: +Formato de banco de dados de sincronização incompatÃvel: Info Info Information Informação +Initial synchronization. Please verify default copy-directions! +Sincronização inicial. Por favor, verifique a direção de cópia padrão! 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: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +600,8 @@ Moving folder %x to user-defined directory %y Movendo pasta %x para o diretório especificado Multiple... Múltiplos... +No database file existing yet: +Nenhum arquivo de banco de dados existe ainda: Not enough free disk space available in: Espaço em disco insuficiente em: Nothing to synchronize according to configuration! @@ -592,6 +616,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Apenas arquivos/diretórios que passarem o filtro serão selecionados para sincronização. O filtro será aplicado ao nome relativo(!) aos diretórios base de sincronização. +Open directly +Abrir diretamente +Open with Explorer +Abrir com Explorer +Open with Konqueror +Abrir com Konqueror Operation aborted! Operação cancelada! Operation: @@ -632,8 +662,6 @@ Report translation error Reportar erro de tradução Reset Reiniciar -Result -Resultado Right Direita S&ave configuration @@ -730,6 +758,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Sincronizar todos arquivos .doc, .zip e .exe exceto tudo que estiver na subpasta \"temp\". Synchronize both sides simultaneously: Copy new or updated files in both directions. Sincronizar ambos os lados simultaneamente: Copia os arquivos novos ou mais recentes em ambas as direções. +Synchronize both sides using a database. Deletions are detected automatically. +Sincronizar ambos os lados usando um banco de dados. Eliminações são detectadas automaticamente. Synchronize... Sincronizar... Synchronizing... @@ -782,6 +812,8 @@ User-defined directory Diretório especificado User-defined directory for deletion was not specified! Diretório especificado para arquivos apagados não foi definido! +Using default synchronization directions. Please recheck. +Usando direções de sincronização padrões. Por favor, verificar novamente. Variant Variante Verifying file %x @@ -796,6 +828,8 @@ When the comparison is started with this option set the following decision tree Quando a comparação é iniciada com esta opção, a seguinte árvore de decisão é processada: You can ignore the error to consider not existing directories as empty. Você pode ignorar o erro para considerar diretórios não existente como vazios. +You can ignore the error to skip current folder pair. +Você pode ignorar o erro para pular o par de pastas atual. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Você pode tentar sincronizar os elementos restantes outra vez (SEM ter que comparar novamente)! different diff --git a/BUILD/Languages/romanian.lng b/BUILD/Languages/romanian.lng new file mode 100644 index 00000000..1e0626a5 --- /dev/null +++ b/BUILD/Languages/romanian.lng @@ -0,0 +1,842 @@ + MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE + MinGW \t- Windows port din GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE + Byte + BaiÈ›i + GB + GB + MB + MB + PB + PB + TB + TB + day(s) + zile + hour(s) + ore + kB + KB + min + min + sec + sec +%x / %y objects deleted successfully +%x / %y obiecte È™terse cu succes +%x Percent +%x Procente +%x directories +%x dosare +%x files, +%x fiÈ™iere, +%x is not a valid FreeFileSync batch file! +%x nu este un fiÈ™ier lot FreeFileSync valid ! +%x of %y rows in view +%x din %y rînduri afiÈ™ate +%x of 1 row in view +%x din 1 rînd afiÈ™at +&Abort +&Anulează +&About... +&Despre... +&Advanced +&Avansate +&Apply +&Aplică +&Cancel +&Anulează +&Check for new version +&Caută Versiune Nouă +&Create batch job +&Creează o Sarcină Lot +&Default +&Implicit +&Exit +&IeÈ™i +&Export file list +&Exportă Lista de FiÈ™iere +&File +&FiÈ™ier +&Global settings +&Setări Globale +&Help +&Ajutor +&Ignore +&Ignoră +&Language +&Limbă +&Load +&Deschide +&Load configuration +&Deschide ConfiguraÈ›ia +&New +&Nou +&No +&Nu +&OK +&OK +&Pause +&Pauză +&Quit +&IeÈ™i +&Restore +&Restaurează +&Retry +&Reîncearcă +&Save +&Salvează +&Yes +&Da +(Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".) +(Doar dispozitivele FAT/FAT32 sînt afectate de această problemă!\nÃŽn celelalte cazuri, puteÈ›i dezactiva setarea \"ignoră diferenÈ›a de 1-oră\".) +, +. +- Other side's counterpart to %dir +- Corespondentul din partea opusă al lui %dir +- Other side's counterpart to %name +- Corespondentul din partea opusă al lui %name +- conflict +- conflict +- conflict (same date, different size) +- conflict (aceeaÈ™i dată, mărime diferită) +- different +- diferit +- directory part only +- doar dosarele +- equal +- identic +- exists left only +- există doar în stînga +- exists right only +- există doar în dreapta +- full file or directory name +- numele complet al fiÈ™ierului sau dosarului +- left +- stînga +- left newer +- cel mai nou e în stînga +- right +- dreapta +- right newer +- cel mai nou e în dreapta +-Open-Source file synchronization- +-Soft cu sursă deschisă pentru sincronizarea de fiÈ™iere- +. +, +/sec +/sec +1 directory +1 dosar +1 file, +1 fiÈ™ier, +1. &Compare +1. &Compară +1. Enter relative file or directory names separated by ';' or a new line. +1. IntroduceÈ›i numele relative ale fiÈ™ierelor sau dosarelor, separate de semnul ';' sau de un rînd nou. +2. &Synchronize... +2. &Sincronizează... +2. Use wildcard characters '*' and '?'. +2. FolosiÈ›i metacaracterele '*' È™i '?' (asterisc È™i semn de întrebare). +3. Exclude files directly on main grid via context menu. +3. ExcludeÈ›i fiÈ™ierele È™i dosarele direct de pe grila principală cu ajutorul meniului contextual. +<Automatic> +<Automată> +<Directory> +<Dosar> +<Last session> +<Ultima sesiune> +<multiple selection> +<selectare multiplă> +A newer version of FreeFileSync is available: +Este disponibilă o versiune nouă de FreeFileSync: +ATTENTION: Failed directory access can lead to file deletions! +ATENÈšIE: EÈ™ecul accesului la dosar poate duce la È™tergerea de fiÈ™iere! +Abort requested: Waiting for current operation to finish... +Abandonare solicitată: Se aÈ™teaptă terminarea operaÈ›iunii în curs... +Aborted +Abandonat +About +Despre +Action +AcÈ›iune +Add folder +Adaugă Dosar +Add folder pair +Adaugă Pereche Nouă de Dosare +An exception occured! +A apărut o excepÈ›ie ! +As a result the files are separated into the following categories: +ÃŽn concluzie, fiÈ™ierele sînt repartizate în categoriile următoare : +As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller: +AÈ™a cum sugerează È™i numele, două fiÈ™iere cu acelaÈ™i nume sînt considerate identice dacă È™i numai dacă este identic È™i conÈ›inutul lor. Această opÈ›iune este utilă mai degrabă pentru verificările de consecvență decît pentru operaÈ›iunile de salvgardare [backup]. AÈ™a că timpurile fiÈ™ierelor (data È™i ora) nu sînt luaÈ›i deloc în considerare.\n\nCu această opÈ›iune activată, arborele de decizie e mai simplu : +Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner. +Se poate crea un fiÈ™ier cu un lot de comenzi [batch file] pentru sincronizarea automată. Pentru a porni în modul lot, indicaÈ›i astfel numele fiÈ™ierului lot pentru prelucrarea sa de către executabilul FreeFileSync : freefilesync.exe <fiÈ™ier lot>. Această operaÈ›iune poate fi programată în planificatorul de sarcini al sistemului de operare [task scheduler]. +Auto-adjust columns +Autoajustează Coloanele +Automatic mode +Mod Automat +Batch execution +Execută FiÈ™ierul Lot +Batch file created successfully! +FiÈ™ierul cu lotul de comenzi a fost creat cu succces ! +Batch job +Sarcină Lot +Big thanks for localizing FreeFileSync goes out to: +MulÈ›umiri pentru traducerea FreeFileSync : +Both sides have changed since last synchronization! +Ambele părÈ›i s-au modificat de la ultima sincronizare! +Browse +Explorează +Build: +Compilat la : +Cancel +Anulează +Cannot determine sync-direction: Changed filter settings! +Nu se poate determina sensul de sincronizare: Setările filtrului s-au schimbat! +Cannot determine sync-direction: No change since last synchronization! +Nu se poate determina sensul de sincronizare: Nici o modificare de la ultima sincronizare! +Category +Categorie +Change direction +Schimbă Sensul +Check all +Bifează Tot +Choose to hide filtered files/directories from list +Ascunde sau arată fiÈ™ierele/dosarele filtrate din listă +Comma separated list +Listă de elemente separate prin virgulă +Commandline +Linie de comandă +Commandline is empty! +Linia de comandă este goală! +Compare +Compară +Compare both sides +Compară PărÈ›ile Stîngă È™i Dreaptă +Compare by \"File content\" +Compară după \"ConÈ›inutul FiÈ™ierelor\" +Compare by \"File size and date\" +Compară după \"Data È™i Mărimea FiÈ™ierelor\" +Compare by... +Compară după: +Comparing content +Compar conÈ›inutul +Comparing content of files %x +Compar conÈ›inutul fiÈ™ierelor %x +Comparing content... +Compar conÈ›inutul... +Comparing files by content failed. +Compararea fiÈ™ierelor după conÈ›inut a eÈ™uat. +Comparison Result +Rezultatul Comparării +Comparison settings +Setările Comparării +Completed +Terminată +Configuration +ConfiguraÈ›ie +Configuration loaded! +ConfiguraÈ›ie încărcată ! +Configuration overview: +Panorama ConfiguraÈ›iei : +Configuration saved! +ConfiguraÈ›ie salvată ! +Configure filter +Configurează Filtrul +Configure filter... +Configurează Filtrul +Configure your own synchronization rules. +Aplicare a regulilor de sincronizare definite de utilizator pentru fiecare situaÈ›ie. Definirea se face cu butoanele colorate din partea dreaptă a panoului. +Confirm +Confirmare +Conflict detected: +Conflict detectat: +Conflicts/files that cannot be categorized +SituaÈ›ii care nu pot fi incluse într-o anumită categorie +Continue +Continuă +Conversion error: +Eroare de convertire: +Copy from left to right +Copiază de la stînga la dreapta +Copy from left to right overwriting +Copiază de la stînga la dreapta cu suprascriere +Copy from right to left +Copiază de la dreapta la stînga +Copy from right to left overwriting +Copiază de la dreapta la stînga cu suprascriere +Copy new or updated files to right folder. +Copiere în dosarul din dreapta a fiÈ™ierelor actualizate sau noi. +Copy to clipboard\tCTRL+C +Copiază în CliplanÈ™etă\tCTRL+C +Copying file %x to %y +Copiez fiÈ™ierul %x în %y +Copying file %x to %y overwriting target +Copiez fiÈ™ierul %x în %y cu suprascrierea È›intei +Could not determine volume name for file: +Nu pot determina numele volumului pentru fiÈ™ierul: +Could not initialize directory monitoring: +Nu pot iniÈ›ializa monitorizarea dosarelor: +Could not read values for the following XML nodes: +Nu pot citi valorile pentru următoarele noduri XML: +Create a batch job +Creează o Sarcină Lot +Creating folder %x +Creez dosarul %x +Current operation: +OperaÈ›iunea curentă : +Custom +Personalizată +Customize columns +Personalizează coloanele +Customize... +Personalizează... +D-Click +Clic-Dreapta +DECISION TREE +ARBORE DECIZIONAL +Data remaining: +Date rămase : +Data verification error: Source and target file have different content! +Eroare la verificarea datelor: FiÈ™ierele sursă È™i È›intă au conÈ›inut diferit! +Date +Dată +Delay +ÃŽntîrziere +Delay between detection of changes and execution of commandline in seconds +ÃŽntîrziere în secunde între detectarea modificărilor ÅŸi executarea liniei de comandă +Delete files/folders existing on left side only +Șterge doar fiÈ™ierele/dosarele din partea stîngă +Delete files/folders existing on right side only +Șterge doar fiÈ™ierele/dosarele din partea dreaptă +Delete files\tDEL +Șterge FiÈ™ierele\tDEL +Delete on both sides +Șterge din ambele părÈ›i +Delete on both sides even if the file is selected on one side only +Șterge din ameble părÈ›i, chiar dacă fiÈ™ierul e selecÈ›ionat într-o singură parte +Delete or overwrite files permanently. +FiÈ™ierele sînt È™terse sau suprascrise în mod definitiv. +Delete permanently +Șterge definitiv +Deleting file %x +Șterg fiÈ™ierul %x +Deleting folder %x +Șterg dosarul %x +Deletion handling +Gestionarea Ștergerii +Description +Descriere +Directories are dependent! Be careful when setting up synchronization rules: +Dosarele sînt interdependente! AtenÈ›ie la setarea regulilor de sincronizare: +Directories to watch +Dosare de monitorizat +Directory +Dosar +Directory does not exist: +Dosarul nu există : +Do not display visual status information but write to a logfile instead +Nu se afiÈ™ează informaÈ›iile despre stare, dar ele se scriu într-un fiÈ™ier jurnal [log] +Do not show this dialog again +Nu afiÈ™a din nou acest dialog +Do nothing +Nici o acÈ›iune +Do you really want to delete the following objects(s)? +Sigur doriÈ›i să È™tergeÈ›i următoarele elemente ? +Do you really want to move the following objects(s) to the Recycle Bin? +Sigur doriÈ›i să mutaÈ›i în Reciclator următoarele elemente ? +Do you want FreeFileSync to automatically check for updates every week? +DoriÈ›i ca FreeFileSync să caute automat actualizări în fiecare săptămînă ? +Donate with PayPal +DonaÈ›i prin PayPal +Download now? +Descarc acum ? +Drag && drop +TrageÈ›i un dosar peste compartiment sau folosiÈ›i butonul Explorează +Email +E-mail +Enable filter to exclude files from synchronization +Se activează filtrul pentru excluderea fiÈ™ierelor din sincronizare +Endless loop when traversing directory: +Buclă infinită la parcurgerea dosarului: +Error +Eroare +Error changing modification time: +Eroare la schimbarea datei de modificare: +Error copying file: +Eroare la copierea fiÈ™ierului: +Error copying locked file %x! +Eroare la copierea fiÈ™ierului zăvorît %x! +Error creating directory: +Eroare la crearea dosarului: +Error deleting directory: +Eroare la È™tergerea dosarului: +Error deleting file: +Eroare la È™tergerea fiÈ™ierului: +Error handling +Gestionarea Erorilor +Error loading library function: +Eroare la încărcarea bibliotecii de funcÈ›ii: +Error moving directory: +Eroare la mutarea dosarului: +Error moving file: +Eroare la mutarea fiÈ™ierului: +Error moving to Recycle Bin: +Eroare la mutarea în Reciclator: +Error opening file: +Eroare la deschiderea fiÈ™ierului: +Error parsing configuration file: +Eroare la parsarea fiÈ™ierului de configurare: +Error reading file attributes: +Eroare la citirea atributelor fiÈ™ierului: +Error reading file: +Eroare la citirea fiÈ™ierului: +Error reading from synchronization database: +Eroare la citirea din baza de date a sincronizării: +Error resolving symbolic link: +Eroare la rezolvarea legăturii simbolice: +Error starting Volume Shadow Copy Service! +Eroare la pornirea serviciului Volume Shadow Copy! +Error traversing directory: +Eroare la parcurgerea dosarului: +Error when monitoring directories. +Eroare la monitorizarea dosarelor. +Error writing file attributes: +Eroare la scrierea atributelor fiÈ™ierului: +Error writing file: +Eroare la scrierea fiÈ™ierului: +Error writing to synchronization database: +Eroare la scrierea în baza de date a sincronizării: +Source directory does not exist anymore: +Dosarul sursă nu mai există: +Example +Exemplu +Exclude +Excluse +Exclude temporarily +Exclude Temporar +Exclude via filter: +Exclude prin Filtru: +Exit immediately and set returncode < 0 +Programul se închide imediat È™i se setează returncode < 0 +Exit with RC < 0 +IeÈ™i cu RC < 0 +External applications +AplicaÈ›ii Externe +Feedback and suggestions are welcome at: +Opiniile È™i sugestiile sînt binevenite: +File %x has an invalid date! +FiÈ™ierul %x are o dată nevalidă ! +File already exists. Overwrite? +FiÈ™ierul există deja. DoriÈ›i să-l suprascrieÈ›i? +File content +ConÈ›inutul FiÈ™ierului +File does not exist: +FiÈ™ierul nu există: +File list exported! +Lista de fiÈ™iere a fost exportată! +File size and date +Mărimea È™i Data FiÈ™ierului +Filename +Numele FiÈ™ierului +Files %x have a file time difference of less than 1 hour!\n\nIt's not safe to decide which one is newer due to Daylight Saving Time issues. +FiÈ™ierele %x au o diferență de dată mai mică de 1 oră!\n\nNu este clar care e mai nou, din cauza problemelor cauzate de ora de vară. +Files %x have the same date but a different size! +FiÈ™ierele %x au aceeaÈ™i dată, dar mărime diferită! +Files are found equal if\n - file content\nis the same. +FiÈ™ierele sînt considerate identice dacă\n - conÈ›inutul\neste identic. +Files are found equal if\n - filesize\n - last write time and date\nare the same. +FiÈ™ierele sînt considerate identice dacă\n - mărimea\n - È™i data ultimei modificări\nsînt identice. +Files remaining: +FiÈ™iere rămase: +Files that are equal on both sides +FiÈ™iere identice în ambele părÈ›i +Files that exist on both sides and have different content +FiÈ™iere care există în ambele părÈ›i È™i au conÈ›inut diferit +Files that exist on both sides, left one is newer +FiÈ™iere care există în ambele părÈ›i, cel din stînga fiind mai nou +Files that exist on both sides, right one is newer +FiÈ™iere care există în ambele părÈ›i, cel din dreapta fiind mai nou +Files/folders found: +FiÈ™iere/dosare găsite: +Files/folders remaining: +FiÈ™iere/dosare rămase: +Files/folders that exist on left side only +FiÈ™iere sau dosare care există doar în partea stîngă +Files/folders that exist on right side only +FiÈ™iere sau dosare care există doar în partea dreaptă +Filter +Filtrare +Filter active: Press again to deactivate +Filtru activ: clicaÈ›i din nou pentru a-l dezactiva +Filter files +Filtrează FiÈ™ierele +Filter view +Filtru de Vedere +Folder Comparison and Synchronization +Comparare È™i Sincronizare de Dosare +Free disk space available: +SpaÈ›iu disponibil pe hardisc : +FreeFileSync - Folder Comparison and Synchronization +FreeFileSync - Comparare È™i Sincronizare de Dosare +FreeFileSync Batch Job +FreeFileSync Sarcină cu Lot de Comenzi +FreeFileSync at Sourceforge +FreeFileSync la Sourceforge +FreeFileSync batch file +FreeFileSync fiÈ™ier cu lot de comenzi +FreeFileSync configuration +FreeFileSync configuraÈ›ie +FreeFileSync is up to date! +AveÈ›i deja ultima versiune a softului! +Full path +Cale completă +Generating database... +Generez baza de date... +Generating file list... +Generez lista de fiÈ™iere... +Global settings +Setări Globale +Help +Ajutor +Hidden dialogs: +Casete de dialog ascunse: +Hide all error and warning messages +Se ascund toate mesajele de eroare È™i de avertizare +Hide conflicts +Ascunde conflictele +Hide files that are different +Ascunde fiÈ™ierele care sînt diferite +Hide files that are equal +Ascunde fiÈ™ierele care sînt identice +Hide files that are newer on left +Ascunde fiÈ™ierele care sînt mai noi în stînga +Hide files that are newer on right +Ascunde fiÈ™ierele care sînt mai noi în dreapta +Hide files that exist on left side only +Ascunde fiÈ™ierele care există doar în stînga +Hide files that exist on right side only +Ascunde fiÈ™ierele care există doar în dreapta +Hide files that will be created on the left side +Ascunde fiÈ™ierele care vor fi create în stînga +Hide files that will be created on the right side +Ascunde fiÈ™ierele care vor fi create în dreapta +Hide files that will be deleted on the left side +Ascunde fiÈ™ierele care vor fi È™terse în stînga +Hide files that will be deleted on the right side +Ascunde fiÈ™ierele care vor fi È™terse în dreapta +Hide files that will be overwritten on left side +Ascunde fiÈ™ierele care vor fi suprascrise în stînga +Hide files that will be overwritten on right side +Ascunde fiÈ™ierele care vor fi suprascrise în dreapta +Hide files that won't be copied +Ascunde fiÈ™ierele care nu vor fi copiate +Hide filtered items +Ascunde itemurile filtrate +Hide further error messages during the current process +Ascunde mesajele de eroare apărute ulterior în timpul acestui proces +Hints: +Sfaturi: +Homepage +Sit +If you like FFS +Donare pentru FFS +Ignore 1-hour file time difference +Ignoră diferenÈ›ele de 1 oră ale timpurilor fiÈ™ierelor +Ignore errors +Ignoră erorile +Ignore subsequent errors +Ignoră erorile ulterioare +Ignore this error, retry or abort synchronization? +Ignor eroarea, reîncerc sau abandonez sincronizarea ? +Ignore this error, retry or abort? +Ignor eroarea, reîncerc sau abandonez? +Include +Incluse +Include temporarily +Include temporar +Include: *.doc;*.zip;*.exe\nExclude: temp\\* +Incluse : *.doc;*.zip;*.exe\nExcluse : temp\\* +Incompatible synchronization database format: +Format incompatibil al bazei de date a sincronizării: +Info +Info +Information +InformaÈ›ii +Initial synchronization. Please verify default copy-directions! +Sincronizare iniÈ›ială. VerificaÈ›i sensurile de copiere implicite! +Integrate external applications into context menu. The following macros are available: +Include aplicaÈ›iile externe în meniul contextual. Sînt disponibile următoarele macrocomenzi: +It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) +IniÈ›ializarea Reciclatorului nu a fost posibilă!\n\nCauza poate fi faptul că nu utilizaÈ›i SO Windows.\nDacă doriÈ›i să utilizaÈ›i această funcÈ›ionalitate, contactaÈ›i autorul. :) +Leave as unresolved conflict +Lasă ca un conflict nerezolvat +Left +Stînga +Legend +Legendă +Load configuration from file +ÃŽncarcă configuraÈ›ia dintr-un fiÈ™ier +Load configuration history (press DEL to delete items) +ÃŽncarcă istoricul configuraÈ›iei (apăsaÈ›i tasta DEL pentru a È™terge itemuri) +Log-messages: +Mesaje de jurnalizare: +Logging +Jurnalizez +Mirror ->> +Clonare =>> +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Salvgardare [backup] prin clonare a dosarului stîng: dosarul din dreapta va fi suprascris È™i va fi identic după sincronizare cu dosarul din stînga. +More than 50% of the total number of files will be copied or deleted! +Peste 50% din numărul total de fiÈ™iere vor fi copiate sau distruse! +Move column down +Mută coloana în jos +Move column up +Mută coloana în sus +Move files to a user-defined directory. +FiÈ™ierele sînt mutate într-un dosar ales de utilizator. +Moving %x to Recycle Bin +Mut %x în Reciclator +Moving file %x to user-defined directory %y +Mut fiÈ™ierul %x în dosarul %y ales de utilizator +Moving folder %x to user-defined directory %y +Mut dosarul %x în dosarul %y ales de utilizator +Multiple... +Multiplu... +No database file existing yet: +Nu există încă un fiÈ™ier cu baza de date: +Not enough free disk space available in: +SpaÈ›iu de stocare insuficient pe: +Nothing to synchronize according to configuration! +Nu este nimic de sincronizat conform configuraÈ›iei! +Number of files and directories that will be created +Numărul de fiÈ™iere È™i dosare care vor fi create +Number of files and directories that will be deleted +Numărul de fiÈ™iere È™i dosare care vor fi È™terse +Number of files that will be overwritten +Numărul de fiÈ™iere care vor fi suprascrise +OK +OK +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. +Doar fiÈ™ierele sau dosarele care trec de filtru vor fi selecÈ›ionate pentru sincronizare. Filtrul va fi aplicat la numele elementelor aflate ierarhic sub dosarul de sincronizat. +Open directly +Deschide Direct +Open with Explorer +Deschide cu Windows Explorer +Open with Konqueror +Deschide cu Konqueror +Operation aborted! +OperaÈ›iune abandonată! +Operation: +OperaÈ›iune: +Overview +Panoramă +Pause +Pauză +Paused +Pauzat +Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature. +CopiaÈ›i fiÈ™ierul \"Shadow.dll\" (din arhiva \"Shadow.zip\") în dosarul de instalare FreeFileSync pentru a putea utiliza această funcÈ›ionalitate. +Please fill all empty directory fields. +CompletaÈ›i toate cîmpurile unde trebuie să apară adrese ale dosarelor comparate. +Press button to activate filter +ClicaÈ›i butonul pentru a activa filtrul +Published under the GNU General Public License: +Publicat sub licenÈ›a GNU GPL: +Question +ÃŽntrebare +Quit +IeÈ™i +Re-enable all hidden dialogs? +ReactivaÈ›i casetele de dialog ascunse? +RealtimeSync - Automated Synchronization +RealtimeSync - Sincronizare Automatizată +RealtimeSync configuration +RealtimeSync configuraÈ›ie +Relative path +Calea Relativă +Remove alternate settings +ÃŽnlătură setările alternative +Remove folder +ÃŽnlătură Dosarul +Remove folder pair +ÃŽnlătură Perechea de Dosare +Report translation error +Raportarea erorilor de traducere +Reset +Resetează +Right +Dreapta +S&ave configuration +S&alvează ConfiguraÈ›ia +S&witch view +Schimbă &Vederea +Save changes to current configuration? +DoriÈ›i să salvaÈ›i modificările configuraÈ›iei curente? +Save current configuration to file +Salvează într-un fiÈ™ier modificările configuraÈ›iei curente +Scanning... +Scanez... +Scanning: +Scanez: +Select a folder +SelectaÈ›i un dosar +Select alternate filter settings +SelectaÈ›i o altă configuraÈ›ie a filtrului +Select alternate synchronization settings +SelectaÈ›i o altă configuraÈ›ie a sincronizării +Select logfile directory: +SelectaÈ›i un dosar pentru fiÈ™ierul .log: +Select variant: +SelectaÈ›i Varianta de Sincronizare: +Show conflicts +Arată conflictele +Show file icons +Arată iconiÈ›ele fiÈ™ierelor +Show files that are different +Arată fiÈ™ierele diferite +Show files that are equal +Arată fiÈ™ierele identice +Show files that are newer on left +Arată fiÈ™ierele din stînga mai noi decît cele din dreapta +Show files that are newer on right +Arată fiÈ™ierele din dreapta mai noi decît cele din stînga +Show files that exist on left side only +Arată fiÈ™ierele care există doar în stînga +Show files that exist on right side only +Arată fiÈ™ierele care există doar în dreapta +Show files that will be created on the left side +Arată fiÈ™ierele care vor fi create în stînga +Show files that will be created on the right side +Arată fiÈ™ierele care vor fi create în dreapta +Show files that will be deleted on the left side +Arată fiÈ™ierele care vor fi È™terse în stînga +Show files that will be deleted on the right side +Arată fiÈ™ierele care vor fi È™terse în dreapta +Show files that will be overwritten on left side +Arată fiÈ™ierele care vor fi suprascrise în stînga +Show files that will be overwritten on right side +Arată fiÈ™ierele care vor fi suprascrise în dreapta +Show files that won't be copied +Arată fiÈ™ierele care nu vor fi copiate +Show hidden dialogs +Arată casetele de dialog ascunse +Show popup +Arată caseta de dialog +Show popup on errors or warnings +Se arată o casetă de dialog pentru fiecare eroare sau avertisment +Significant difference detected: +Diferență semnificativă detectată: +Silent mode +Mod silenÈ›ios +Size +Mărime +Source code written completely in C++ utilizing: +Cod sursă scris complet în C++ folosind: +Speed: +Viteză : +Start +PorneÈ™te +Start synchronization +PorneÈ™te Sincronizarea +Statistics +Statistici +Stop +OpreÈ™te +Swap sides +Schimbă părÈ›ile între ele +Synchronization Preview +Previzionarea Sincronizării +Synchronization aborted! +Sincronizare abandonată! +Synchronization completed successfully! +Sincronizare terminată cu succes! +Synchronization completed with errors! +Sincronizare terminată cu erori! +Synchronization settings +Setările Sincronizării +Synchronization status +Starea Sincronizării +Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\". +Sincronizează fiÈ™ierele .doc, .zip È™i .exe, cu excepÈ›ia celor din dosarul \"temp\". +Synchronize both sides simultaneously: Copy new or updated files in both directions. +Sincronizare simultană a celor două părÈ›i: copiere în ambele sensuri a fiÈ™ierelor noi sau actualizate. +Synchronize both sides using a database. Deletions are detected automatically. +Sincronizare simultană a celor două părÈ›i folosind o bază de date. Ștergerile sînt detectate automat. +Synchronize... +Sincronizează +Synchronizing... +Sincronizare aflată în curs... +System out of memory! +Memoria sistemului a fost epuizată! +Target directory already existing! +Dosarul È›intă există deja! +Target file already existing! +FiÈ™ierul È›intă există deja! +The file does not contain a valid configuration: +FiÈ™ierul nu conÈ›ine o configuraÈ›ie validă: +This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. +Această variantă defineÈ™te două fiÈ™iere cu acelaÈ™i nume ca fiind identice atunci cînd au aceeaÈ™i mărime ȘI aceeaÈ™i dată È™i oră a ultimei modificări. +Time +Oră +Time elapsed: +Timp scurs : +Time remaining: +Timp rămas : +Total amount of data that will be transferred +Volumul total de date care va fi transferat +Total required free disk space: +SpaÈ›iu de stocare necesar: +Total time: +Timp total : +Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes. +Tratează ca egale timpurile fiÈ™ierelor care diferă exact cu +/- 1 oră, iar cele care diferă cu mai puÈ›in de 1 oră, ca niÈ™te conflicte generate de gestiunea orei de vară. +Two way <-> +Ambele Sensuri <=> +Unable to connect to sourceforge.net! +Conectarea la situl sourceforge.net nu poate fi realizată! +Unable to create logfile! +FiÈ™ierul jurnal nu poate fi creat! +Unable to initialize Recycle Bin! +Reciclatorul nu poate fi iniÈ›ializat! +Uncheck all +Debifează Tot +Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization. +Există conflicte nerezolvate!\n\nPuteÈ›i ignora conflictele pentru a continua cu sincronizarea. +Update -> +Actualizare => +Usage: Select directories for monitoring and enter a commandline. Each time files are modified within these directories (or subdirectories) the commandline is executed. +Utilizare: SelectaÈ›i dosarele de sincronizat È™i introduceÈ›i o linie de comandă. De fiecare dată cînd un fiÈ™ier este modificat în aceste dosare (sau subdosare), este executată linia de comandă. +Use Recycle Bin +Mută în reciclator +Use Recycle Bin when deleting or overwriting files. +Se foloseÈ™te Reciclatorul [Recycle Bin] cu ocazia È™tergerii sau suprascrierii unui fiÈ™ier. +User-defined directory +Mută într-un dosar personalizat +User-defined directory for deletion was not specified! +Dosarul ales de utilizator pentru È™tergere nu a fost specificat ! +Using default synchronization directions. Please recheck. +Se folosesc sensurile implicite de sincronizare. ReverificaÈ›i. +Variant +Varianta Sincronizării +Verifying file %x +Verific fiÈ™ierul %x +Volume name %x not part of filename %y! +Numele volumului %x nu face parte din numele fiÈ™ierului %y ! +Warning +Avertisment +Warning: Synchronization failed for %x item(s): +AtenÈ›ie : Sincronizarea a eÈ™uat pentru %x itemuri : +When the comparison is started with this option set the following decision tree is processed: +Cînd compararea este pornită cu acest set de opÈ›iuni, este executat următorul arbore de decizie: +You can ignore the error to consider not existing directories as empty. +PuteÈ›i ignora eroarea care consideră că un dosar inexistent este gol. +You can ignore the error to skip current folder pair. +PuteÈ›i ignora eroarea pentru a sări perechea de dosare curentă. +You may try to synchronize remaining items again (WITHOUT having to re-compare)! +PuteÈ›i încerca să sincronizaÈ›i din nou itemurile rămase (FÄ‚RÄ‚ să trebuiască să le recomparaÈ›i) ! +different +fiÈ™iere diferite +file exists on both sides +fiÈ™ierul există în ambele părÈ›i +on one side only +fiÈ™ierul există doar într-o parte diff --git a/BUILD/Languages/russian.lng b/BUILD/Languages/russian.lng index c6300e78..f050ab36 100644 --- a/BUILD/Languages/russian.lng +++ b/BUILD/Languages/russian.lng @@ -138,6 +138,8 @@ 2. ИÑпользуйте Ñимволы '*' и '?' Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ‹ неизвеÑтных. 3. Exclude files directly on main grid via context menu. 3. ИÑключите файлы прÑмо в главном окне через контекÑтное меню. +<Automatic> +<ÐвтоматичеÑкий> <Directory> <Папка> <Last session> @@ -146,6 +148,8 @@ <групповое выделение> A newer version of FreeFileSync is available: ДоÑтупна Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ FreeFileSync: +ATTENTION: Failed directory access can lead to file deletions! +Ð’ÐИМÐÐИЕ: Отказ в доÑтупе к каталогу может привеÑти к удалению файла! Abort requested: Waiting for current operation to finish... Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ñ‹: Ожидайте, пока Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚ÑÑ... Aborted @@ -157,7 +161,7 @@ Action Add folder Добавить папку Add folder pair -Добавить папку +Добавить пару папок An exception occured! ИÑключение произошло! As a result the files are separated into the following categories: @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Создайте файл Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ð·Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð½Ð¾Ð¹ Ñинхронизации. Чтобы запуÑтить программу в Ñтом режиме проÑто передайте название файла на выполнение FreeFileSync: FreeFileSync.exe <batchfile>. Ðто также может быть запиÑано в планировщике задач Вашей операционной ÑиÑтемы. Auto-adjust columns Ðвтовыравнивание ширины колонок +Automatic mode +ÐвтоматичеÑкий режим Batch execution Выполнение пакетного Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Пакетное задание Big thanks for localizing FreeFileSync goes out to: Большое ÑпаÑибо за перевод FreeFileSync: +Both sides have changed since last synchronization! +Со времени поÑледней Ñинхронизации Ñ Ð¾Ð±ÐµÐ¸Ñ… Ñторон произошли изменениÑ! Browse Обзор Build: Сборка: Cancel Отмена +Cannot determine sync-direction: Changed filter settings! +Ðевозможно определить направление Ñинхронизации: Изменены наÑтройки фильтра! +Cannot determine sync-direction: No change since last synchronization! +Ðевозможно определить направление Ñинхронизации: Ðикаких изменений поÑле поÑледней Ñинхронизации! +Category +ÐšÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ Change direction ПоменÑÑ‚ÑŒ направление Check all @@ -376,6 +390,8 @@ Error reading file attributes: Ошибка при чтении параметров файла: Error reading file: Ошибка при чтении файла: +Error reading from synchronization database: +Ошибка при чтении из базы данных Ñинхронизации: Error resolving symbolic link: Ошибка при решении ÑимволичеÑкой ÑÑылки: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Ошибка при запиÑи параметров файла: Error writing file: Ошибка при запиÑи файла: -Error: Source directory does not exist anymore: -Ошибка: ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° больше не ÑущеÑтвует: +Error writing to synchronization database: +Ошибка при запиÑи в базу данных Ñинхронизации: +Source directory does not exist anymore: +ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° больше не ÑущеÑтвует: Example Пример Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Файлы, ÑущеÑтвующие на обоих Ñторонах, левый новее Files that exist on both sides, right one is newer Файлы, ÑущеÑтвующие на обоих Ñторонах, правый новее +Files/folders found: +Файлов/папок найдено: Files/folders remaining: Файлов/папок оÑталоÑÑŒ: -Files/folders scanned: -Файлов/папок проÑканировано: Files/folders that exist on left side only Файлы/папки, ÑущеÑтвующие только на левой Ñтороне Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! У Ð’Ð°Ñ ÑÐ°Ð¼Ð°Ñ Ð¿Ð¾ÑледнÑÑ Ð²ÐµÑ€ÑÐ¸Ñ FreeFileSync! Full path Полный путь +Generating database... +Создание базы данных... Generating file list... Создание ÑпиÑка файлов... Global settings @@ -536,10 +556,14 @@ Include temporarily Ð’ÐºÐ»ÑŽÑ‡Ð°Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ðµ Include: *.doc;*.zip;*.exe\nExclude: temp\\* ВключаÑ: *.doc;*.zip;*.exe\nИÑключаÑ: temp\\* +Incompatible synchronization database format: +ÐеÑовмеÑтимый формат базы данных Ñинхронизации: Info Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Information Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ +Initial synchronization. Please verify default copy-directions! +ÐŸÐµÑ€Ð²Ð¾Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ ÑинхронизациÑ. ПожалуйÑта, проверьте направление копированиÑ! Integrate external applications into context menu. The following macros are available: Интегрирует внешние Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² контекÑтное меню.\nСледующие команды доÑтупны: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -561,7 +585,7 @@ Logging Mirror ->> Зеркало ->> Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. -Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð»ÐµÐ²Ð¾Ð¹ папки: Ð¿Ñ€Ð°Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° будет перезапиÑана и поÑле Ñинхронизации будет точно ÑоответÑтвовать левой папке +Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð»ÐµÐ²Ð¾Ð¹ папки: Ð¿Ñ€Ð°Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° будет перезапиÑана и поÑле Ñинхронизации будет точно ÑоответÑтвовать левой папке. More than 50% of the total number of files will be copied or deleted! Более 50% общего количеÑтва файлов будет Ñкопировано или удалено! Move column down @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y Перемещение папки %x в заданную пользователем папку %y Multiple... Различные варианты Ñинхронизации +No database file existing yet: +Файла базы данных еще не ÑущеÑтвует: Not enough free disk space available in: Ðе доÑтаточно Ñвободного меÑта в: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Только файлы/папки, которые проходÑÑ‚ фильтрацию будут отобраны Ð´Ð»Ñ Ñинхронизации. Фильтр будет применÑÑ‚ÑŒÑÑ ÐºÐ¾ вÑем именам, отноÑÑщимÑÑ Ðº оÑновным Ñинхронизируемым папкам. +Open directly +Открыть +Open with Explorer +Открыть путь в Проводнике +Open with Konqueror +Открыть путь в Konqueror Operation aborted! ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚Ð¼ÐµÐ½ÐµÐ½Ð°! Operation: @@ -627,13 +659,11 @@ Remove alternate settings Remove folder Удалить папку Remove folder pair -Удалить папку +Удалить пару папок Report translation error Сообщить об ошибке перевода Reset СброÑить -Result -ОпиÑание Right Справа S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Синхронизировать вÑе .doc, .zip и .exe файлы, за иÑключением вÑех файлов из подпапки \"temp\" Synchronize both sides simultaneously: Copy new or updated files in both directions. Синхронизировать обе Ñтороны одновременно: копировать новые или обновлÑÑ‚ÑŒ файлы в обоих направлениÑÑ…. +Synchronize both sides using a database. Deletions are detected automatically. +Синхронизировать обе Ñтороны, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð±Ð°Ð·Ñƒ данных. Удаленные файлы/папки определÑÑŽÑ‚ÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки. Synchronize... Синхронизировать Synchronizing... @@ -757,7 +789,7 @@ Total required free disk space: Total time: Общее времÑ: Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes. -Учитывать файлы, которые отличаютÑÑ Ð¿Ð¾ времени на 1 чаÑ, как равные, менее чем на 1 чаÑ, как конфликтные, чтобы учеÑÑ‚ÑŒ переход на летнее времÑ. +Учитывать файлы, которые отличаютÑÑ Ð¿Ð¾ времени на 1 чаÑ, как равные, менее чем на 1 чаÑ, как конфликтные, чтобы учеÑÑ‚ÑŒ переход на летнее Ð²Ñ€ÐµÐ¼Ñ Two way <-> Ð’ обоих направлениÑÑ… <-> Unable to connect to sourceforge.net! @@ -782,6 +814,8 @@ User-defined directory ИÑпользовать заданную пользователем папку User-defined directory for deletion was not specified! ПользовательÑÐºÐ°Ñ Ð¿Ð°Ð¿ÐºÐ° Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð½Ðµ была указана! +Using default synchronization directions. Please recheck. +ИÑпользуютÑÑ Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñинхронизации по-умолчанию. ПожалуйÑта, перепроверьте. Variant Вариант Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Когда Ñравнение запущено Ñ Ñтими критериÑми, алгоритм Ñледующий: You can ignore the error to consider not existing directories as empty. Ð’Ñ‹ можете проигнорировать ошибку, принÑв неÑущеÑтвующие папки за пуÑтые. +You can ignore the error to skip current folder pair. +Ð’Ñ‹ можете проигнорировать ошибку, чтобы пропуÑтить текущую пару папок и продолжить. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Ð’Ñ‹ можете попытатьÑÑ Ñинхронизировать оÑтавшиеÑÑ Ð¿ÑƒÐ½ÐºÑ‚Ñ‹ Ñнова (без повторного ÑравнениÑ)! different diff --git a/BUILD/Languages/slovenian.lng b/BUILD/Languages/slovenian.lng index 93a7e4f8..cf60cd2d 100644 --- a/BUILD/Languages/slovenian.lng +++ b/BUILD/Languages/slovenian.lng @@ -138,6 +138,8 @@ Duplikat z druge strani od %name 2. Uporabite lahko tudi znake '*' in '?'. 3. Exclude files directly on main grid via context menu. 3. IzkljuÄite datoteke neposredno na glavni mreži s kontekstnim menujem. +<Automatic> +<Samodejno> <Directory> <Imenik> <Last session> @@ -146,6 +148,8 @@ Duplikat z druge strani od %name <mnogokratna izbira> A newer version of FreeFileSync is available: Na voljo je nova razliÄica FreeFileSync: +ATTENTION: Failed directory access can lead to file deletions! +POZOR: NeuspeÅ¡en dostop do imenika lahko vodi do izbrisa datotek! Abort requested: Waiting for current operation to finish... Zahtevana je bila prekinitev: Äakam, da se zakljuÄi trenutna operacija... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Sestavi batch datoteko za samodejno sinhronizacijo. Da zaÄnete v batch naÄinu, preprosto podajte ime datoteke k FreeFileSync izvrÅ¡ilni datoteki: FreeFileSync.exe <imedatotekebatch>. To se lahko tudi nastavi v urniku opravil vaÅ¡ega operacijskega sistema. Auto-adjust columns Samo-prilagodi stolpce +Automatic mode +Samodejni naÄin Batch execution Batch izvajanje Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Batch opravilo Big thanks for localizing FreeFileSync goes out to: Zahvale za prevod FreeFileSync gredo: +Both sides have changed since last synchronization! +Obe strani sta se spremenili od zadnje sinhronizacije! Browse Brskaj Build: Izgradnja: Cancel PrekliÄi +Cannot determine sync-direction: Changed filter settings! +Ne morem doloÄiti smeri sinhronizacije: Spremenite nastavitve filtra! +Cannot determine sync-direction: No change since last synchronization! +Ne morem doloÄiti smeri sinhronizacije: Ni bilo sprememb od zadnje sinhronizacije! +Category +Kategorija Change direction Spremeni smer Check all @@ -376,6 +390,8 @@ Error reading file attributes: Napaka pri branju atributov datoteke: Error reading file: Napaka pri branju datoteke: +Error reading from synchronization database: +Napaka pri branju iz sinhronizacijske podatkovne baze: Error resolving symbolic link: Napaka pri razreÅ¡evanju simboliÄne povezave: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Napaka pri pisanju atributov datoteke: Error writing file: Napaka pri pisanju datoteke: -Error: Source directory does not exist anymore: -Napaka: Izvorni imenik ne obstaja veÄ: +Error writing to synchronization database: +Napaka pri pisanju v sinhronizacijsko podatkovno bazo: +Source directory does not exist anymore: +Izvorni imenik ne obstaja veÄ: Example Primer Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Datoteke, ki obstajajo na obeh straneh, leva je novejÅ¡a Files that exist on both sides, right one is newer Datoteke, ki obstajajo na obeh straneh, desna je novejÅ¡a +Files/folders found: +Najdene datoteke/mape: Files/folders remaining: Preostale datoteke/mape: -Files/folders scanned: -Pregledane datoteke/mape: Files/folders that exist on left side only Datoteke/mape, ki obstajajo samo na levi strani Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync je posodobljen! Full path Polna pot +Generating database... +Ustvarjam podatkovno bazo... Generating file list... Ustvarjam seznam datotek... Global settings @@ -536,10 +556,14 @@ Include temporarily Trenutno vkljuÄi Include: *.doc;*.zip;*.exe\nExclude: temp\\* VkljuÄi: *.doc;*.zip;*.exe\nIzkljuÄi: temp\\* +Incompatible synchronization database format: +Nekompatibilen format sinhronizacijske podatkovne baze: Info Info Information Informacije +Initial synchronization. Please verify default copy-directions! +ZaÄetna sinhronizacija. Prosimo preverite privzete smeri kopiranja! Integrate external applications into context menu. The following macros are available: Integriraj zunanje aplikacije v kontekstni menu. Na voljo so naslednji makri: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y Premikam mapo %x v uporabniÅ¡ko-doloÄen imenik %y Multiple... VeÄkratno... +No database file existing yet: +Datoteka podatkovne baze Å¡e ne obstaja: Not enough free disk space available in: Na voljo ni dovolj prostega prostora na disku v: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK V redu Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. Samo datoteke/imeniki, ki preidejo filtriranje bodo izbrani za sinhronizacijo. Filter bo uveljavljnen k imenu relativno(!) na bazo sinhroniziranih imenikov. +Open directly +Odpri neposredno +Open with Explorer +Odpri z Raziskovalcem +Open with Konqueror +Odpri s Konquerorjem Operation aborted! Operacija prekinjena! Operation: @@ -632,8 +664,6 @@ Report translation error PoroÄaj o napaki prevoda Reset Ponastavi -Result -Rezultat Right Desno S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Sinhroniziraj vse .doc, .zip in .exe datoteke, razen iz podmape \"temp\". Synchronize both sides simultaneously: Copy new or updated files in both directions. Sinhroniziraj obe strani istoÄasno: Kopiraj nove ali posodobljene datoteke v obe smeri. +Synchronize both sides using a database. Deletions are detected automatically. +Sinhroniziraj obe strani z uporabo podatkovne baze. Izbrisi so zaznani samodejno. Synchronize... Sinhroniziraj... Synchronizing... @@ -782,6 +814,8 @@ User-defined directory UporabniÅ¡ko-doloÄen imenik User-defined directory for deletion was not specified! UporabniÅ¡ko-doloÄen imenik za brisanje ni bil naveden! +Using default synchronization directions. Please recheck. +Uporabljam privzete sinhronizacijske smeri. Prosimo preverite ponovno. Variant RazliÄica Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Ko se primerjava zažene s tem setom možnosti, se obdela naslednje drevo odloÄitev: You can ignore the error to consider not existing directories as empty. Ignoriraj napako za smatranje neobstojeÄih imenikv kot praznih. +You can ignore the error to skip current folder pair. +Ignoriraj napako tako, da se spusti trenutni par map. You may try to synchronize remaining items again (WITHOUT having to re-compare)! Naslednje predmete lahko ponovno poskusite sinhronizirati (BREZ ponovne primerjave) ! different diff --git a/BUILD/Languages/spanish.lng b/BUILD/Languages/spanish.lng index ff290214..ea202d8a 100644 --- a/BUILD/Languages/spanish.lng +++ b/BUILD/Languages/spanish.lng @@ -138,6 +138,8 @@ 2. Usar '*' y '?' como caracteres comodÃn. 3. Exclude files directly on main grid via context menu. 3. Excluir directamente ficheros sobre la rejilla a través del menu de contexto. +<Automatic> + <Directory> <Directorio> <Last session> @@ -146,6 +148,8 @@ <Selección múltiple> A newer version of FreeFileSync is available: +ATTENTION: Failed directory access can lead to file deletions! + Abort requested: Waiting for current operation to finish... Abortar pedido: Esperar a que la actual operación finalice... Aborted @@ -168,6 +172,8 @@ Assemble a batch file for automated synchronization. To start in batch mode simp Crear un fichero "batch" para una sincronización automática. Para empezar en modo "batch" simplemente pasar el nombre del fichero al ejecutable FreeFileSyinc en la ventana de comandos (CMD): FreeFileSync.exe <nombre de fichero batch>. También puede ser planificada en el Administrador de Tareas programadas. Auto-adjust columns +Automatic mode + Batch execution Ejecución del "batch" Batch file created successfully! @@ -176,12 +182,20 @@ Batch job Tarea Batch Big thanks for localizing FreeFileSync goes out to: Agradecimientos por la traducción de FreeFileSync a: +Both sides have changed since last synchronization! + Browse Build: ConstruÃdo: Cancel Cancelar +Cannot determine sync-direction: Changed filter settings! + +Cannot determine sync-direction: No change since last synchronization! + +Category + Change direction Check all @@ -376,6 +390,8 @@ Error reading file attributes: Error al leer atributos del fichero: Error reading file: Error al leer el fichero: +Error reading from synchronization database: + Error resolving symbolic link: Error al resolver enlace simbólico: Error starting Volume Shadow Copy Service! @@ -388,8 +404,10 @@ Error writing file attributes: Error al escribir atributos del fichero: Error writing file: Error al escribir fichero: -Error: Source directory does not exist anymore: -Error: El directorio origen no existe ya: +Error writing to synchronization database: + +Source directory does not exist anymore: +El directorio origen no existe ya: Example Ejemplo Exclude @@ -438,10 +456,10 @@ Files that exist on both sides, left one is newer Ficheros que existen en ambos lados, el de la izquierda es más reciente Files that exist on both sides, right one is newer Ficheros que existen en ambos lados, el de la derecha es más reciente +Files/folders found: + Files/folders remaining: Ficheros/carpetas restantes: -Files/folders scanned: -Ficheros/carpetas analizados: Files/folders that exist on left side only Ficheros/carpetas que existen sólo en el lado izquierdo Files/folders that exist on right side only @@ -472,6 +490,8 @@ FreeFileSync is up to date! FreeFileSync está actualizado Full path +Generating database... + Generating file list... Generando lista de ficheros... Global settings @@ -536,10 +556,14 @@ Include temporarily Incluir temporalmente Include: *.doc;*.zip;*.exe\nExclude: temp\\* +Incompatible synchronization database format: + Info Info Information Información +Initial synchronization. Please verify default copy-directions! + Integrate external applications into context menu. The following macros are available: It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) @@ -578,6 +602,8 @@ Moving folder %x to user-defined directory %y Multiple... +No database file existing yet: + Not enough free disk space available in: Nothing to synchronize according to configuration! @@ -592,6 +618,12 @@ OK OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. +Open directly + +Open with Explorer + +Open with Konqueror + Operation aborted! Operación abortada! Operation: @@ -632,8 +664,6 @@ Report translation error Reset Reiniciar -Result -Resultado Right S&ave configuration @@ -730,6 +760,8 @@ Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\ Synchronize both sides simultaneously: Copy new or updated files in both directions. Sincronizar ambos lados simultáneamente: Copiar ficheros nuevos o actualizados en ambas direcciones. +Synchronize both sides using a database. Deletions are detected automatically. + Synchronize... Synchronizing... @@ -782,6 +814,8 @@ User-defined directory User-defined directory for deletion was not specified! +Using default synchronization directions. Please recheck. + Variant Verifying file %x @@ -796,6 +830,8 @@ When the comparison is started with this option set the following decision tree Cuando la comparación se inicia con este conjunto de opciones, se procesa el siguiente árbol de decisiones: You can ignore the error to consider not existing directories as empty. +You can ignore the error to skip current folder pair. + You may try to synchronize remaining items again (WITHOUT having to re-compare)! Puede intentar sincronizar los elementos restantes otra vez (SIN tener que volver a comparar) different diff --git a/BUILD/Languages/turkish.lng b/BUILD/Languages/turkish.lng new file mode 100644 index 00000000..2e0c1ff2 --- /dev/null +++ b/BUILD/Languages/turkish.lng @@ -0,0 +1,840 @@ + MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE + MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI Framework\n wxFormBuilder\t- wxWidgets GUI-Builder\n CodeBlocks \t- Open-Source IDE + Byte + Bit + GB + GB + MB + MB + PB + PB + TB + TB + day(s) + gün(ler) + hour(s) + saat(ler) + kB + kB + min + dak + sec + san +%x / %y objects deleted successfully +%x / %y obje baÅŸarıyla silindi +%x Percent +Yüzde %x +%x directories +%x dizin +%x files, +%x dosya, +%x is not a valid FreeFileSync batch file! +%x geçerli bir FreeFileSync komut (batch) dosyası deÄŸildir! +%x of %y rows in view +%y satırdan %x'i görüntüleniyor +%x of 1 row in view +1 satırdan %x'i görüntüleniyor +&Abort +Va&zgeç +&About... +&Hakkında... +&Advanced +&GeliÅŸmiÅŸ +&Apply +&Uygula +&Cancel +&Ä°ptal +&Check for new version +&Yeni sürüm kontrolü yap +&Create batch job +&Komut (batch) görevi oluÅŸtur +&Default +&Varsayılan +&Exit +Çı&kış +&Export file list +Dosya list&esini dışarı aktar +&File +&Dosya +&Global settings +&Genel ayarlar +&Help +&Yardım +&Ignore +&Yoksay +&Language +&Dil +&Load +&Yükle +&Load configuration +Konfigürasyon &yükle +&New +&Yeni +&No +&Hayır +&OK +&Tamam +&Pause +&Duraklat +&Quit +&Çık +&Restore +Ge&ri yükle +&Retry +&Yeniden dene +&Save +&Kaydet +&Yes +&Evet +(Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".) +(Not: Sadece FAT/FAT32 olarak biçimlendirilmiÅŸ sürücüler bu problemden etkilenir!\nDiÄŸer durumlarda, \"1-saat'lik zaman farkını yoksay\" ayarı devre dışı bırakılabilir.) +, +, +- Other side's counterpart to %dir +- %dir'e diÄŸer tarafın karşılığı +- Other side's counterpart to %name +- %name'e diÄŸer tarafın karşılığı +- conflict +- tutarsızlık +- conflict (same date, different size) +- tutarsızlık (aynı tarih, farklı ebat) +- different +- farklı +- directory part only +- sadece kısmi dizin +- equal +- eÅŸit +- exists left only +- sadece solda olan +- exists right only +- sadece saÄŸda olan +- full file or directory name +- tam dosya veya dizin adı +- left +- sol +- left newer +- soldaki daha yeni +- right +- saÄŸ +- right newer +- saÄŸdaki daha yeni +-Open-Source file synchronization- +-Açık kaynak dosya senkronizasyonu +. +. +/sec +/san +1 directory +1 dizin +1 file, +1 dosya, +1. &Compare +1. &KarşılaÅŸtır +1. Enter relative file or directory names separated by ';' or a new line. +1. ';' ile ayırarak veya herbiri yeni satırda olacak ÅŸekilde göreceli (relatif) dosya veya dizin adlarını girin. +2. &Synchronize... +2. &Senkronize et... +2. Use wildcard characters '*' and '?'. +2. Joker karakter olan '*' ve '?' kullan. +3. Exclude files directly on main grid via context menu. +3. SaÄŸ fare tuÅŸu ile açılan menüden ana listedeki dosyaları direk olarak hariç tutun. +<Automatic> +<Otomatik> +<Directory> +<Dizin> +<Last session> +<Önceki oturum> +<multiple selection> +<Çoklu seçim> +A newer version of FreeFileSync is available: +FreeFileSync'in yeni bir sürümü var: +Abort requested: Waiting for current operation to finish... +Vazgeçildi: Devam eden iÅŸlemin bitmesi bekleniyor... +Aborted +Vazgeçildi +About +Hakkında +Action +Ä°ÅŸlem +Add folder +Klasör ekle +Add folder pair +Klasör çifti ekle +An exception occured! +OlaÄŸan dışı bir durum oluÅŸtu! +As a result the files are separated into the following categories: +Sonuç olarak dosyalar takibeden katagorilere göre ayrıldı: +As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller: +Ä°smindende anlaşılacağı gibi, aynı isme sahip iki dosya sadece ve sadece aynı içeriÄŸe sahipse eÅŸit olarak iÅŸaretlenir. Bu seçenek yedekleme iÅŸlemlerinden daha ziyade uyuÅŸma kontrolü için faydalıdır. Bu yüzden dosya tarihleri hiç bir zaman dikkate alınmaz.\n\nBu seçenek etkinleÅŸtirildiÄŸinde karar ÅŸeması küçülür: +Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner. +Otomatik senkronizasyon için bir komut (batch) dosyası oluÅŸturun. Komut modunda baÅŸlamak için, komut dosyasını parametre olarak tanımlayarak FreeFileSync'i çalıştırın: FreeFileSync.exe <Komut Dosyası Adı>. Bu komut dosyası, istenirse, iÅŸletim sistemindeki görev zamanlayıcı ile istenilen zamanlarda çalıştırılabilir. +Auto-adjust columns +Kolonları otomatik olarak hizala +Automatic mode +Otomatik mod +Batch execution +Komut (batch) çalıştırılması +Batch file created successfully! +Komut (batch) dosyası baÅŸarıyla oluÅŸturuldu! +Batch job +Komut (batch) görevi +Big thanks for localizing FreeFileSync goes out to: +FreeFileSync'in çevirisinden dolayı çok teÅŸekkürler: +Both sides have changed since last synchronization! +En son senkronizasyondan sonra her iki tarafta deðiþmiþ bulunuyor! +Browse +AraÅŸtır +Build: +Derleme: +Cancel +Ä°ptal +Cannot determine sync-direction: Changed filter settings! +Senkronizasyon yönü belirlenemiyor: Filtre ayarlarý deðiþmiþ! +Cannot determine sync-direction: No change since last synchronization! +Senkronizasyon yönü belirlenemiyor: En son senkronizasyondan beri deðiþiklik yok! +Category +Kategori +Change direction +Yönü deÄŸiÅŸtir +Check all +Tümünü iÅŸaretle +Choose to hide filtered files/directories from list +Listedeki filtrelenmiÅŸ dosyaları/dizinleri gizlemek seçiniz +Comma separated list +Virgül ile ayrılmış liste +Commandline +Komut satırı +Commandline is empty! +Komut satırı boÅŸ! +Compare +KarşılaÅŸtır +Compare both sides +Ä°ki tarafıda karşılaÅŸtır +Compare by \"File content\" +\"Dosya içeriÄŸi\" ile karşılaÅŸtır +Compare by \"File size and date\" +\"Dosya ebadı ve tarihi\" ile karşılaÅŸtır +Compare by... +ile karşılaÅŸtır... +Comparing content +İçerik karşılaÅŸtırılıyor +Comparing content of files %x +%x dosyasının içeriÄŸi karşılaÅŸtırılıyor +Comparing content... +İçerik karşılaÅŸtırılıyor... +Comparing files by content failed. +Dosyaların içerik ile karşılaÅŸtırılması baÅŸarısız oldu. +Comparison Result +KarşılaÅŸtırma sonucu +Comparison settings +KarşılaÅŸtırma ayarları +Completed +Tamamlandı +Configuration +Konfigürasyon +Configuration loaded! +Konfigürasyon yüklendi! +Configuration overview: +Konfigürasyon özeti: +Configuration saved! +Konfigürasyon kaydedildi! +Configure filter +Filtrelemeyi ayarla +Configure filter... +Filtrelemeyi ayarla... +Configure your own synchronization rules. +Kendi senkronizasyon kurallarınızı ayarlayın. +Confirm +DoÄŸrula +Conflict detected: +Tutarsızlık saptandı: +Conflicts/files that cannot be categorized +Katagorize edilemeyen tutarsızlıklar/dosyalar +Continue +Devam et +Conversion error: +Dönüştürme hatası: +Copy from left to right +Soldan saÄŸa kopyala +Copy from left to right overwriting +Soldan saÄŸa üzerine yazmaya izin vererek kopyala +Copy from right to left +SaÄŸdan sola kopyala +Copy from right to left overwriting +SaÄŸdan sola üzerine yazmaya izin vererek kopyala +Copy new or updated files to right folder. +Yeni veya güncellenmiÅŸ dosyaları saÄŸdaki klasöre kopyala. +Copy to clipboard\tCTRL+C +Hafızaya kopyala\tCTRL+C +Copying file %x to %y +%x'den %y'e dosya kopyalanıyor +Copying file %x to %y overwriting target +%x'den %y'e üzerine yazmaya açık olarak dosya kopyalanıyor +Could not determine volume name for file: +Belirtilen dosya için birim adı belirlenemedi: +Could not initialize directory monitoring: +Dizin izlemesi baÅŸlatılamadı: +Could not read values for the following XML nodes: +Takibeden XML baÅŸlığındaki deÄŸerler okunamadı: +Create a batch job +Komut (batch) görevi oluÅŸtur +Creating folder %x +%x klasörü oluÅŸturuluyor +Current operation: +Halihazırdaki iÅŸlem: +Custom +Özel +Customize columns +Kolonları özelleÅŸtir +Customize... +ÖzelleÅŸtir... +D-Click +D-TuÅŸu +DECISION TREE +Karar Åžeması +Data remaining: +Kalan veri: +Data verification error: Source and target file have different content! +Veri doÄŸrulama hatası: Kaynak ve hedef dosyası içeriÄŸi farklı! +Date +Tarih +Delay +Gecikme +Delay between detection of changes and execution of commandline in seconds +Saniye olarak, deÄŸiÅŸikliklerin tespiti ile komut satırının çalıştırılması arasındaki boÅŸluk süresi +Delete files/folders existing on left side only +Sadece sol tarafta olan dosyaları/klasörleri sil +Delete files/folders existing on right side only +Sadece saÄŸ tarafta olan dosyaları/klasörleri sil +Delete files\tDEL +Dosyaları sil\tDEL +Delete on both sides +Her iki taraftakini sil +Delete on both sides even if the file is selected on one side only +Dosya sadece bir tarafta seçili olsa bile her iki taraftakini de sil +Delete or overwrite files permanently. +Kalıcı olarak üzerine yaz veya sil. +Delete permanently +Kalıcı olarak sil +Deleting file %x +%x dosyası siliniyor +Deleting folder %x +%x klasörü siliniyor +Deletion handling +Silme iÅŸleminin idaresi +Description +Açıklama +Directories are dependent! Be careful when setting up synchronization rules: +Dizinler bağımlı! Senkronizasyon kurallarını koyarken dikkatli olun: +Directories to watch +Ä°zlenecek dizinler +Directory +Dizin +Directory does not exist: +Dizin mevcut deÄŸil: +Do not display visual status information but write to a logfile instead +Görsel durum bilgisini ekrana getirme, fakat bir kayıt dosyasına yaz +Do not show this dialog again +Bu iletiyi tekrar gösterme +Do nothing +Hiçbir ÅŸey yapma +Do you really want to delete the following objects(s)? +Gerçekten ÅŸu objeleri silmek istiyormusunuz? +Do you really want to move the following objects(s) to the Recycle Bin? +Gerçekten ÅŸu objeleri geri dönüşüm kutusuna taşımak istiyormusunuz? +Do you want FreeFileSync to automatically check for updates every week? +Her hafta FreeFileSync'in güncellemeleri denetlemesini istermisiniz? +Donate with PayPal +PayPal ile bağış yapın +Download now? +Åžimdi indirilsinmi? +Drag && drop +Sürükle bırak +Email +Eposta +Enable filter to exclude files from synchronization +Senkronizasyon sırasında dosya hariç tutmayı etkinleÅŸtir +Endless loop when traversing directory: +Dizin iÅŸleminde sonsuz döngü: +Error +Hata +Error changing modification time: +DeÄŸiÅŸiklik tarihini deÄŸiÅŸtirirken hata: +Error copying file: +Dosya kopyalarken hata: +Error copying locked file %x! +Kilitli dosya %x'i kopyalarken hata! +Error creating directory: +Dizin oluÅŸtururken hata: +Error deleting directory: +Dizin silerken hata: +Error deleting file: +Dosya silerken hata: +Error handling +Hataları ele alma +Error loading library function: +Kütüphaneden fonksiyon yüklerken hata: +Error moving directory: +Dizin taşırken hata: +Error moving file: +Dosya taşırken hata: +Error moving to Recycle Bin: +Geri dönüşüm kutusuna taşırken hata: +Error opening file: +Dosya açarken hata: +Error parsing configuration file: +Konfigürasyon dosyasını çözümlerken hata: +Error reading file attributes: +Dosya özniteliklerini okurken hata: +Error reading file: +Dosyayı okurken hata: +Error reading from synchronization database: +Senkronizasyon veri tabanýndan okuma hatasý: +Error resolving symbolic link: +Sembolik baÄŸlantıyı çözümlerken hata: +Error starting Volume Shadow Copy Service! +'Volume shadow copy' servisini baÅŸlatırken hata! +Error traversing directory: +Dizini okurken hata: +Error when monitoring directories. +Dizinler izlenirken hata. +Error writing file attributes: +Dosya özniteliklerini yazarken hata: +Error writing file: +Dosya yazarken hata: +Error writing to synchronization database: +Senkronizasyon veri tabanýna yazma hatasý: +Example +Örnek +Exclude +Dışarda bırak +Exclude temporarily +Geçici olarak dışarda bırak +Exclude via filter: +Filtrelemeyle dışarda bırak: +Exit immediately and set returncode < 0 +Hemen çık ve 'returncode < 0' gerçekleÅŸtir +Exit with RC < 0 +RC < 0 ile çık +External applications +Harici uygulamalar +Feedback and suggestions are welcome at: +Geri bildirim ve öneriler için: +File %x has an invalid date! +%x dosyası geçersiz bir tarihe sahip! +File already exists. Overwrite? +Dosya zaten mevcut. Ãœzerine yazılsınmı? +File content +Dosya içeriÄŸi +File does not exist: +Dosya mevcut deÄŸil: +File list exported! +Dosya listesi karışmış! +File size and date +Dosya ebatı ve tarihi +Filename +Dosya adı +Files %x have a file time difference of less than 1 hour!\n\nIt's not safe to decide which one is newer due to Daylight Saving Time issues. +%X dosyaları 1 saat'ten daha az tarih farkına sahip!\n\Gün ışığından yararlanma ayarına baÄŸlı olarak hangisinin daha yeni olduÄŸuna karar vermek güvenli deÄŸil. +Files %x have the same date but a different size! +%x dosyalarının tarihleri aynı fakat ebatları farklı! +Files are found equal if\n - file content\nis the same. +\n - dosya içeriÄŸi\naynı ise dosyalar eÅŸit kabul edilir. +Files are found equal if\n - filesize\n - last write time and date\nare the same. +\n - dosya ebadı\n - son deÄŸiÅŸiklik tarihi\naynı ise dosyalar eÅŸit kabul edilir. +Files remaining: +Kalan dosyalar: +Files that are equal on both sides +Her iki tarafta eÅŸit olan dosyalar +Files that exist on both sides and have different content +Her iki tarafta aynı fakat içerikleri farklı dosyalar +Files that exist on both sides, left one is newer +Her iki tarafta mevcut olup solda olanı yeni olan dosyalar +Files that exist on both sides, right one is newer +Her iki tarafta mevcut olup saÄŸda olanı yeni olan dosyalar +Files/folders found: +Bulunan dosyalar/klasörler: +Files/folders remaining: +Kalan dosyalar/klasörler: +Files/folders that exist on left side only +Sadece sol tarafta mevcut olan dosyalar/klasörler +Files/folders that exist on right side only +Sadece saÄŸ tarafta mevcut olan dosyalar/klasörler +Filter +Filtre +Filter active: Press again to deactivate +Filtre etkin: EtkinliÄŸini kaldırmak için tekrar basın +Filter files +Fltre dosyaları +Filter view +Filtre görünümü +Folder Comparison and Synchronization +Klasör KarşılaÅŸtırması ve Senkronizasyonu +Free disk space available: +BoÅŸta kullanılabilir disk alanı: +FreeFileSync - Folder Comparison and Synchronization +FreeFileSync - Klasör KarşılaÅŸtırması ve Senkronizasyonu +FreeFileSync Batch Job +FreeFileSync Komut (Batch) Görevi +FreeFileSync at Sourceforge +Sourceforge'da FreeFileSync +FreeFileSync batch file +FreeFileSync komut (batch) dosyası +FreeFileSync configuration +FreeFileSync konfigürasyonu +FreeFileSync is up to date! +FreeFileSync güncel! +Full path +Tam dizin +Generating database... +Veri tabaný yaratýlýyor... +Generating file list... +Dosya listesi oluÅŸturuluyor... +Global settings +Genel ayarlar +Help +Yardım +Hidden dialogs: +GösterilmemiÅŸ iletiler: +Hide all error and warning messages +Hata ve uyarı mesajlarını gösterme +Hide conflicts +Tutarsızlıkları gösterme +Hide files that are different +Farklı olan dosyaları gösterme +Hide files that are equal +EÅŸit olan dosyaları gösterme +Hide files that are newer on left +Solda daha yeni olan dosyaları gösterme +Hide files that are newer on right +SaÄŸda daha yeni olan dosyaları gösterme +Hide files that exist on left side only +Sadece sol tarafta mevcut olan dosyaları gösterme +Hide files that exist on right side only +Sadece saÄŸ tarafta mevcut olan dosyaları gösterme +Hide files that will be created on the left side +Sol tarafta yaratılacak dosyaları gösterme +Hide files that will be created on the right side +SaÄŸ tarafta yaratılacak dosyaları gösterme +Hide files that will be deleted on the left side +Sol tarafta silinecek dosyaları gösterme +Hide files that will be deleted on the right side +SaÄŸ tarafta silinecek dosyaları gösterme +Hide files that will be overwritten on left side +Sol tarafta üzerine yazılacak dosyaları gösterme +Hide files that will be overwritten on right side +SaÄŸ tarafta üzerine yazılacak dosyaları gösterme +Hide files that won't be copied +Kopyalanmayacak dosyaları gösterme +Hide filtered items +FiltrelenmiÅŸ olanları gösterme +Hide further error messages during the current process +Devam eden iÅŸlem süresince daha fazla hata mesajı gösterme +Hints: +Ä°puçları: +Homepage +Ana sayfa +If you like FFS +EÄŸer FFS’i sevdiyseniz +Ignore 1-hour file time difference +1 saatlik dosya tarihi farklılaÅŸmasını yoksay +Ignore errors +Hataları yoksay +Ignore subsequent errors +Takibeden hataları yoksay +Ignore this error, retry or abort synchronization? +Bu hatayı yoksay, yeniden dene veya senkronizasyondan vazgeç? +Ignore this error, retry or abort? +Bu hatayı yoksay, yeniden dene veya vazgeç? +Include +Dahil et +Include temporarily +Geçici olarak dahil et +Include: *.doc;*.zip;*.exe\nExclude: temp\\* +Dahil et: *.doc;*.zip;*.exe\nHariç tut: temp\\* +Incompatible synchronization database format: +Uyumsuz senkronizasyon veritabaný formatý: +Info +Bilgi +Information +Bilgi +Initial synchronization. Please verify default copy-directions! +Baþlangýç senkronizasyonu. Lütfen ön tanýmlý kopyalama yönlerini doðrulayýnýz! +Integrate external applications into context menu. The following macros are available: +Harici uygulamaları içerik menüsüne ekle. Åžu makro’lar temin edilebilir: +It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) +Geri dönüşüm kutusunu baÅŸlatmak mümkün olmadı!\n\nMuhtemelen Microsoft Windows kullanmıyorsunuz.\nEÄŸer bu özelliÄŸin eklenmesini istiyorsanız, lütfen program yazarı ile temasa geçin. :) +Leave as unresolved conflict +ÇözülmemiÅŸ tutarsızlık olarak bırak +Left +Sol +Legend +Lejant +Load configuration from file +Dosyadan konfigürasyonu yükle +Load configuration history (press DEL to delete items) +Konfigürasyon geçmiÅŸini yükle (Öğeleri silmek için DEL’e basın) +Log-messages: +Kayıt mesajları: +Logging +Kayıt tutma +Mirror ->> +Yedekleme ->> +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Sol klasörün yedeklemesi: Senkronizasyondan sonra sol klasör ile tam olarak eÅŸleÅŸen saÄŸ klasörün üzerine yazılacak. +More than 50% of the total number of files will be copied or deleted! +%50’den fazla dosya kopyalanacak veya silinecek! +Move column down +Kolonu aÅŸağı taşı +Move column up +Kolonu yukarı taşı +Move files to a user-defined directory. +Dosyaları kullanıcı tanımlı bir dizine taşı. +Moving %x to Recycle Bin +%x geri dönüşüm kutusuna taşınıyor +Moving file %x to user-defined directory %y +%x dosyası kullanıcı tanımlı dizin %y’e taşınıyor +Moving folder %x to user-defined directory %y +%x klasörü kullanıcı tanımlı dizin %y’e taşınıyor +Multiple... +Çoklu... +No database file existing yet: +Henüz mevcut bir veritabaný yok: +Not enough free disk space available in: +Yeterli disk alanı yok : +Nothing to synchronize according to configuration! +Konfigürasyona göre senkronize edecek bir ÅŸey yok! +Number of files and directories that will be created +OluÅŸturulacak dosya ve dizinlerin sayısı +Number of files and directories that will be deleted +Silinecek dosya ve dizinlerin sayısı +Number of files that will be overwritten +Ãœzerine yazılacak dosyaların sayısı +OK +TAMAM +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories. +Senkronizasyon için sadece filtrelenmiÅŸ dosyalar/dizinler seçilecek. Senkronizasyon taban dizinlerine göreceli isimlere filtereleme uygulanacaktır. +Open directly +Doðrudan aç +Open with Explorer +Gezgin ile aç +Open with Konqueror +Konqueror ile aç +Operation aborted! +Ä°ÅŸlemden vazgeçildi! +Operation: +Ä°ÅŸlem: +Overview +DeÄŸerlendirme +Pause +Duraklat +Paused +Duraklatıldı +Please copy the appropriate \"Shadow.dll\" (located in \"Shadow.zip\" archive) into the FreeFileSync installation directory to enable this feature. +Bu özelliÄŸi etkinleÅŸtirmek için FreeFileSync’in kurulum dizinine \"Shadow.dll\" (\"Shadow.zip\" sıkıştırılmış dosyasındaki uygun olanı) kopyalayın. +Please fill all empty directory fields. +Lütfen boÅŸ dizin alanlarını doldurunuz. +Press button to activate filter +Filtrelemeyi etkinleÅŸtirmek için tuÅŸa basın +Published under the GNU General Public License: +“GNU General Public Licenseâ€a uygun olarak yayımlanmıştır: +Question +Soru +Quit +Çık +Re-enable all hidden dialogs? +Gösterilmeyen iletilerin görünmesini istermisiniz? +RealtimeSync - Automated Synchronization +RealtimeSync - Otomatik senkronizasyon +RealtimeSync configuration +RealtimeSync Konfigürasyon +Relative path +Göreceli dizin yolu +Remove alternate settings +Alternatif ayarları kaldır +Remove folder +Klasörü kaldır +Remove folder pair +Klasör çiftini kaldır +Report translation error +Çeviri hatasını bildir +Reset +Sıfırla +Right +SaÄŸ +S&ave configuration +Konfigürasyonu &kaydet +S&witch view +Görünümü &deÄŸiÅŸtir +Save changes to current configuration? +DeÄŸiÅŸiklikleri aktif konfigürasyona kaydetmek istermisiniz? +Save current configuration to file +Aktif konfigürasyonu dosyaya kaydet +Scanning... +Taranıyor... +Scanning: +Taranıyor: +Select a folder +Bir klasör seç +Select alternate filter settings +Alternatif filtreleme ayarı seç +Select alternate synchronization settings +Alternatif senkronizasyon ayarı seç +Select logfile directory: +Kayıt dosyası dizinini seç: +Select variant: +DeÄŸiÅŸkeni seç: +Show conflicts +Tutarsızlıkları göster +Show file icons +Dosya simgelerini göster +Show files that are different +Farklı olan dosyaları göster +Show files that are equal +EÅŸit olan dosyaları göster +Show files that are newer on left +Solda daha yeni olan dosyaları göster +Show files that are newer on right +SaÄŸda daha yeni olan dosyaları göster +Show files that exist on left side only +Sadece sol tarafta var olan dosyaları göster +Show files that exist on right side only +Sadece saÄŸ tarafta var olan dosyaları göster +Show files that will be created on the left side +Sadece sol tarafta yaratılacak dosyaları göster +Show files that will be created on the right side +Sadece saÄŸ tarafta yaratılacak dosyaları göster +Show files that will be deleted on the left side +Sadece sol tarafta silinecek dosyaları göster +Show files that will be deleted on the right side +Sadece saÄŸ tarafta silinecek dosyaları göster +Show files that will be overwritten on left side +Sadece sol tarafta üzerine yazılacak dosyaları göster +Show files that will be overwritten on right side +Sadece saÄŸ tarafta üzerine yazılacak dosyaları göster +Show files that won't be copied +Kopyalanmayacak dosyaları göster +Show hidden dialogs +GösterilmemiÅŸ diyalogları göster +Show popup +açılır bildirimleri göster +Show popup on errors or warnings +Hata ve uyarılarda açılır bildirimi göster +Significant difference detected: +Önemli fark saptandı: +Silent mode +Sessiz mod +Size +Ebat +Source code written completely in C++ utilizing: +Kaynak kod tümüyle C++ ile yazıldı: +Source directory does not exist anymore: +Kaynak dizin artık mevcut deÄŸil: +Speed: +Hız: +Start +BaÅŸla +Start synchronization +Senkronizasyonu baÅŸlat +Statistics +Ä°statistik +Stop +Durdur +Swap sides +Tarafları ters çevir +Synchronization Preview +Senkronizasyon Önizlemesi +Synchronization aborted! +Senkronizasyon durduruldu! +Synchronization completed successfully! +Senkronizasyon baÅŸarı ile tamamlandı! +Synchronization completed with errors! +Senkronizasyon hatalı olarak tamamlandı! +Synchronization settings +Senkronizasyon ayarları +Synchronization status +Senkronizasyon durumu +Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\". +\"temp\" alt klasöründeki herÅŸey hariç, tüm .doc, .zip ve .exe dosyalarını senkronize et. +Synchronize both sides simultaneously: Copy new or updated files in both directions. +Her iki tarafı eÅŸzamanlı olarak senkronize et: Yeni veya güncellenmiÅŸ dosyaları her iki yönede kopyala. +Synchronize both sides using a database. Deletions are detected automatically. +Bir veritabaný kullanarak iki tarafý senkronize et. Silmeler otomatik olarak algýlanýr. +Synchronize... +Senkronize et... +Synchronizing... +Senkronize ediliyor... +System out of memory! +Sistem hafızası yetersiz! +Target directory already existing! +Hedef dizin zaten mevcut! +Target file already existing! +Hedef dosya zaten mevcut! +The file does not contain a valid configuration: +Dosya geçerli bir konfigürasyon içermiyor: +This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. +Bu deÄŸiÅŸken, aynı isimli iki dosyanın, aynı ebata ve aynı son deÄŸiÅŸikik tarihine sahip olması durumunda eÅŸit olması anlamına gelir. +Time +Zaman +Time elapsed: +Geçen zaman: +Time remaining: +Kalan zaman: +Total amount of data that will be transferred +Transfer edilecek toplam veri miktarı +Total required free disk space: +Toplam gerekli boÅŸ disk alanı: +Total time: +Toplam zaman: +Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes. +Dosya tarihleri tam olarak +/- 1 saat farklı olduÄŸunda dosyaları eÅŸit olarak algıla. 1 saatten az tarih farklılıklarını ise tutarsızlık olarak belirt (Gün ışığından yararlanma durumu). +Two way <-> +Ä°ki yönlü <-> +Unable to connect to sourceforge.net! +sourceforge.net’e baÄŸlanılamıyor! +Unable to create logfile! +Kayıt dosyası yaratılamıyor! +Unable to initialize Recycle Bin! +Geri dönüşüm kutusu baÅŸlatılamıyor! +Uncheck all +Tüm iÅŸaretlemeleri kaldır +Unresolved conflicts existing! \n\nYou can ignore conflicts and continue synchronization. +Çözülemeyen tutarsızlık mevcut! \n\nTutarsızlıkları yoksayıp senkronizasyona devam edebilirsiniz. +Update -> +Güncelle -> +Usage: Select directories for monitoring and enter a commandline. Each time files are modified within these directories (or subdirectories) the commandline is executed. +Kullanım: Ä°zleme için dizinleri seç ve bir komut satırı ver. Bu dizinlerdeki (veya alt dizinlerdeki) dosyalar deÄŸiÅŸikliÄŸe her uÄŸradığında, girilen komut satırı çalıştırılacaktır. +Use Recycle Bin +Geri dönüşüm kutusunu kullan +Use Recycle Bin when deleting or overwriting files. +Silme ve üzerine yazma sırasında geri dönüşüm kutusunu kullan +User-defined directory +Kullanıcı tanımlı dizin +User-defined directory for deletion was not specified! +Silme için kulllanıcı tanımlı dizin belirtilmemiÅŸ! +Using default synchronization directions. Please recheck. +Ön tanýmlý senkronizasyon yönlerini kullanarak. Lütfen yeniden kontrol edin. +Variant +DeÄŸiÅŸken +Verifying file %x +%x dosyası doÄŸrulanıyor +Volume name %x not part of filename %y! +%x birim adı, %y dosya adının bölümü deÄŸil! +Warning +Uyarı +Warning: Synchronization failed for %x item(s): +Uyarı: %x kadar öğe için senkronizasyon baÅŸarısız oldu: +When the comparison is started with this option set the following decision tree is processed: +Bu opsiyonla karşılaÅŸtırma baÅŸlatıldığı zaman, takibeden karar ÅŸemasının iÅŸleme konacağını tanımla: +You can ignore the error to consider not existing directories as empty. +Var olamayan dizinleri boÅŸ olarak tanımlama hatasını yoksay. +You can ignore the error to skip current folder pair. +Halihazýrdaki klasör çiftini es geçmek için hatayý yok sayabilirsiniz. +You may try to synchronize remaining items again (WITHOUT having to re-compare)! +Kalan öğeleri tekrar senkronize etmeyi deneyebilirsiniz (Tekrar kaşılaÅŸtırma yapmadan)! +different +farklı +file exists on both sides +Dosya her iki tarafta da mevcut +on one side only +sadece tek tarafta diff --git a/BUILD/Readme.txt b/BUILD/Readme.txt index 20576738..f39bbb48 100644 --- a/BUILD/Readme.txt +++ b/BUILD/Readme.txt @@ -1,4 +1,4 @@ -FreeFileSync v2.3 +FreeFileSync v3.0 ----------------- --------- @@ -17,14 +17,15 @@ FreeFileSync v2.3 2. No limitations: An arbitrary number of files can be synchronized. 3. Unicode support. 4. Network support. -5. Full support for Windows/Linux Symbolic Links and Windows Junction Points. -6. Lean & easily accessible UI: Highly optimized for speed and huge sets of data. -7. Algorithms coded in C++ completely. -8. Progress indicators are updated only every 100ms for optimal performance! -9. Subfolders are also synchronized, including empty folders. -10. Support for multiple folder pairs -11. Create Batch Jobs for automated synchronization with or without GUI. -12. Focus on usability: +5. Synchronization database for automated setting of sync-directions +6. Support for multiple folder pairs with distinct configuration +7. Full support for Windows/Linux Symbolic Links and Windows Junction Points. +8. Lean & easily accessible UI: Highly optimized for speed and huge sets of data. +9. Algorithms coded in C++ completely. +10. Subfolders are also synchronized, including empty folders. +12. Progress indicators are updated only every 100ms for optimal performance! +12. Create Batch Jobs for automated synchronization with or without GUI. +13. Focus on usability: - Only necessary functionality on UI: no overloaded menus or icon jungle. - Select folders via drag & drop. - Last configuration and screen settings are saved automatically. @@ -36,22 +37,24 @@ FreeFileSync v2.3 - Status information and error reporting - Sort file-lists by name, size or date. - Display statistical data: total filesizes, amount of bytes that will be transfered with the current settings. -13. Support for filesizes larger than 4 GB. -14. Option to move files to Recycle Bin instead of deleting/overwriting them. -15. Automatically ignore directories "\RECYCLER" and "\System Volume Information" when comparing and sync'ing. (Windows only) -16. Localized versions for many languages are available. -17. Delete before copy: Avoid disc space shortages with large sync-operations. -18. Based on wxWidgets framework => Portable to many operating systems. -19. Filter functionality to include/exclude files from synchronization (without re-compare!). -20. Include/exclude specific files from synchronization manually. -21. Create sync jobs via GUI to synchronize automatically (can be scheduled or executed directly). -22. Handle daylight saving time changes on FAT/FAT32 volumes correctly. -23. Portable version (.zip) available. -24. No Windows registry entries for portable version. -25. Support for \\?\ path prefix for unrestricted path length. (Windows only) -26. Check for updates from within FreeFileSync automatically. -27. Copy locked files using Windows Volume Shadow Copy. (Windows only) -28. Load file icons asynchronously for maximum display performance. +14. Support for filesizes larger than 4 GB. +15. Option to move files to Recycle Bin instead of deleting/overwriting them. +16. Automatically ignore directories "\RECYCLER" and "\System Volume Information" with default Filter. (Windows only) +17. Localized versions for many languages are available. +18. Delete before copy: Avoid disc space shortages with large sync-operations. +19. Based on wxWidgets framework => Portable to many operating systems. +20. Filter functionality to include/exclude files from synchronization (without re-compare!). +21. Include/exclude specific files from synchronization manually. +22. Create sync jobs via GUI to synchronize automatically (can be scheduled or executed directly). +23. Handle daylight saving time changes on FAT/FAT32 volumes correctly. +24. Portable version (.zip) available. +25. No Windows registry entries for portable version. +26. Support for \\?\ path prefix for unrestricted path length. (Windows only) +27. Check for updates from within FreeFileSync automatically. +28. Copy locked files using Windows Volume Shadow Copy. (Windows only) +29. Load file icons asynchronously for maximum display performance. +30. Create regular backups with macros %time%, %date% within directory names + ------------------- @@ -71,6 +74,7 @@ FreeFileSync v2.3 - Instead of displaying "An error occurred!" you can specify any other command like sending an email notification (using a third party tool). +------------------------------------------------------------------------------------ 2.) Schedule Batch Job in Windows Task Planner - Create a FreeFileSync batch file. (E.g. C:\SyncJob.ffs_batch) @@ -80,6 +84,7 @@ FreeFileSync v2.3 C:\Program Files\FreeFileSync\FreeFileSync.exe C:\SyncJob.ffs_batch +------------------------------------------------------------------------------------ 3.) Drag & drop support FreeFileSync has a big focus on usability. Therefore drag & drop is supported in various situations: @@ -90,7 +95,8 @@ You can: - drag & drop any directory onto the main window to set the directory f - drag & drop *.ffs_batch files onto the main window to display and edit the batch configuration - drag & drop *.ffs_batch files onto the batch dialog to display and edit the batch configuration - + +------------------------------------------------------------------------------------ 4.) Exclude all subfolders from synchronization If you want to synchronize all files from the base synchronization directories only, simply set up a filter like this: @@ -101,6 +107,7 @@ If you want to synchronize all files from the base synchronization directories o This will exclude all objects within the two directories that end with a "\" character, which is interpreted as the end of a directory name, +------------------------------------------------------------------------------------ 5.) Synchronize with FTP FreeFileSync does not support FTP directly. But the FTP functionality can be easily activated by mapping the FTP webspace to a drive letter: @@ -111,6 +118,7 @@ Example: Use the free utility NetDrive (http://www.netdrive.net/) - Note: Most FTP drives set a file's timestamp to current time when synchronizing. As a workaround you can try a "compare by filesize", see below. +------------------------------------------------------------------------------------ 6.) Start external application on double-click FreeFileSync's default is to show files in the operating system's standard file browser on each double-click e.g. by invoking "explorer /select, %name" on Windows. @@ -120,10 +128,12 @@ Examples: - Start associated application: cmd /c start "" "%name" - Start visual difference tool: C:\Program Files\WinMerge\WinMergeU.exe "%name" "%nameCo" (Don't forget to use quotation marks if file names contain spaces!) - + +------------------------------------------------------------------------------------ 7. Synchronize USB sticks with variable drive letter -USB sticks often have different volume names assigned to them when plugged into two distinct computers. In order to handle this flexibility FreeFileSync is able to process directory names relative to the current working directory. Thus the following workflow is possible: +USB sticks often have different volume names assigned to them when plugged into two distinct computers. In order to handle this flexibility FreeFileSync is able to +process directory names relative to the current working directory. Thus the following workflow is possible: - Replace the absolute USB directory name (variable) in your configuration by a relative one: E.g. "E:\SyncDir" -> "\SyncDir" - Save and copy synchronization settings to the USB stick: "E:\settings.ffs_gui" @@ -132,6 +142,7 @@ USB sticks often have different volume names assigned to them when plugged into => Working directory automatically is set to "E:\" by the operating system so that "\SyncDir" is interpreted as "E:\SyncDir". Now start synchronization as usual. +------------------------------------------------------------------------------------ 8. Start RealtimeSync via commandline RealtimeSync can be used to load a configuration file and start processing immediately without additional user intervention. Just pass the name of a configuration file as @@ -140,6 +151,7 @@ first commandline argument. Example: C:\Program Files\FreeFileSync\RealtimeSync.exe MyConfig.ffs_real +------------------------------------------------------------------------------------ 9. Compare by filesize Sometimes you might want to compare both sides by filesize only, ignoring the last modification timestamp. Here is how you can do this: Open your *.ffs_gui configuration file @@ -147,6 +159,19 @@ and change the XML node <FileTimeTolerance> to some sufficiently large value. No synchronization direction for conflics can be used. +------------------------------------------------------------------------------------ +10. Create regular backups with time-stamped directory names + +You can use macros %time%, %date% within the directory names you want to synchronize: Assuming you have a directory "C:\Source" which you want to backup each day into a time-stamped target +directory like "C:\Target_2009-10-08", all that needs to be done is setting up base directories like this: + +Source folder: "C:\Source" +Target folder: "C:\Target_%date%" + +Latter will be interactively replaced with the current date. In order to further automate this process, you can create a *.ffs_batch file with this configuration and choose +"ignore errors" to avoid the warning that target directory is not (yet) existing. + + --------- | Links | diff --git a/BUILD/Resources.dat b/BUILD/Resources.dat Binary files differindex 4fc53ba5..55072595 100644 --- a/BUILD/Resources.dat +++ b/BUILD/Resources.dat diff --git a/FreeFileSync.cbp b/FreeFileSync.cbp index 3ca4ef97..575f9e04 100644 --- a/FreeFileSync.cbp +++ b/FreeFileSync.cbp @@ -101,6 +101,7 @@ <Add directory="C:\Programme\C++\wxWidgets\include" /> <Add directory="C:\Programme\C++\wxWidgets\contrib\include" /> <Add directory="shared\boost_1_40_0" /> + <Add directory="shared" /> </Compiler> <ResourceCompiler> <Add directory="C:\Programme\C++\wxWidgets\include" /> @@ -228,6 +229,14 @@ <Option target="Debug" /> <Option target="Release" /> </Unit> + <Unit filename="shared\appMain.cpp"> + <Option target="Debug" /> + <Option target="Release" /> + </Unit> + <Unit filename="shared\appMain.h"> + <Option target="Debug" /> + <Option target="Release" /> + </Unit> <Unit filename="shared\customButton.cpp"> <Option target="Debug" /> <Option target="Release" /> @@ -266,6 +275,7 @@ <Unit filename="shared\standardPaths.cpp" /> <Unit filename="shared\standardPaths.h" /> <Unit filename="shared\staticAssert.h" /> + <Unit filename="shared\stringConv.h" /> <Unit filename="shared\systemConstants.h" /> <Unit filename="shared\systemFunctions.cpp" /> <Unit filename="shared\systemFunctions.h" /> @@ -293,12 +303,13 @@ <Unit filename="synchronization.h"> <Option target="<{~None~}>" /> </Unit> - <Unit filename="ui\batchStatusHandler.cpp"> + <Unit filename="ui\appMain.h"> <Option target="Debug" /> <Option target="Release" /> </Unit> - <Unit filename="ui\batchStatusHandler.h"> - <Option target="<{~None~}>" /> + <Unit filename="ui\batchStatusHandler.cpp"> + <Option target="Debug" /> + <Option target="Release" /> </Unit> <Unit filename="ui\checkVersion.cpp"> <Option target="Debug" /> @@ -339,23 +350,25 @@ <Unit filename="ui\mainDialog.h"> <Option target="<{~None~}>" /> </Unit> - <Unit filename="ui\smallDialogs.cpp"> + <Unit filename="ui\settingsDialog.cpp"> <Option target="Debug" /> <Option target="Release" /> </Unit> - <Unit filename="ui\smallDialogs.h"> - <Option target="<{~None~}>" /> - </Unit> - <Unit filename="ui\sorting.h"> + <Unit filename="ui\settingsDialog.h"> <Option target="<{~None~}>" /> </Unit> - <Unit filename="ui\syncDialog.cpp"> + <Unit filename="ui\smallDialogs.cpp"> <Option target="Debug" /> <Option target="Release" /> </Unit> - <Unit filename="ui\syncDialog.h"> + <Unit filename="ui\smallDialogs.h"> + <Option target="<{~None~}>" /> + </Unit> + <Unit filename="ui\sorting.h"> <Option target="<{~None~}>" /> </Unit> + <Unit filename="ui\util.cpp" /> + <Unit filename="ui\util.h" /> <Extensions> <code_completion /> <envvars /> diff --git a/FreeFileSync.vcproj b/FreeFileSync.vcproj index 2027afb9..124ba944 100644 --- a/FreeFileSync.vcproj +++ b/FreeFileSync.vcproj @@ -200,6 +200,10 @@ > </File> <File + RelativePath=".\shared\appMain.cpp" + > + </File> + <File RelativePath=".\ui\batchStatusHandler.cpp" > </File> @@ -284,6 +288,10 @@ > </File> <File + RelativePath=".\ui\settingsDialog.cpp" + > + </File> + <File RelativePath=".\shared\shadow.cpp" > </File> @@ -308,10 +316,6 @@ > </File> <File - RelativePath=".\ui\syncDialog.cpp" - > - </File> - <File RelativePath=".\synchronization.cpp" > </File> @@ -340,6 +344,10 @@ > </File> <File + RelativePath=".\ui\util.cpp" + > + </File> + <File RelativePath=".\shared\xmlBase.cpp" > </File> @@ -1,5 +1,5 @@ -CPPFLAGS=-Wall -pipe -DNDEBUG `wx-config --cppflags` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c -Ishared/boost_1_40_0 -LINKFLAGS=`wx-config --libs` -O3 -pthread +CPPFLAGS=-Wall -pipe -DNDEBUG -DwxUSE_UNICODE `wx-config --cxxflags --debug=no --unicode=yes` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c -Ishared/boost_1_40_0 +LINKFLAGS=`wx-config --libs --debug=no --unicode=yes` -O3 -pthread FILE_LIST= #internal list of all *.cpp files needed for compilation FILE_LIST+=structures.cpp @@ -9,9 +9,10 @@ FILE_LIST+=synchronization.cpp FILE_LIST+=fileHierarchy.cpp FILE_LIST+=application.cpp FILE_LIST+=ui/guiGenerated.cpp +FILE_LIST+=ui/util.cpp FILE_LIST+=ui/gridView.cpp FILE_LIST+=ui/mainDialog.cpp -FILE_LIST+=ui/syncDialog.cpp +FILE_LIST+=ui/settingsDialog.cpp FILE_LIST+=ui/checkVersion.cpp FILE_LIST+=ui/batchStatusHandler.cpp FILE_LIST+=ui/guiStatusHandler.cpp @@ -37,6 +38,7 @@ FILE_LIST+=shared/fileTraverser.cpp FILE_LIST+=shared/standardPaths.cpp FILE_LIST+=shared/zstring.cpp FILE_LIST+=shared/xmlBase.cpp +FILE_LIST+=shared/appMain.cpp FILE_LIST+=shared/customButton.cpp FILE_LIST+=shared/toggleButton.cpp diff --git a/RealtimeSync/functions.cpp b/RealtimeSync/functions.cpp index f966187e..e5e3f5f5 100644 --- a/RealtimeSync/functions.cpp +++ b/RealtimeSync/functions.cpp @@ -2,14 +2,16 @@ #include <wx/textctrl.h> #include <wx/filepicker.h> //#include "../shared/globalFunctions.h" +#include "../shared/stringConv.h" #include "../shared/fileHandling.h" +using namespace FreeFileSync; void RealtimeSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) { txtCtrl->SetValue(dirname); - const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(dirname.c_str()); - if (wxDirExists(leftDirFormatted.c_str())) - dirPicker->SetPath(leftDirFormatted.c_str()); + const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(wxToZ(dirname)); + if (dirExists(leftDirFormatted)) + dirPicker->SetPath(zToWx(leftDirFormatted)); } diff --git a/RealtimeSync/mainDialog.cpp b/RealtimeSync/mainDialog.cpp index cb1cbf86..d849eee5 100644 --- a/RealtimeSync/mainDialog.cpp +++ b/RealtimeSync/mainDialog.cpp @@ -12,6 +12,9 @@ #include "../shared/fileHandling.h" #include "xmlFreeFileSync.h" #include "../shared/systemConstants.h" +#include "../shared/stringConv.h" + +using namespace FreeFileSync; MainDialog::MainDialog(wxDialog *dlg, const wxString& cfgFilename) @@ -75,8 +78,8 @@ MainDialog::MainDialog(wxDialog *dlg, const wxString& cfgFilename) if (startWatchingImmediately) //start watch mode directly { - wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED); - this->OnStart(dummy); + wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED); + this->OnStart(dummy2); } } @@ -111,9 +114,9 @@ void MainDialog::OnQuit(wxCommandEvent &event) const wxString& MainDialog::lastConfigFileName() { - static wxString instance = FreeFileSync::getConfigDir().EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR)) ? + static wxString instance = FreeFileSync::getConfigDir().EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR)) ? FreeFileSync::getConfigDir() + wxT("LastRun.ffs_real") : - FreeFileSync::getConfigDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("LastRun.ffs_real"); + FreeFileSync::getConfigDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("LastRun.ffs_real"); return instance; } @@ -249,9 +252,9 @@ void MainDialog::setConfiguration(const xmlAccess::XmlRealConfig& cfg) //fill top folder m_txtCtrlDirectoryMain->SetValue(*cfg.directories.begin()); - const wxString dirFormatted = FreeFileSync::getFormattedDirectoryName(cfg.directories.begin()->c_str()).c_str(); - if (wxDirExists(dirFormatted)) - m_dirPickerMain->SetPath(dirFormatted); + const Zstring dirFormatted = FreeFileSync::getFormattedDirectoryName(wxToZ(*cfg.directories.begin())); + if (dirExists(dirFormatted)) + m_dirPickerMain->SetPath(zToWx(dirFormatted)); //fill additional folders addFolder(std::vector<wxString>(cfg.directories.begin() + 1, cfg.directories.end())); diff --git a/RealtimeSync/makefile b/RealtimeSync/makefile index 81f41b16..054bd3c1 100644 --- a/RealtimeSync/makefile +++ b/RealtimeSync/makefile @@ -1,5 +1,5 @@ -CPPFLAGS=-Wall -pipe -DNDEBUG `wx-config --cppflags` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c -I../shared/boost_1_40_0 -LINKFLAGS=`wx-config --libs` -O3 -pthread +CPPFLAGS=-Wall -pipe -DNDEBUG -DwxUSE_UNICODE `wx-config --cxxflags --debug=no --unicode=yes` `pkg-config --cflags gtk+-2.0` -DFFS_LINUX -DTIXML_USE_STL -DZSTRING_CHAR -O3 -pthread -c -I../shared/boost_1_40_0 +LINKFLAGS=`wx-config --libs --debug=no --unicode=yes` -O3 -pthread FILE_LIST= #internal list of all *.cpp files needed for compilation FILE_LIST+=application.cpp diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp index 979b5ecb..37a0bb43 100644 --- a/RealtimeSync/resources.cpp +++ b/RealtimeSync/resources.cpp @@ -4,10 +4,12 @@ #include <wx/image.h> #include <wx/icon.h> #include <memory> -//#include "../shared/globalFunctions.h" +#include "../shared/stringConv.h" #include "../shared/standardPaths.h" #include "../shared/systemConstants.h" +using namespace FreeFileSync; + const GlobalResources& GlobalResources::getInstance() { @@ -40,7 +42,7 @@ GlobalResources::~GlobalResources() void GlobalResources::load() const { - wxFFileInputStream input(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("Resources.dat")); + wxFFileInputStream input(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("Resources.dat")); if (input.IsOk()) //if not... we don't want to react too harsh here { //activate support for .png files diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp index 4949f01a..7aaa189d 100644 --- a/RealtimeSync/watcher.cpp +++ b/RealtimeSync/watcher.cpp @@ -4,6 +4,7 @@ #include <wx/intl.h> #include <wx/filefn.h> #include "../shared/fileHandling.h" +#include "../shared/stringConv.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -15,6 +16,8 @@ #include "../shared/fileTraverser.h" #endif +using namespace FreeFileSync; + #ifdef FFS_WIN class ChangeNotifications @@ -130,14 +133,14 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal //add all subdirectories for (std::vector<wxString>::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i) { - const Zstring formattedDir = FreeFileSync::getFormattedDirectoryName(i->c_str()); + const Zstring formattedDir = FreeFileSync::getFormattedDirectoryName(wxToZ(*i)); if (formattedDir.empty()) throw FreeFileSync::FileError(_("Please fill all empty directory fields.")); else if (!FreeFileSync::dirExists(formattedDir)) throw FreeFileSync::FileError(wxString(_("Directory does not exist:")) + wxT("\n") + - wxT("\"") + formattedDir + wxT("\"") + wxT("\n\n") + + wxT("\"") + zToWx(formattedDir) + wxT("\"") + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); fullDirList.push_back(formattedDir.c_str()); @@ -170,8 +173,8 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal } catch (const InotifyException& e) { - const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + *i + wxT("\""); - throw FreeFileSync::FileError(errorMessage + wxT("\n\n") + e.GetMessage().c_str()); + const wxString errorMessage = wxString(_("Could not initialize directory monitoring:")) + wxT("\n\"") + zToWx(i->c_str()) + wxT("\""); + throw FreeFileSync::FileError(errorMessage + wxT("\n\n") + zToWx(e.GetMessage().c_str())); } } @@ -188,11 +191,11 @@ void RealtimeSync::waitForChanges(const std::vector<wxString>& dirNames, WaitCal } catch (const InotifyException& e) { - throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + e.GetMessage().c_str()); + throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + zToWx(e.GetMessage().c_str())); } catch (const std::exception& e) { - throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + e.what()); + throw FreeFileSync::FileError(wxString(_("Error when monitoring directories.")) + wxT("\n\n") + zToWx(e.what())); } #endif } diff --git a/RealtimeSync/xmlFreeFileSync.cpp b/RealtimeSync/xmlFreeFileSync.cpp index b3c11d50..dc352135 100644 --- a/RealtimeSync/xmlFreeFileSync.cpp +++ b/RealtimeSync/xmlFreeFileSync.cpp @@ -4,10 +4,13 @@ #include "../shared/zstring.h" #include "functions.h" #include "../shared/xmlBase.h" +#include "../shared/stringConv.h" //include FreeFileSync xml headers #include "../library/processXml.h" +using namespace FreeFileSync; + #ifdef FFS_WIN struct CmpNoCase @@ -31,20 +34,20 @@ xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& bat #endif //add main folders - uniqueFolders.insert(batchCfg.mainCfg.mainFolderPair.leftDirectory.c_str()); - uniqueFolders.insert(batchCfg.mainCfg.mainFolderPair.rightDirectory.c_str()); + uniqueFolders.insert(zToWx(batchCfg.mainCfg.mainFolderPair.leftDirectory)); + uniqueFolders.insert(zToWx(batchCfg.mainCfg.mainFolderPair.rightDirectory)); //additional folders for (std::vector<FreeFileSync::FolderPairEnh>::const_iterator i = batchCfg.mainCfg.additionalPairs.begin(); i != batchCfg.mainCfg.additionalPairs.end(); ++i) { - uniqueFolders.insert(i->leftDirectory.c_str()); - uniqueFolders.insert(i->rightDirectory.c_str()); + uniqueFolders.insert(zToWx(i->leftDirectory)); + uniqueFolders.insert(zToWx(i->rightDirectory)); } output.directories.insert(output.directories.end(), uniqueFolders.begin(), uniqueFolders.end()); - output.commandline = FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("FreeFileSync.exe ") + + output.commandline = FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("FreeFileSync.exe ") + wxT("\"") + filename + wxT("\""); return output; diff --git a/algorithm.cpp b/algorithm.cpp index 94c4abfe..1b3ce0b1 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -3,224 +3,560 @@ #include <stdexcept> #include <wx/log.h> #include "library/resources.h" -#include "shared/systemFunctions.h" #include "shared/fileHandling.h" #include <wx/msgdlg.h> -#include <wx/textctrl.h> -#include <wx/combobox.h> -#include <wx/filepicker.h> -#include "shared/localization.h" #include "library/filter.h" #include <boost/bind.hpp> +#include "shared/stringConv.h" #include "shared/globalFunctions.h" -#include <wx/scrolwin.h> - -#ifdef FFS_WIN -#include <wx/msw/wrapwin.h> //includes "windows.h" -#endif - +#include "shared/loki/TypeManip.h" +#include "shared/loki/NullType.h" using namespace FreeFileSync; -wxString FreeFileSync::formatFilesizeToShortString(const wxLongLong& filesize) +void FreeFileSync::swapGrids(const MainConfiguration& config, FolderComparison& folderCmp) { - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); + std::for_each(folderCmp.begin(), folderCmp.end(), boost::bind(&BaseDirMapping::swap, _1)); + redetermineSyncDirection(config, folderCmp, NULL); } -wxString FreeFileSync::formatFilesizeToShortString(const wxULongLong& filesize) +//---------------------------------------------------------------------------------------------- +class Redetermine { - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); -}; - +public: + Redetermine(const SyncConfiguration& configIn) : config(configIn) {} -wxString FreeFileSync::formatFilesizeToShortString(const double filesize) -{ - if (filesize < 0) - return _("Error"); + void execute(HierarchyObject& hierObj) const + { + //process files + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); + //process directories + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); + } - if (filesize <= 999) - return wxString::Format(wxT("%i"), static_cast<int>(filesize)) + _(" Byte"); //no decimal places in case of bytes +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); - double nrOfBytes = filesize; + void operator()(FileMapping& fileObj) const + { + switch (fileObj.getCategory()) + { + case FILE_LEFT_SIDE_ONLY: + fileObj.setSyncDir(config.exLeftSideOnly); + break; + case FILE_RIGHT_SIDE_ONLY: + fileObj.setSyncDir(config.exRightSideOnly); + break; + case FILE_RIGHT_NEWER: + fileObj.setSyncDir(config.rightNewer); + break; + case FILE_LEFT_NEWER: + fileObj.setSyncDir(config.leftNewer); + break; + case FILE_DIFFERENT: + fileObj.setSyncDir(config.different); + break; + case FILE_CONFLICT: + fileObj.setSyncDir(config.conflict); + break; + case FILE_EQUAL: + fileObj.setSyncDir(SYNC_DIR_NONE); + break; + } + } - nrOfBytes /= 1024; - wxString unit = _(" kB"); - if (nrOfBytes > 999) + void operator()(DirMapping& dirObj) const { - nrOfBytes /= 1024; - unit = _(" MB"); - if (nrOfBytes > 999) + switch (dirObj.getDirCategory()) { - nrOfBytes /= 1024; - unit = _(" GB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" TB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" PB"); - } - } + case DIR_LEFT_SIDE_ONLY: + dirObj.setSyncDir(config.exLeftSideOnly); + break; + case DIR_RIGHT_SIDE_ONLY: + dirObj.setSyncDir(config.exRightSideOnly); + break; + case DIR_EQUAL: + dirObj.setSyncDir(SYNC_DIR_NONE); + break; } + + //recursion + execute(dirObj); } - //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111 + const SyncConfiguration& config; +}; + + +//--------------------------------------------------------------------------------------------------------------- +enum Answer +{ + CHANGE_DETECTED, + NO_CHANGE, + CANT_SAY_FILTERING_CHANGED +}; + + +template <bool respectFiltering> +class DetectChanges +{ +public: + DetectChanges(const DirContainer* dirCont, //DirContainer in sense of a HierarchyObject + const FilterProcess& dbFilter); + + DetectChanges(const DirContainer* dirCont); //DirContainer in sense of a HierarchyObject - const unsigned int leadDigitCount = globalFunctions::getDigitCount(static_cast<unsigned int>(nrOfBytes)); //number of digits before decimal point - if (leadDigitCount == 0 || leadDigitCount > 3) - return _("Error"); + template <SelectedSide side> + Answer detectFileChange(const FileMapping& fileObj) const; - if (leadDigitCount == 3) - return wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes)) + unit; - else if (leadDigitCount == 2) + struct DirAnswer { - wxString output = wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes * 10)); - output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); - return output + unit; + DirAnswer(Answer status, const DetectChanges instance) : dirStatus(status), subDirInstance(instance) {} + Answer dirStatus; + DetectChanges subDirInstance; //not valid if dirStatus == CANT_SAY_FILTERING_CHANGED + }; + template <SelectedSide side> + DirAnswer detectDirChange(const DirMapping& dirObj) const; + +private: + const DirContainer* const dirCont_; //if NULL: did not exist during db creation + typename Loki::Select<respectFiltering, const FilterProcess&, Loki::NullType>::Result dbFilter_; //filter setting that was used when db was created +}; + + +template <> +inline +DetectChanges<true>::DetectChanges(const DirContainer* dirCont, //DirContainer in sense of a HierarchyObject + const FilterProcess& dbFilter) : + dirCont_(dirCont), + dbFilter_(dbFilter) {} + + +template <> +inline +DetectChanges<false>::DetectChanges(const DirContainer* dirCont) : //DirContainer in sense of a HierarchyObject + dirCont_(dirCont) {} + + + +template <SelectedSide side> +Answer detectFileChangeSub(const FileMapping& fileObj, const DirContainer* dbDirectory) +{ + if (dbDirectory) + { + DirContainer::SubFileList::const_iterator j = dbDirectory->getSubFiles().find(fileObj.getObjShortName()); + if (j == dbDirectory->getSubFiles().end()) + { + if (fileObj.isEmpty<side>()) + return NO_CHANGE; + else + return CHANGE_DETECTED; //->create + } + else + { + if (fileObj.isEmpty<side>()) + return CHANGE_DETECTED; //->delete + else + { + const FileDescriptor& dbData = j->second.getData(); + if ( fileObj.getLastWriteTime<side>() == dbData.lastWriteTimeRaw && + fileObj.getFileSize<side>() == dbData.fileSize) + return NO_CHANGE; + else + return CHANGE_DETECTED; //->update + } + } } - else //leadDigitCount == 1 + else { - wxString output = wxString::Format(wxT("%03i"), static_cast<int>(nrOfBytes * 100)); - output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); - return output + unit; + if (fileObj.isEmpty<side>()) + return NO_CHANGE; + else + return CHANGE_DETECTED; //->create } +} + - //return wxString::Format(wxT("%.*f"), 3 - leadDigitCount, nrOfBytes) + unit; +template <> +template <SelectedSide side> +inline +Answer DetectChanges<false>::detectFileChange(const FileMapping& fileObj) const +{ + return detectFileChangeSub<side>(fileObj, dirCont_); } -wxString FreeFileSync::includeNumberSeparator(const wxString& number) +template <> +template <SelectedSide side> +inline +Answer DetectChanges<true>::detectFileChange(const FileMapping& fileObj) const { - wxString output(number); - for (int i = output.size() - 3; i > 0; i -= 3) - output.insert(i, FreeFileSync::THOUSANDS_SEPARATOR); + //if filtering would have excluded file during database creation, then we can't say anything about its former state + if (!dbFilter_.passFileFilter(fileObj.getObjShortName())) + return CANT_SAY_FILTERING_CHANGED; - return output; + return detectFileChangeSub<side>(fileObj, dirCont_); } -template <class T> -void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker) +template <SelectedSide side> +Answer detectDirChangeSub(const DirMapping& dirObj, const DirContainer* dbDirectory, const DirContainer*& dbSubDirectory) { - txtCtrl->SetValue(dirname); - const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(dirname.c_str()); - if (wxDirExists(leftDirFormatted.c_str())) - dirPicker->SetPath(leftDirFormatted.c_str()); + if (dbDirectory) + { + DirContainer::SubDirList::const_iterator j = dbDirectory->getSubDirs().find(dirObj.getObjShortName()); + if (j == dbDirectory->getSubDirs().end()) + { + if (dirObj.isEmpty<side>()) + return NO_CHANGE; + else + return CHANGE_DETECTED; //->create + } + else + { + dbSubDirectory = &j->second; + if (dirObj.isEmpty<side>()) + return CHANGE_DETECTED; //->delete + else + return NO_CHANGE; + } + } + else + { + if (dirObj.isEmpty<side>()) + return NO_CHANGE; + else + return CHANGE_DETECTED; //->create + } } -void FreeFileSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) +template <> +template <SelectedSide side> +DetectChanges<false>::DirAnswer DetectChanges<false>::detectDirChange(const DirMapping& dirObj) const { - setDirectoryNameImpl(dirname, txtCtrl, dirPicker); + const DirContainer* dbSubDir = NULL; + const Answer answer = detectDirChangeSub<side>(dirObj, dirCont_, dbSubDir); + + return DirAnswer(answer, DetectChanges<false>(dbSubDir)); } -void FreeFileSync::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) +template <> +template <SelectedSide side> +DetectChanges<true>::DirAnswer DetectChanges<true>::detectDirChange(const DirMapping& dirObj) const { - txtCtrl->SetSelection(wxNOT_FOUND); - setDirectoryNameImpl(dirname, txtCtrl, dirPicker); + //if filtering would have excluded file during database creation, then we can't say anything about its former state + if (!dbFilter_.passDirFilter(dirObj.getObjShortName(), NULL)) + return DirAnswer(CANT_SAY_FILTERING_CHANGED, DetectChanges<true>(NULL, dbFilter_)); + + const DirContainer* dbSubDir = NULL; + const Answer answer = detectDirChangeSub<side>(dirObj, dirCont_, dbSubDir); + + return DirAnswer(answer, DetectChanges<true>(dbSubDir, dbFilter_)); } -void FreeFileSync::scrollToBottom(wxScrolledWindow* scrWindow) +//---------------------------------------------------------------------------------------------- +class SetDirChangedFilter { - int height = 0; - scrWindow->GetClientSize(NULL, &height); +public: + SetDirChangedFilter() : + txtFilterChanged(_("Cannot determine sync-direction: Changed filter settings!")) {} + + void execute(HierarchyObject& hierObj) const + { + //files + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); + //directories + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); + } - int pixelPerLine = 0; - scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine); +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); - if (height > 0 && pixelPerLine > 0) + void operator()(FileMapping& fileObj) const { - const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL); - const int scrollLinesOnScreen = height / pixelPerLine; - const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen; + const CompareFilesResult cat = fileObj.getCategory(); + if (cat == FILE_LEFT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_RIGHT); + else if (cat == FILE_RIGHT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_LEFT); + else + fileObj.setSyncDirConflict(txtFilterChanged); //set syncDir = SYNC_DIR_INT_CONFLICT + } - if (0 <= scrollPosBottom) - scrWindow->Scroll(0, scrollPosBottom); + void operator()(DirMapping& dirObj) const + { + switch (dirObj.getDirCategory()) + { + case DIR_LEFT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_RIGHT); + break; + case DIR_RIGHT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_LEFT); + break; + case DIR_EQUAL: + break; + } + + execute(dirObj); //recursion } -} + + const wxString txtFilterChanged; +}; -void swapGridsFP(HierarchyObject& hierObj) +//---------------------------------------------------------------------------------------------- +class RedetermineAuto { - //swap directories - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), std::mem_fun_ref(&FileSystemObject::swap)); - //swap files - std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), std::mem_fun_ref(&FileSystemObject::swap)); - //recurse into sub-dirs - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), swapGridsFP); -} +public: + RedetermineAuto(BaseDirMapping& baseDirectory, + DeterminationProblem* handler) : + txtBothSidesChanged(_("Both sides have changed since last synchronization!")), + txtNoSideChanged(_("Cannot determine sync-direction: No change since last synchronization!")), + txtFilterChanged(_("Cannot determine sync-direction: Changed filter settings!")), + handler_(handler) + { + //try to load sync-database files + boost::shared_ptr<const DirInformation> dirInfoLeft = loadDBFile<LEFT_SIDE>(baseDirectory); + boost::shared_ptr<const DirInformation> dirInfoRight = dirInfoLeft.get() == NULL ? //don't load second DB if loading of first failed, to avoid duplicate error messages + boost::shared_ptr<const DirInformation>() : loadDBFile<RIGHT_SIDE>(baseDirectory); + if ( dirInfoLeft.get() == NULL || + dirInfoRight.get() == NULL) + { + //use standard settings: + SyncConfiguration defaultSync; + defaultSync.setVariant(SyncConfiguration::TWOWAY); + Redetermine(defaultSync).execute(baseDirectory); + return; + } + + if ( respectFiltering(baseDirectory, *dirInfoLeft) && + respectFiltering(baseDirectory, *dirInfoRight)) + { + execute(baseDirectory, + DetectChanges<true>(&dirInfoLeft->baseDirContainer, + FilterProcess(dirInfoLeft->includeFilter, + dirInfoLeft->excludeFilter)), + DetectChanges<true>(&dirInfoRight->baseDirContainer, + FilterProcess(dirInfoRight->includeFilter, + dirInfoRight->excludeFilter))); + } + else if ( !respectFiltering(baseDirectory, *dirInfoLeft) && + respectFiltering(baseDirectory, *dirInfoRight)) + { + execute(baseDirectory, + DetectChanges<false>(&dirInfoLeft->baseDirContainer), + DetectChanges<true>(&dirInfoRight->baseDirContainer, + FilterProcess(dirInfoRight->includeFilter, + dirInfoRight->excludeFilter))); + } + else if ( respectFiltering(baseDirectory, *dirInfoLeft) && + !respectFiltering(baseDirectory, *dirInfoRight)) + { + execute(baseDirectory, + DetectChanges<true>(&dirInfoLeft->baseDirContainer, + FilterProcess(dirInfoLeft->includeFilter, + dirInfoLeft->excludeFilter)), + DetectChanges<false>(&dirInfoRight->baseDirContainer)); + } + else + { + execute(baseDirectory, + DetectChanges<false>(&dirInfoLeft->baseDirContainer), + DetectChanges<false>(&dirInfoRight->baseDirContainer)); + } + } -void FreeFileSync::swapGrids2(const MainConfiguration& config, FolderComparison& folderCmp) -{ - std::for_each(folderCmp.begin(), folderCmp.end(), swapGridsFP); - redetermineSyncDirection(config, folderCmp); -} +private: + static bool respectFiltering(const BaseDirMapping& baseDirectory, const DirInformation& dirInfo) + { + return dirInfo.filterActive && //respect filtering if sync-DB filter is active && different from baseDir's filter + (!baseDirectory.getFilter().filterActive || -class Redetermine -{ -public: - Redetermine(const SyncConfiguration& configIn) : config(configIn) {} + FilterProcess(baseDirectory.getFilter().includeFilter, + baseDirectory.getFilter().excludeFilter) != + + FilterProcess(dirInfo.includeFilter, + dirInfo.excludeFilter)); + } - void operator()(FileSystemObject& fsObj) const + template <SelectedSide side> + boost::shared_ptr<const DirInformation> loadDBFile(const BaseDirMapping& baseDirectory) //return NULL on failure { - switch (fsObj.getCategory()) + if (!FreeFileSync::fileExists(baseDirectory.getDBFilename<side>())) { - case FILE_LEFT_SIDE_ONLY: - fsObj.syncDir = convertToSyncDirection(config.exLeftSideOnly); - break; + if (handler_) handler_->reportWarning( + wxString(_("Initial synchronization. Please verify default copy-directions!")) + wxT(" \n") + + wxT("(") + _("No database file existing yet:") + wxT(" \"") + zToWx(baseDirectory.getBaseDir<side>()) + wxT("\")")); + return boost::shared_ptr<const DirInformation>(); //NULL + } - case FILE_RIGHT_SIDE_ONLY: - fsObj.syncDir = convertToSyncDirection(config.exRightSideOnly); - break; + try + { + return loadFromDisk(baseDirectory.getDBFilename<side>()); + } + catch (FileError& error) //e.g. incompatible database version + { + if (handler_) handler_->reportWarning(error.show() + wxT(" \n\n") + + _("Using default synchronization directions. Please recheck.")); + } + return boost::shared_ptr<const DirInformation>(); //NULL + } - case FILE_RIGHT_NEWER: - fsObj.syncDir = convertToSyncDirection(config.rightNewer); - break; + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); - case FILE_LEFT_NEWER: - fsObj.syncDir = convertToSyncDirection(config.leftNewer); - break; + template <bool dbLeftFilterActive, bool dbRightFilterActive> + void execute(HierarchyObject& hierObj, + const DetectChanges<dbLeftFilterActive>& dbLeft, + const DetectChanges<dbRightFilterActive>& dbRight) + { + //process files + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), + boost::bind(&RedetermineAuto::processFile<dbLeftFilterActive, dbRightFilterActive>, this, _1, boost::ref(dbLeft), boost::ref(dbRight))); + //process directories + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), + boost::bind(&RedetermineAuto::processDir<dbLeftFilterActive, dbRightFilterActive>, this, _1, boost::ref(dbLeft), boost::ref(dbRight))); + } - case FILE_DIFFERENT: - fsObj.syncDir = convertToSyncDirection(config.different); - break; + template <bool dbLeftFilterActive, bool dbRightFilterActive> + void processFile(FileMapping& fileObj, + const DetectChanges<dbLeftFilterActive>& dbLeft, + const DetectChanges<dbRightFilterActive>& dbRight) + { + const CompareFilesResult cat = fileObj.getCategory(); + if (cat == FILE_EQUAL) + return; - case FILE_CONFLICT: - fsObj.syncDir = convertToSyncDirection(config.conflict); - break; + const Answer statusLeft = dbLeft. template detectFileChange<LEFT_SIDE>(fileObj); + const Answer statusRight = dbRight.template detectFileChange<RIGHT_SIDE>(fileObj); - case FILE_EQUAL: - fsObj.syncDir = SYNC_DIR_NONE; + if ( statusLeft == CANT_SAY_FILTERING_CHANGED || + statusRight == CANT_SAY_FILTERING_CHANGED) + { + if (cat == FILE_LEFT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_RIGHT); + else if (cat == FILE_RIGHT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_LEFT); + else + fileObj.setSyncDirConflict(txtFilterChanged); //set syncDir = SYNC_DIR_INT_CONFLICT + return; + } + + + if ( statusLeft == CHANGE_DETECTED && + statusRight == NO_CHANGE) + fileObj.setSyncDir(SYNC_DIR_RIGHT); + + else if ( statusLeft == NO_CHANGE && + statusRight == CHANGE_DETECTED) + fileObj.setSyncDir(SYNC_DIR_LEFT); + + else if ( statusLeft == CHANGE_DETECTED && + statusRight == CHANGE_DETECTED) + fileObj.setSyncDirConflict(txtBothSidesChanged); //set syncDir = SYNC_DIR_INT_CONFLICT + + else if ( statusLeft == NO_CHANGE && + statusRight == NO_CHANGE) + { + if (cat == FILE_LEFT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_RIGHT); + else if (cat == FILE_RIGHT_SIDE_ONLY) + fileObj.setSyncDir(SYNC_DIR_LEFT); + else + fileObj.setSyncDirConflict(txtNoSideChanged); //set syncDir = SYNC_DIR_INT_CONFLICT } } -private: - const SyncConfiguration& config; + + + template <bool dbLeftFilterActive, bool dbRightFilterActive> + void processDir(DirMapping& dirObj, + const DetectChanges<dbLeftFilterActive>& dbLeft, + const DetectChanges<dbRightFilterActive>& dbRight) + { + const typename DetectChanges<dbLeftFilterActive> ::DirAnswer statusLeft = dbLeft. template detectDirChange<LEFT_SIDE>(dirObj); + const typename DetectChanges<dbRightFilterActive>::DirAnswer statusRight = dbRight.template detectDirChange<RIGHT_SIDE>(dirObj); + + const CompareDirResult cat = dirObj.getDirCategory(); + if (cat != DIR_EQUAL) + { + if ( (statusLeft.dirStatus == CANT_SAY_FILTERING_CHANGED || + statusRight.dirStatus == CANT_SAY_FILTERING_CHANGED)) + { + switch (cat) + { + case DIR_LEFT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_RIGHT); + break; + case DIR_RIGHT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_LEFT); + break; + case DIR_EQUAL: + assert(false); + } + + SetDirChangedFilter().execute(dirObj); //filter issue for this directory => treat subfiles/-dirs the same + return; + } + else if ( statusLeft.dirStatus == CHANGE_DETECTED && + statusRight.dirStatus == NO_CHANGE) + dirObj.setSyncDir(SYNC_DIR_RIGHT); + + else if ( statusLeft.dirStatus == NO_CHANGE && + statusRight.dirStatus == CHANGE_DETECTED) + dirObj.setSyncDir(SYNC_DIR_LEFT); + + else if ( statusLeft.dirStatus == CHANGE_DETECTED && + statusRight.dirStatus == CHANGE_DETECTED) + dirObj.setSyncDirConflict(txtBothSidesChanged); //set syncDir = SYNC_DIR_INT_CONFLICT + + else if ( statusLeft.dirStatus == NO_CHANGE && + statusRight.dirStatus == NO_CHANGE) + { + switch (cat) + { + case DIR_LEFT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_RIGHT); + break; + case DIR_RIGHT_SIDE_ONLY: + dirObj.setSyncDir(SYNC_DIR_LEFT); + break; + case DIR_EQUAL: + assert(false); + } + } + } + + execute(dirObj, statusLeft.subDirInstance, statusRight.subDirInstance); //recursion + } + + const wxString txtBothSidesChanged; + const wxString txtNoSideChanged; + const wxString txtFilterChanged; + + DeterminationProblem* const handler_; }; -void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, HierarchyObject& baseDirectory) +//--------------------------------------------------------------------------------------------------------------- +void FreeFileSync::redetermineSyncDirection(const SyncConfiguration& config, BaseDirMapping& baseDirectory, DeterminationProblem* handler) { - //do not handle i->selectedForSynchronization in this method! handled in synchronizeFile(), synchronizeFolder()! - - //swap directories - std::for_each(baseDirectory.subDirs.begin(), baseDirectory.subDirs.end(), Redetermine(config)); - //swap files - std::for_each(baseDirectory.subFiles.begin(), baseDirectory.subFiles.end(), Redetermine(config)); - //recurse into sub-dirs - std::for_each(baseDirectory.subDirs.begin(), baseDirectory.subDirs.end(), - boost::bind(static_cast<void (*)(const SyncConfiguration&, HierarchyObject&)>(redetermineSyncDirection), boost::cref(config), _1)); + if (config.automatic) + RedetermineAuto(baseDirectory, handler); + else + Redetermine(config).execute(baseDirectory); } -void FreeFileSync::redetermineSyncDirection(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp) +void FreeFileSync::redetermineSyncDirection(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp, DeterminationProblem* handler) { if (folderCmp.size() == 0) return; @@ -228,59 +564,67 @@ void FreeFileSync::redetermineSyncDirection(const MainConfiguration& currentMain throw std::logic_error("Programming Error: Contract violation!"); //main pair - redetermineSyncDirection(currentMainCfg.syncConfiguration, folderCmp[0]); + redetermineSyncDirection(currentMainCfg.syncConfiguration, folderCmp[0], handler); //add. folder pairs for (std::vector<FolderPairEnh>::const_iterator i = currentMainCfg.additionalPairs.begin(); i != currentMainCfg.additionalPairs.end(); ++i) { redetermineSyncDirection(i->altSyncConfig.get() ? i->altSyncConfig->syncConfiguration : currentMainCfg.syncConfiguration, - folderCmp[i - currentMainCfg.additionalPairs.begin() + 1]); + folderCmp[i - currentMainCfg.additionalPairs.begin() + 1], handler); } } +//--------------------------------------------------------------------------------------------------------------- class SetNewDirection { public: SetNewDirection(SyncDirection newDirection) : - newDirection_(newDirection) {} + newDirection_(newDirection) {} - void operator()(FileSystemObject& fsObj) const - { - fsObj.syncDir = newDirection_; - } - - void setSyncDirectionSub(FreeFileSync::HierarchyObject& hierObj) + void execute(HierarchyObject& hierObj) const { //directories std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); //files std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); - //recurse into sub-dirs - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), boost::bind(&SetNewDirection::setSyncDirectionSub, this, _1)); } private: - SyncDirection newDirection_; + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); + + void operator()(FileMapping& fileObj) const + { + fileObj.setSyncDir(newDirection_); + } + + void operator()(DirMapping& dirObj) const + { + dirObj.setSyncDir(newDirection_); + execute(dirObj); //recursion + } + + const SyncDirection newDirection_; }; -void FreeFileSync::setSyncDirection(SyncDirection newDirection, FileSystemObject& fsObj) +void FreeFileSync::setSyncDirectionRec(SyncDirection newDirection, FileSystemObject& fsObj) { - fsObj.syncDir = newDirection; + fsObj.setSyncDir(newDirection); DirMapping* dirObj = dynamic_cast<DirMapping*>(&fsObj); if (dirObj) //process subdirectories also! - SetNewDirection(newDirection).setSyncDirectionSub(*dirObj); + SetNewDirection(newDirection).execute(*dirObj); } void FreeFileSync::applyFiltering(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp) { - assert (folderCmp.size() == 0 || folderCmp.size() == currentMainCfg.additionalPairs.size() + 1); - - if (folderCmp.size() != currentMainCfg.additionalPairs.size() + 1) + if (folderCmp.size() == 0) return; + else if (folderCmp.size() != currentMainCfg.additionalPairs.size() + 1) + throw std::logic_error("Programming Error: Contract violation!"); //main pair FreeFileSync::FilterProcess(currentMainCfg.includeFilter, currentMainCfg.excludeFilter).filterAll(folderCmp[0]); @@ -319,13 +663,13 @@ std::pair<wxString, int> FreeFileSync::deleteFromGridAndHDPreview( //assemble me if (!currObj.isEmpty<LEFT_SIDE>()) { - filesToDelete += (currObj.getFullName<LEFT_SIDE>() + wxT("\n")).c_str(); + filesToDelete += zToWx(currObj.getFullName<LEFT_SIDE>()) + wxT("\n"); ++totalDelCount; } if (!currObj.isEmpty<RIGHT_SIDE>()) { - filesToDelete += (currObj.getFullName<RIGHT_SIDE>() + wxT("\n")).c_str(); + filesToDelete += zToWx(currObj.getFullName<RIGHT_SIDE>()) + wxT("\n"); ++totalDelCount; } @@ -340,7 +684,7 @@ std::pair<wxString, int> FreeFileSync::deleteFromGridAndHDPreview( //assemble me if (!currObj.isEmpty<LEFT_SIDE>()) { - filesToDelete += (currObj.getFullName<LEFT_SIDE>() + wxT("\n")).c_str(); + filesToDelete += zToWx(currObj.getFullName<LEFT_SIDE>()) + wxT("\n"); ++totalDelCount; } } @@ -351,7 +695,7 @@ std::pair<wxString, int> FreeFileSync::deleteFromGridAndHDPreview( //assemble me if (!currObj.isEmpty<RIGHT_SIDE>()) { - filesToDelete += (currObj.getFullName<RIGHT_SIDE>() + wxT("\n")).c_str(); + filesToDelete += zToWx(currObj.getFullName<RIGHT_SIDE>()) + wxT("\n"); ++totalDelCount; } } @@ -418,13 +762,13 @@ class FinalizeDeletion { public: FinalizeDeletion(FolderComparison& folderCmp, const MainConfiguration& mainConfig) : - folderCmp_(folderCmp), - mainConfig_(mainConfig) {} + folderCmp_(folderCmp), + mainConfig_(mainConfig) {} ~FinalizeDeletion() { std::for_each(folderCmp_.begin(), folderCmp_.end(), FileSystemObject::removeEmpty); - redetermineSyncDirection(mainConfig_, folderCmp_); + redetermineSyncDirection(mainConfig_, folderCmp_, NULL); } private: @@ -476,102 +820,9 @@ void FreeFileSync::deleteFromGridAndHD(FolderComparison& folderCmp, statusHandler); } } -//############################################################################################################ - - -inline -void writeTwoDigitNumber(unsigned int number, wxString& string) -{ - assert (number < 100); - - string += '0' + number / 10; - string += '0' + number % 10; -} - - -inline -void writeFourDigitNumber(unsigned int number, wxString& string) -{ - assert (number < 10000); - - string += '0' + number / 1000; - number %= 1000; - string += '0' + number / 100; - number %= 100; - string += '0' + number / 10; - number %= 10; - string += '0' + number; -} - - -wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename) -{ -#ifdef FFS_WIN - //convert ansi C time to FILETIME - wxLongLong fileTimeLong(utcTime); - - fileTimeLong += wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s - fileTimeLong *= 10000000; - - FILETIME lastWriteTimeUtc; - lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); //GetLo() returns unsigned - lastWriteTimeUtc.dwHighDateTime = unsigned(fileTimeLong.GetHi()); //GetHi() returns signed - - - FILETIME localFileTime; - if (::FileTimeToLocalFileTime( //convert to local time - &lastWriteTimeUtc, //pointer to UTC file time to convert - &localFileTime //pointer to converted file time - ) == 0) - throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + - wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") + - filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).To8BitData())); - - if (localFileTime.dwHighDateTime > 0x7fffffff) - return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever! - //Testcase (UTC): dateHigh = 2147483647 (=0x7fffffff) -> year 30000 - // dateLow = 4294967295 - - SYSTEMTIME time; - if (::FileTimeToSystemTime( - &localFileTime, //pointer to file time to convert - &time //pointer to structure to receive system time - ) == 0) - throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" local FILETIME -> SYSTEMTIME: ") + - wxT("(") + wxULongLong(localFileTime.dwHighDateTime, localFileTime.dwLowDateTime).ToString() + wxT(") ") + - filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).To8BitData())); - - //assemble time string (performance optimized) - wxString formattedTime; - formattedTime.reserve(20); - - writeFourDigitNumber(time.wYear, formattedTime); - formattedTime += wxChar('-'); - writeTwoDigitNumber(time.wMonth, formattedTime); - formattedTime += wxChar('-'); - writeTwoDigitNumber(time.wDay, formattedTime); - formattedTime += wxChar(' '); - formattedTime += wxChar(' '); - writeTwoDigitNumber(time.wHour, formattedTime); - formattedTime += wxChar(':'); - writeTwoDigitNumber(time.wMinute, formattedTime); - formattedTime += wxChar(':'); - writeTwoDigitNumber(time.wSecond, formattedTime); - - return formattedTime; - -#elif defined FFS_LINUX - tm* timeinfo; - const time_t fileTime = utcTime.ToLong(); - timeinfo = localtime(&fileTime); //convert to local time - char buffer[50]; - strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", timeinfo); - - return wxString(buffer); -#endif -} +//############################################################################################################ /*Statistical theory: detect daylight saving time (DST) switch by comparing files that exist on both sides (and have same filesizes). If there are "enough" that have a shift by +-1h then assert that DST switch occured. What is "enough" =: N? N should be large enough AND small enough that the following two errors remain small: @@ -724,3 +975,5 @@ void FreeFileSync::checkForDSTChange(const FileCompareResult& gridData, } #endif //FFS_WIN */ + + diff --git a/algorithm.h b/algorithm.h index 25fc6338..b2b0a4ef 100644 --- a/algorithm.h +++ b/algorithm.h @@ -3,67 +3,53 @@ #include "fileHierarchy.h" -class ErrorHandler; -class wxComboBox; -class wxTextCtrl; -class wxDirPickerCtrl; -class wxScrolledWindow; - namespace FreeFileSync { - wxString formatFilesizeToShortString(const wxLongLong& filesize); - wxString formatFilesizeToShortString(const wxULongLong& filesize); - wxString formatFilesizeToShortString(const double filesize); - - wxString includeNumberSeparator(const wxString& number); - - void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker); - void setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker); - void scrollToBottom(wxScrolledWindow* scrWindow); +void swapGrids(const MainConfiguration& config, FolderComparison& folderCmp); - void swapGrids2(const MainConfiguration& config, FolderComparison& folderCmp); +struct DeterminationProblem //callback +{ + virtual ~DeterminationProblem() {} + virtual void reportWarning(const wxString& text) = 0; +}; +void redetermineSyncDirection(const SyncConfiguration& config, BaseDirMapping& baseDirectory, DeterminationProblem* handler); //handler may be NULL +void redetermineSyncDirection(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp, DeterminationProblem* handler); - void redetermineSyncDirection(const SyncConfiguration& config, HierarchyObject& baseDirectory); - void redetermineSyncDirection(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp); +void setSyncDirectionRec(SyncDirection newDirection, FileSystemObject& fsObj); //set new direction (recursively) - void setSyncDirection(SyncDirection newDirection, FileSystemObject& fsObj); //set new direction (recursively) +void applyFiltering(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp); - void applyFiltering(const MainConfiguration& currentMainCfg, FolderComparison& folderCmp); +//manual deletion of files on main grid +std::pair<wxString, int> deleteFromGridAndHDPreview( //returns wxString with elements to be deleted and total count + const std::vector<FileSystemObject*>& rowsToDeleteOnLeft, //all pointers need to be bound! + const std::vector<FileSystemObject*>& rowsToDeleteOnRight, // + const bool deleteOnBothSides); - //manual deletion of files on main grid - std::pair<wxString, int> deleteFromGridAndHDPreview( //returns wxString with elements to be deleted and total count - const std::vector<FileSystemObject*>& rowsToDeleteOnLeft, //all pointers need to be bound! - const std::vector<FileSystemObject*>& rowsToDeleteOnRight, // - const bool deleteOnBothSides); +class DeleteFilesHandler +{ +public: + DeleteFilesHandler() {} + virtual ~DeleteFilesHandler() {} - class DeleteFilesHandler + enum Response { - public: - DeleteFilesHandler() {} - virtual ~DeleteFilesHandler() {} - - enum Response - { - IGNORE_ERROR = 10, - RETRY - }; - virtual Response reportError(const wxString& errorMessage) = 0; - - //virtual void totalFilesToDelete(int objectsTotal) = 0; //informs about the total number of files to be deleted - virtual void deletionSuccessful() = 0; //called for each file/folder that has been deleted - + IGNORE_ERROR = 10, + RETRY }; - void deleteFromGridAndHD(FolderComparison& folderCmp, //attention: rows will be physically deleted! - std::vector<FileSystemObject*>& rowsToDeleteOnLeft, //refresh GUI grid after deletion to remove invalid rows - std::vector<FileSystemObject*>& rowsToDeleteOnRight, //all pointers need to be bound! - const bool deleteOnBothSides, - const bool useRecycleBin, - const MainConfiguration& mainConfig, - DeleteFilesHandler* statusHandler); - - - wxString utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename); + virtual Response reportError(const wxString& errorMessage) = 0; + + //virtual void totalFilesToDelete(int objectsTotal) = 0; //informs about the total number of files to be deleted + virtual void deletionSuccessful() = 0; //called for each file/folder that has been deleted + +}; +void deleteFromGridAndHD(FolderComparison& folderCmp, //attention: rows will be physically deleted! + std::vector<FileSystemObject*>& rowsToDeleteOnLeft, //refresh GUI grid after deletion to remove invalid rows + std::vector<FileSystemObject*>& rowsToDeleteOnRight, //all pointers need to be bound! + const bool deleteOnBothSides, + const bool useRecycleBin, + const MainConfiguration& mainConfig, + DeleteFilesHandler* statusHandler); } #endif // ALGORITHM_H_INCLUDED diff --git a/comparison.cpp b/comparison.cpp index a43a0c86..c2593ed0 100644 --- a/comparison.cpp +++ b/comparison.cpp @@ -7,8 +7,10 @@ #include <wx/msgdlg.h> #include <wx/log.h> #include "algorithm.h" +#include "ui/util.h" #include <wx/thread.h> #include <memory> +#include "shared/stringConv.h" #include "library/statusHandler.h" #include "shared/fileHandling.h" #include "shared/systemFunctions.h" @@ -17,6 +19,7 @@ #include <map> #include "fileHierarchy.h" #include <boost/bind.hpp> +#include <boost/scoped_array.hpp> using namespace FreeFileSync; @@ -65,10 +68,10 @@ public: const Zstring& relNameParentPf, //postfixed with FILE_NAME_SEPARATOR! DirContainer& output, StatusHandler* handler) : - baseCallback_(baseCallback), - relNameParentPf_(relNameParentPf), - output_(output), - statusHandler(handler) {} + baseCallback_(baseCallback), + relNameParentPf_(relNameParentPf), + output_(output), + statusHandler(handler) {} virtual ~DirCallback() {} @@ -91,11 +94,11 @@ class BaseDirCallback : public DirCallback<filterActive> friend class DirCallback<filterActive>; public: BaseDirCallback(DirContainer& output, const FilterProcess* filter, StatusHandler* handler) : - DirCallback<filterActive>(this, Zstring(), output, handler), - textScanning(Zstring(_("Scanning:")) + wxT(" \n")), - filterInstance(filter) {} + DirCallback<filterActive>(this, Zstring(), output, handler), + textScanning(wxToZ(wxString(_("Scanning:")) + wxT(" \n"))), + filterInstance(filter) {} - virtual TraverseCallback::ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName); + virtual TraverseCallback::ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const TraverseCallback::FileInfo& details); private: typedef boost::shared_ptr<const DirCallback<filterActive> > CallbackPointer; @@ -109,6 +112,17 @@ private: template <bool filterActive> TraverseCallback::ReturnValue DirCallback<filterActive>::onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) { + //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") + Zstring statusText = baseCallback_->textScanning; + statusText.reserve(statusText.length() + fullName.length() + 2); + statusText += DefaultChar('\"'); + statusText += fullName; + statusText += DefaultChar('\"'); + + //update UI/commandline status information + statusHandler->updateStatusText(statusText); + +//------------------------------------------------------------------------------------ //apply filter before processing (use relative name!) if (filterActive) { @@ -119,17 +133,8 @@ TraverseCallback::ReturnValue DirCallback<filterActive>::onFile(const DefaultCha } } - output_.addSubFile(FileDescriptor(shortName, details.lastWriteTimeRaw, details.fileSize), relNameParentPf_); - - //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") - Zstring statusText = baseCallback_->textScanning; - statusText.reserve(statusText.length() + fullName.length() + 2); - statusText += DefaultChar('\"'); - statusText += fullName; - statusText += DefaultChar('\"'); + output_.addSubFile(shortName, FileDescriptor(details.lastWriteTimeRaw, details.fileSize)); - //update UI/commandline status information - statusHandler->updateStatusText(statusText); //add 1 element to the progress indicator statusHandler->updateProcessedData(1, 0); //NO performance issue at all //trigger display refresh @@ -144,6 +149,17 @@ TraverseCallback::ReturnValDir DirCallback<filterActive>::onDir(const DefaultCha { using globalFunctions::FILE_NAME_SEPARATOR; + //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") + Zstring statusText = baseCallback_->textScanning; + statusText.reserve(statusText.length() + fullName.length() + 2); + statusText += DefaultChar('\"'); + statusText += fullName; + statusText += DefaultChar('\"'); + + //update UI/commandline status information + statusHandler->updateStatusText(statusText); + +//------------------------------------------------------------------------------------ Zstring relName = relNameParentPf_; relName += shortName; @@ -157,7 +173,7 @@ TraverseCallback::ReturnValDir DirCallback<filterActive>::onDir(const DefaultCha if (subObjMightMatch) { - DirContainer& subDir = output_.addSubDir(DirDescriptor(shortName), relNameParentPf_); + DirContainer& subDir = output_.addSubDir(shortName); DirCallback* subDirCallback = new DirCallback(baseCallback_, relName += FILE_NAME_SEPARATOR, subDir, statusHandler); baseCallback_->callBackBox.push_back(typename BaseDirCallback<filterActive>::CallbackPointer(subDirCallback)); //handle ownership @@ -170,24 +186,14 @@ TraverseCallback::ReturnValDir DirCallback<filterActive>::onDir(const DefaultCha } } - DirContainer& subDir = output_.addSubDir(DirDescriptor(shortName), relNameParentPf_); - + DirContainer& subDir = output_.addSubDir(shortName); - //assemble status message (performance optimized) = textScanning + wxT("\"") + fullName + wxT("\"") - Zstring statusText = baseCallback_->textScanning; - statusText.reserve(statusText.length() + fullName.length() + 2); - statusText += DefaultChar('\"'); - statusText += fullName; - statusText += DefaultChar('\"'); - - //update UI/commandline status information - statusHandler->updateStatusText(statusText); //add 1 element to the progress indicator statusHandler->updateProcessedData(1, 0); //NO performance issue at all //trigger display refresh statusHandler->requestUiRefresh(); - DirCallback* subDirCallback = new DirCallback(baseCallback_, relName+=FILE_NAME_SEPARATOR, subDir, statusHandler); + DirCallback* subDirCallback = new DirCallback(baseCallback_, relName += FILE_NAME_SEPARATOR, subDir, statusHandler); baseCallback_->callBackBox.push_back(typename BaseDirCallback<filterActive>::CallbackPointer(subDirCallback)); //handle ownership return ReturnValDir(ReturnValDir::Continue(), subDirCallback); @@ -213,17 +219,20 @@ TraverseCallback::ReturnValue DirCallback<filterActive>::onError(const wxString& template <bool filterActive> -TraverseCallback::ReturnValDir BaseDirCallback<filterActive>::onDir(const DefaultChar* shortName, const Zstring& fullName) +TraverseCallback::ReturnValue BaseDirCallback<filterActive>::onFile( + const DefaultChar* shortName, + const Zstring& fullName, + const TraverseCallback::FileInfo& details) { -//#ifdef FFS_WIN => transparency is more important: just scan every file -// if ( fullName.EndsWith(wxT("\\RECYCLER")) || -// fullName.EndsWith(wxT("\\System Volume Information"))) -// { -// DirCallback<filterActive>::statusHandler->requestUiRefresh(); -// return TraverseCallback::ReturnValDir::Ignore(); -// } -//#endif // FFS_WIN - return DirCallback<filterActive>::onDir(shortName, fullName); + //do not scan the database file +#ifdef FFS_WIN + if (getSyncDBFilename().CmpNoCase(shortName) == 0) +#elif defined FFS_LINUX + if (getSyncDBFilename().Cmp(shortName) == 0) +#endif + return TraverseCallback::TRAVERSING_CONTINUE; + + return DirCallback<filterActive>::onFile(shortName, fullName, details); } @@ -232,8 +241,8 @@ struct DirBufferKey { DirBufferKey(const Zstring& dirname, boost::shared_ptr<const FilterProcess>& filterInst) : - directoryName(dirname), - filterInstance(filterInst) {} + directoryName(dirname), + filterInstance(filterInst) {} Zstring directoryName; boost::shared_ptr<const FilterProcess> filterInstance; //buffering has to consider filtering! @@ -260,16 +269,16 @@ class CompareProcess::DirectoryBuffer //buffer multiple scans of the same direc { public: DirectoryBuffer(const bool traverseDirectorySymlinks, StatusHandler* statusUpdater) : - m_traverseDirectorySymlinks(traverseDirectorySymlinks), - m_statusUpdater(statusUpdater) {} + m_traverseDirectorySymlinks(traverseDirectorySymlinks), + m_statusUpdater(statusUpdater) {} - const DirContainer& getDirectoryDescription(const Zstring& directoryPostfixed, bool filterActive, const wxString& includeFilter, const wxString& excludeFilter); + const DirContainer& getDirectoryDescription(const Zstring& directoryPostfixed, bool filterActive, const Zstring& includeFilter, const Zstring& excludeFilter); private: typedef boost::shared_ptr<DirContainer> DirBufferValue; //exception safety: avoid memory leak typedef std::map<DirBufferKey, DirBufferValue> BufferType; - static DirBufferKey createKey(const Zstring& directoryPostfixed, bool filterActive, const wxString& includeFilter, const wxString& excludeFilter); + static DirBufferKey createKey(const Zstring& directoryPostfixed, bool filterActive, const Zstring& includeFilter, const Zstring& excludeFilter); DirContainer& insertIntoBuffer(const DirBufferKey& newKey); BufferType buffer; @@ -280,7 +289,7 @@ private: //------------------------------------------------------------------------------------------ -DirBufferKey CompareProcess::DirectoryBuffer::createKey(const Zstring& directoryPostfixed, bool filterActive, const wxString& includeFilter, const wxString& excludeFilter) +DirBufferKey CompareProcess::DirectoryBuffer::createKey(const Zstring& directoryPostfixed, bool filterActive, const Zstring& includeFilter, const Zstring& excludeFilter) { boost::shared_ptr<const FilterProcess> filterInstance( filterActive && FilterProcess(includeFilter, excludeFilter) != FilterProcess::nullFilter() ? //nullfilter: in: '*', ex '' @@ -311,8 +320,8 @@ DirContainer& CompareProcess::DirectoryBuffer::insertIntoBuffer(const DirBufferK const DirContainer& CompareProcess::DirectoryBuffer::getDirectoryDescription( const Zstring& directoryPostfixed, bool filterActive, - const wxString& includeFilter, - const wxString& excludeFilter) + const Zstring& includeFilter, + const Zstring& excludeFilter) { const DirBufferKey searchKey = createKey(directoryPostfixed, filterActive, includeFilter, excludeFilter); @@ -340,14 +349,14 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF checkEmptyDirnameActive = false; while (true) { - const ErrorHandler::Response rv = statusUpdater->reportError(wxString(_("Please fill all empty directory fields.")) + wxT("\n\n") + + const ErrorHandler::Response rv = statusUpdater->reportError(wxString(_("Please fill all empty directory fields.")) + wxT(" \n\n") + + wxT("(") + additionalInfo + wxT(")")); if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } } } @@ -356,29 +365,29 @@ void foldersAreValidForComparison(const std::vector<FolderPairCfg>& folderPairsF if (!i->leftDirectory.empty()) while (!FreeFileSync::dirExists(i->leftDirectory.c_str())) { - ErrorHandler::Response rv = statusUpdater->reportError(wxString(_("Directory does not exist:")) + wxT("\n") + - wxT("\"") + i->leftDirectory + wxT("\"") + wxT("\n\n") + + ErrorHandler::Response rv = statusUpdater->reportError(wxString(_("Directory does not exist:")) + wxT(" \n") + + wxT("\"") + zToWx(i->leftDirectory) + wxT("\"") + wxT("\n\n") + FreeFileSync::getLastErrorFormatted() + wxT(" ") + additionalInfo); if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } if (!i->rightDirectory.empty()) while (!FreeFileSync::dirExists(i->rightDirectory.c_str())) { ErrorHandler::Response rv = statusUpdater->reportError(wxString(_("Directory does not exist:")) + wxT("\n") + - wxT("\"") + i->rightDirectory + wxT("\"") + wxT("\n\n") + + wxT("\"") + zToWx(i->rightDirectory) + wxT("\"") + wxT("\n\n") + FreeFileSync::getLastErrorFormatted() + wxT(" ") + additionalInfo); if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } } } @@ -390,8 +399,8 @@ bool dependencyExists(const std::set<Zstring>& folders, const Zstring& newFolder if (newFolder.StartsWith(*i) || i->StartsWith(newFolder)) { warningMessage = wxString(_("Directories are dependent! Be careful when setting up synchronization rules:")) + wxT("\n") + - wxT("\"") + i->c_str() + wxT("\",\n") + - wxT("\"") + newFolder.c_str() + wxT("\""); + wxT("\"") + zToWx(*i) + wxT("\",\n") + + wxT("\"") + zToWx(newFolder) + wxT("\""); return true; } return false; @@ -429,33 +438,16 @@ CompareProcess::CompareProcess(const bool traverseSymLinks, const bool ignoreOneHourDiff, xmlAccess::OptionalDialogs& warnings, StatusHandler* handler) : - fileTimeTolerance(fileTimeTol), - ignoreOneHourDifference(ignoreOneHourDiff), - m_warnings(warnings), - statusUpdater(handler), - txtComparingContentOfFiles(Zstring(_("Comparing content of files %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)) + fileTimeTolerance(fileTimeTol), + ignoreOneHourDifference(ignoreOneHourDiff), + m_warnings(warnings), + statusUpdater(handler), + txtComparingContentOfFiles(wxToZ(_("Comparing content of files %x")).Replace(DefaultStr("%x"), DefaultStr("\n\"%x\""), false)) { directoryBuffer.reset(new DirectoryBuffer(traverseSymLinks, handler)); } -struct MemoryAllocator -{ - MemoryAllocator() - { - buffer = new unsigned char[bufferSize]; - } - - ~MemoryAllocator() - { - delete [] buffer; - } - - static const unsigned int bufferSize = 512 * 1024; //512 kb seems to be the perfect buffer size - unsigned char* buffer; -}; - - //callback functionality for status updates while comparing class CompareCallback { @@ -467,27 +459,36 @@ public: bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback) { - static MemoryAllocator memory1; - static MemoryAllocator memory2; - - wxFFile file1(filename1.c_str(), wxT("rb")); + const unsigned int BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size + static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]); + static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]); + +#ifdef FFS_WIN + wxFFile file1(filename1.c_str(), DefaultStr("rb")); +#elif defined FFS_LINUX + wxFFile file1(::fopen(filename1.c_str(), DefaultStr("rb"))); //utilize UTF-8 filename +#endif if (!file1.IsOpened()) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + filename1.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - wxFFile file2(filename2.c_str(), wxT("rb")); +#ifdef FFS_WIN + wxFFile file2(filename2.c_str(), DefaultStr("rb")); +#elif defined FFS_LINUX + wxFFile file2(::fopen(filename2.c_str(), DefaultStr("rb"))); //utilize UTF-8 filename +#endif if (!file2.IsOpened()) //NO cleanup necessary for (wxFFile) file1 - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + filename2.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); wxLongLong bytesCompared; do { - const size_t length1 = file1.Read(memory1.buffer, MemoryAllocator::bufferSize); - if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename1.c_str() + wxT("\"")); + const size_t length1 = file1.Read(memory1.get(), BUFFER_SIZE); + if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\"")); - const size_t length2 = file2.Read(memory2.buffer, MemoryAllocator::bufferSize); - if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename2.c_str() + wxT("\"")); + const size_t length2 = file2.Read(memory2.get(), BUFFER_SIZE); + if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\"")); - if (length1 != length2 || ::memcmp(memory1.buffer, memory2.buffer, length1) != 0) + if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) return false; bytesCompared += length1 * 2; @@ -509,11 +510,12 @@ class CmpCallbackImpl : public CompareCallback { public: CmpCallbackImpl(StatusHandler* handler, wxLongLong& bytesComparedLast) : - m_handler(handler), - m_bytesComparedLast(bytesComparedLast) {} + m_handler(handler), + m_bytesComparedLast(bytesComparedLast) {} virtual void updateCompareStatus(const wxLongLong& totalBytesTransferred) - { //called every 512 kB + { + //called every 512 kB //inform about the (differential) processed amount of data m_handler->updateProcessedData(0, totalBytesTransferred - m_bytesComparedLast); @@ -554,72 +556,11 @@ bool filesHaveSameContentUpdating(const Zstring& filename1, const Zstring& filen } -/* OLD IMPLEMENTATION USING A WORKER THREAD - -//handle execution of a method while updating the UI -class UpdateWhileComparing : public UpdateWhileExecuting -{ -public: - UpdateWhileComparing() {} - ~UpdateWhileComparing() {} - - Zstring file1; - Zstring file2; - bool success; - Zstring errorMessage; - bool sameContent; - -private: - void longRunner() //virtual method implementation - { - try - { - sameContent = filesHaveSameContent(file1, file2); - success = true; - } - catch (FileError& error) - { - success = false; - errorMessage = error.show(); - } - } -}; - - -bool filesHaveSameContentUpdating(const Zstring& filename1, const Zstring& filename2, const wxULongLong& totalBytesToCmp, StatusHandler* updateClass) -{ - static UpdateWhileComparing cmpAndUpdate; //single instantiation: thread enters wait phase after each execution - - cmpAndUpdate.waitUntilReady(); - - //longRunner is called from thread, but no mutex needed here, since thread is in waiting state! - cmpAndUpdate.file1 = filename1; - cmpAndUpdate.file2 = filename2; - - cmpAndUpdate.execute(updateClass); - - //no mutex needed here since longRunner is finished - if (!cmpAndUpdate.success) - throw FileError(cmpAndUpdate.errorMessage); - - //inform about the processed amount of data - updateClass->updateProcessedData(0, totalBytesToCmp.ToDouble()); - - return cmpAndUpdate.sameContent; -}*/ - -void formatPair(FolderPairCfg& input) -{ - input.leftDirectory = FreeFileSync::getFormattedDirectoryName(input.leftDirectory); - input.rightDirectory = FreeFileSync::getFormattedDirectoryName(input.rightDirectory); -} - - struct ToBeRemoved { bool operator()(const DirMapping& dirObj) const { - return !dirObj.selectedForSynchronization && dirObj.subDirs.size() == 0 && dirObj.subFiles.size() == 0; + return !dirObj.isActive() && dirObj.subDirs.size() == 0 && dirObj.subFiles.size() == 0; } }; @@ -627,39 +568,51 @@ struct ToBeRemoved class RemoveFilteredDirs { public: - RemoveFilteredDirs(const wxString& include, const wxString& exclude) : - filterProc(include, exclude) {} + RemoveFilteredDirs(const FilterProcess& filterProc) : + filterProc_(filterProc) {} - void operator()(HierarchyObject& hierObj) + void execute(HierarchyObject& hierObj) { //process subdirs recursively std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); - //filter subdirectories - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), boost::bind(&RemoveFilteredDirs::filterDir, this, _1)); - //remove superfluous directories hierObj.subDirs.erase(std::remove_if(hierObj.subDirs.begin(), hierObj.subDirs.end(), ::ToBeRemoved()), hierObj.subDirs.end()); } - void filterDir(FreeFileSync::DirMapping& dirObj) - { - const Zstring relName = dirObj.isEmpty<FreeFileSync::LEFT_SIDE>() ? - dirObj.getRelativeName<FreeFileSync::RIGHT_SIDE>() : - dirObj.getRelativeName<FreeFileSync::LEFT_SIDE>(); +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); - dirObj.selectedForSynchronization = filterProc.passDirFilter(relName, NULL); //subObjMightMatch is always true in this context! + void operator()(DirMapping& dirObj) + { + dirObj.setActive(filterProc_.passDirFilter(dirObj.getObjRelativeName().c_str(), NULL)); //subObjMightMatch is always true in this context! + execute(dirObj); } -private: - const FilterProcess filterProc; + const FilterProcess& filterProc_; }; +inline +void formatPair(FolderPairCfg& input) +{ + //ensure they end with globalFunctions::FILE_NAME_SEPARATOR and replace macros + input.leftDirectory = FreeFileSync::getFormattedDirectoryName(input.leftDirectory); + input.rightDirectory = FreeFileSync::getFormattedDirectoryName(input.rightDirectory); +} + + + + +//############################################################################################################################# + //filters and removes all excluded directories (but keeps those serving as parent folders) -void filterAndRemoveDirs(BaseDirMapping& baseDir, const wxString& include, const wxString& exclude) +void filterAndRemoveDirs(BaseDirMapping& baseDir, const Zstring& include, const Zstring& exclude) { - RemoveFilteredDirs(include, exclude)(baseDir); + FilterProcess filterProc(include, exclude); + + RemoveFilteredDirs(filterProc).execute(baseDir); } @@ -676,7 +629,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc //init process: keep at beginning so that all gui elements are initialized properly statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects - //format directory pairs: ensure they end with globalFunctions::FILE_NAME_SEPARATOR! + //format directory pairs: ensure they end with globalFunctions::FILE_NAME_SEPARATOR and replace macros! std::vector<FolderPairCfg> directoryPairsFormatted = directoryPairs; std::for_each(directoryPairsFormatted.begin(), directoryPairsFormatted.end(), formatPair); @@ -717,10 +670,26 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc //attention: some filtered directories are still in the comparison result! (see include filter handling!) if (fpCfg.filterIsActive) //let's filter them now... (and remove those that contain excluded elements only) - filterAndRemoveDirs(*j, fpCfg.includeFilter, fpCfg.excludeFilter); + filterAndRemoveDirs(*j, fpCfg.includeFilter.c_str(), fpCfg.excludeFilter.c_str()); - //set sync-direction initially - FreeFileSync::redetermineSyncDirection(fpCfg.syncConfiguration, *j); + //set initial sync-direction + class RedetermineCallback : public DeterminationProblem + { + public: + RedetermineCallback(bool& warningSyncDatabase, StatusHandler& statusUpdater) : + warningSyncDatabase_(warningSyncDatabase), + statusUpdater_(statusUpdater) {} + + virtual void reportWarning(const wxString& text) + { + statusUpdater_.reportWarning(text, warningSyncDatabase_); + } + private: + bool& warningSyncDatabase_; + StatusHandler& statusUpdater_; + } redetCallback(m_warnings.warningSyncDatabase, *statusUpdater); + + FreeFileSync::redetermineSyncDirection(fpCfg.syncConfiguration, *j, &redetCallback); } //only if everything was processed correctly output is written to! @@ -730,9 +699,9 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc catch (const std::exception& e) { if (dynamic_cast<const std::bad_alloc*>(&e) != NULL) - statusUpdater->reportFatalError(wxString(_("System out of memory!")) + wxT(" ") + wxString::From8BitData(e.what())); + statusUpdater->reportFatalError(wxString(_("System out of memory!")) + wxT(" ") + wxString::FromAscii(e.what())); else - statusUpdater->reportFatalError(wxString::From8BitData(e.what())); + statusUpdater->reportFatalError(wxString::FromAscii(e.what())); return; //should be obsolete! } } @@ -743,7 +712,7 @@ void CompareProcess::startCompareProcess(const std::vector<FolderPairCfg>& direc wxString getConflictInvalidDate(const Zstring& fileNameFull, const wxLongLong& utcTime) { wxString msg = _("File %x has an invalid date!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + fileNameFull.c_str() + wxT("\"")); + msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(fileNameFull) + wxT("\"")); msg += wxString(wxT("\n\n")) + _("Date") + wxT(": ") + utcTimeToLocalString(utcTime, fileNameFull); return wxString(_("Conflict detected:")) + wxT("\n") + msg; } @@ -760,7 +729,7 @@ wxString getConflictSameDateDiffSize(const FileMapping& fileObj) right.Pad(maxPref - right.length(), wxT(' '), true); wxString msg = _("Files %x have the same date but a different size!"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + fileObj.getRelativeName<LEFT_SIDE>() + wxT("\"")); + msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(fileObj.getRelativeName<LEFT_SIDE>()) + wxT("\"")); msg += wxT("\n\n"); msg += left + wxT("\t") + _("Date") + wxT(": ") + utcTimeToLocalString(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getFullName<LEFT_SIDE>()) + wxT(" \t") + _("Size") + wxT(": ") + fileObj.getFileSize<LEFT_SIDE>().ToString() + wxT("\n"); @@ -782,7 +751,7 @@ wxString getConflictChangeWithinHour(const FileMapping& fileObj) wxString msg = _("Files %x have a file time difference of less than 1 hour!\n\nIt's not safe to decide which one is newer due to Daylight Saving Time issues."); msg += wxString(wxT("\n")) + _("(Note that only FAT/FAT32 drives are affected by this problem!\nIn all other cases you can disable the setting \"ignore 1-hour difference\".)"); - msg.Replace(wxT("%x"), wxString(wxT("\"")) + fileObj.getRelativeName<LEFT_SIDE>() + wxT("\"")); + msg.Replace(wxT("%x"), wxString(wxT("\"")) + zToWx(fileObj.getRelativeName<LEFT_SIDE>()) + wxT("\"")); msg += wxT("\n\n"); msg += left + wxT("\t") + _("Date") + wxT(": ") + utcTimeToLocalString(fileObj.getLastWriteTime<LEFT_SIDE>(), fileObj.getFullName<LEFT_SIDE>()) + wxT("\n"); msg += right + wxT("\t") + _("Date") + wxT(": ") + utcTimeToLocalString(fileObj.getLastWriteTime<RIGHT_SIDE>(), fileObj.getFullName<RIGHT_SIDE>()); @@ -791,7 +760,7 @@ wxString getConflictChangeWithinHour(const FileMapping& fileObj) //----------------------------------------------------------------------------- inline -bool sameFileTime(const wxLongLong& a, const wxLongLong& b, const unsigned tolerance) +bool sameFileTime(const wxLongLong& a, const wxLongLong& b, const unsigned int tolerance) { if (a < b) return b - a <= tolerance; @@ -802,15 +771,21 @@ bool sameFileTime(const wxLongLong& a, const wxLongLong& b, const unsigned toler void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output) { + output.reserve(output.size() + directoryPairsFormatted.size()); + //process one folder pair after each other for (std::vector<FolderPairCfg>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) { - BaseDirMapping newEntry(pair->leftDirectory, pair->rightDirectory); + BaseDirMapping newEntry(pair->leftDirectory, + pair->rightDirectory, + pair->filterIsActive, + pair->includeFilter, + pair->excludeFilter); output.push_back(newEntry); //attention: push_back() copies by value!!! performance: append BEFORE writing values into fileCmp! - //do basis scan and retrieve files existing on both sides + //do basis scan and retrieve files existing on both sides as "compareCandidates" std::vector<FileMapping*> compareCandidates; - performBaseComparison(*pair, output.back(), compareCandidates); + performBaseComparison(output.back(), compareCandidates); //PERF_START; @@ -829,11 +804,10 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directo line->getLastWriteTime<LEFT_SIDE>() > oneYearFromNow || //dated more than one year in future line->getLastWriteTime<RIGHT_SIDE>() > oneYearFromNow) //dated more than one year in future { - line->cmpResult = FILE_CONFLICT; if (line->getLastWriteTime<LEFT_SIDE>() < 0 || line->getLastWriteTime<LEFT_SIDE>() > oneYearFromNow) - line->conflictDescription = getConflictInvalidDate(line->getFullName<LEFT_SIDE>(), line->getLastWriteTime<LEFT_SIDE>()); + line->setCategoryConflict(getConflictInvalidDate(line->getFullName<LEFT_SIDE>(), line->getLastWriteTime<LEFT_SIDE>())); else - line->conflictDescription = getConflictInvalidDate(line->getFullName<RIGHT_SIDE>(), line->getLastWriteTime<RIGHT_SIDE>()); + line->setCategoryConflict(getConflictInvalidDate(line->getFullName<RIGHT_SIDE>(), line->getLastWriteTime<RIGHT_SIDE>())); } else //from this block on all dates are at least "valid" { @@ -841,12 +815,9 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directo if (sameFileTime(line->getLastWriteTime<LEFT_SIDE>(), line->getLastWriteTime<RIGHT_SIDE>(), fileTimeTolerance)) { if (line->getFileSize<LEFT_SIDE>() == line->getFileSize<RIGHT_SIDE>()) - line->cmpResult = FILE_EQUAL; + line->setCategory<FILE_EQUAL>(); else - { - line->cmpResult = FILE_CONFLICT; //same date, different filesize - line->conflictDescription = getConflictSameDateDiffSize(*line); - } + line->setCategoryConflict(getConflictSameDateDiffSize(*line)); //same date, different filesize } else { @@ -855,27 +826,21 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directo { //date diff < 1 hour is a conflict: it's not safe to determine which file is newer if (sameFileTime(line->getLastWriteTime<LEFT_SIDE>(), line->getLastWriteTime<RIGHT_SIDE>(), 3600 - 2 - 1)) - { - line->cmpResult = FILE_CONFLICT; - line->conflictDescription = getConflictChangeWithinHour(*line); - } + line->setCategoryConflict(getConflictChangeWithinHour(*line)); else //exact +/- 1-hour detected: treat as equal { if (line->getFileSize<LEFT_SIDE>() == line->getFileSize<RIGHT_SIDE>()) - line->cmpResult = FILE_EQUAL; + line->setCategory<FILE_EQUAL>(); else - { - line->cmpResult = FILE_CONFLICT; //same date, different filesize - line->conflictDescription = getConflictSameDateDiffSize(*line); - } + line->setCategoryConflict(getConflictSameDateDiffSize(*line)); //same date, different filesize } } else { if (line->getLastWriteTime<LEFT_SIDE>() < line->getLastWriteTime<RIGHT_SIDE>()) - line->cmpResult = FILE_RIGHT_NEWER; + line->setCategory<FILE_RIGHT_NEWER>(); else - line->cmpResult = FILE_LEFT_NEWER; + line->setCategory<FILE_LEFT_NEWER>(); } } } @@ -883,12 +848,9 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPairCfg>& directo else //same write time { if (line->getFileSize<LEFT_SIDE>() == line->getFileSize<RIGHT_SIDE>()) - line->cmpResult = FILE_EQUAL; + line->setCategory<FILE_EQUAL>(); else - { - line->cmpResult = FILE_CONFLICT; //same date, different filesize - line->conflictDescription = getConflictSameDateDiffSize(*line); - } + line->setCategoryConflict(getConflictSameDateDiffSize(*line)); //same date, different filesize } } } @@ -911,14 +873,21 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director //PERF_START; std::vector<FileMapping*> compareCandidates; + //attention: make sure pointers in "compareCandidates" remain valid!!! + output.reserve(output.size() + directoryPairsFormatted.size()); + //process one folder pair after each other for (std::vector<FolderPairCfg>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) { - BaseDirMapping newEntry(pair->leftDirectory, pair->rightDirectory); + BaseDirMapping newEntry(pair->leftDirectory, + pair->rightDirectory, + pair->filterIsActive, + pair->includeFilter, + pair->excludeFilter); output.push_back(newEntry); //attention: push_back() copies by value!!! performance: append BEFORE writing values into fileCmp! //do basis scan and retrieve candidates for binary comparison (files existing on both sides) - performBaseComparison(*pair, output.back(), compareCandidates); + performBaseComparison(output.back(), compareCandidates); } //finish categorization... @@ -931,7 +900,7 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director { //pre-check: files have different content if they have a different filesize if ((*i)->getFileSize<LEFT_SIDE>() != (*i)->getFileSize<RIGHT_SIDE>()) - (*i)->cmpResult = FILE_DIFFERENT; + (*i)->setCategory<FILE_DIFFERENT>(); else filesToCompareBytewise.push_back(*i); } @@ -951,7 +920,7 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director FileMapping* const gridline = *j; Zstring statusText = txtComparingContentOfFiles; - statusText.Replace(wxT("%x"), gridline->getRelativeName<LEFT_SIDE>(), false); + statusText.Replace(DefaultStr("%x"), gridline->getRelativeName<LEFT_SIDE>(), false); statusUpdater->updateStatusText(statusText); //check files that exist in left and right model but have different content @@ -966,9 +935,9 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director gridline->getFullName<RIGHT_SIDE>(), gridline->getFileSize<LEFT_SIDE>() * 2, statusUpdater)) - gridline->cmpResult = FILE_EQUAL; + gridline->setCategory<FILE_EQUAL>(); else - gridline->cmpResult = FILE_DIFFERENT; + gridline->setCategory<FILE_DIFFERENT>(); statusUpdater->updateProcessedData(2, 0); //processed data is communicated in subfunctions! break; @@ -978,15 +947,14 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director ErrorHandler::Response rv = statusUpdater->reportError(error.show()); if (rv == ErrorHandler::IGNORE_ERROR) { - gridline->cmpResult = FILE_CONFLICT; //same date, different filesize - gridline->conflictDescription = wxString(_("Conflict detected:")) + wxT("\n") + _("Comparing files by content failed."); + gridline->setCategoryConflict(wxString(_("Conflict detected:")) + wxT("\n") + _("Comparing files by content failed.")); break; } else if (rv == ErrorHandler::RETRY) ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } } } @@ -996,12 +964,8 @@ void CompareProcess::compareByContent(const std::vector<FolderPairCfg>& director class MergeSides { public: - MergeSides(const Zstring& baseDirLeftPf, - const Zstring& baseDirRightPf, - std::vector<FileMapping*>& appendUndefinedOut) : - baseDirLeft(baseDirLeftPf), - baseDirRight(baseDirRightPf), - appendUndefined(appendUndefinedOut) {} + MergeSides(std::vector<FileMapping*>& appendUndefinedOut) : + appendUndefined(appendUndefinedOut) {} void execute(const DirContainer& leftSide, const DirContainer& rightSide, HierarchyObject& output) { @@ -1017,60 +981,52 @@ public: for (DirContainer::SubFileList::const_iterator i = leftSide.getSubFiles().begin(); i != leftSide.getSubFiles().end(); ++i) { - DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().find(*i); + DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().find(i->first); //find files that exist on left but not on right if (j == rightSide.getSubFiles().end()) - output.addSubFile(i->getData(), FILE_LEFT_SIDE_ONLY, FileMapping::nullData(), - RelNamesBuffered(baseDirLeft, //base sync dir postfixed - baseDirRight, - i->getParentRelNamePf())); //relative parent name postfixed + output.addSubFile(i->second.getData(), i->first); //find files that exist on left and right else { appendUndefined.push_back( - &output.addSubFile(i->getData(), FILE_EQUAL, j->getData(), //FILE_EQUAL is just a dummy-value here - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf()))); + &output.addSubFile(i->second.getData(), i->first, FILE_EQUAL, j->second.getData())); //FILE_EQUAL is just a dummy-value here } } //find files that exist on right but not on left for (DirContainer::SubFileList::const_iterator j = rightSide.getSubFiles().begin(); j != rightSide.getSubFiles().end(); ++j) { - if (leftSide.getSubFiles().find(*j) == leftSide.getSubFiles().end()) - output.addSubFile(FileMapping::nullData(), FILE_RIGHT_SIDE_ONLY, j->getData(), - RelNamesBuffered(baseDirLeft, baseDirRight, j->getParentRelNamePf())); + if (leftSide.getSubFiles().find(j->first) == leftSide.getSubFiles().end()) + output.addSubFile(j->first, j->second.getData()); } //----------------------------------------------------------------------------------------------- for (DirContainer::SubDirList::const_iterator i = leftSide.getSubDirs().begin(); i != leftSide.getSubDirs().end(); ++i) { - DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(*i); + DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().find(i->first); //find directories that exist on left but not on right if (j == rightSide.getSubDirs().end()) { - DirMapping& newDirMap = output.addSubDir(i->getData(), DIR_LEFT_SIDE_ONLY, DirMapping::nullData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())); - fillOneSide<true>(*i, newDirMap); //recurse into subdirectories + DirMapping& newDirMap = output.addSubDir(true, i->first, false); + fillOneSide<true>(i->second, newDirMap); //recurse into subdirectories } else //directories that exist on both sides { - DirMapping& newDirMap = output.addSubDir(i->getData(), DIR_EQUAL, j->getData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())); - execute(*i, *j, newDirMap); //recurse into subdirectories + DirMapping& newDirMap = output.addSubDir(true, i->first, true); + execute(i->second, j->second, newDirMap); //recurse into subdirectories } } //find directories that exist on right but not on left for (DirContainer::SubDirList::const_iterator j = rightSide.getSubDirs().begin(); j != rightSide.getSubDirs().end(); ++j) { - if (leftSide.getSubDirs().find(*j) == leftSide.getSubDirs().end()) + if (leftSide.getSubDirs().find(j->first) == leftSide.getSubDirs().end()) { - DirMapping& newDirMap = output.addSubDir(DirMapping::nullData(), DIR_RIGHT_SIDE_ONLY, j->getData(), - RelNamesBuffered(baseDirLeft, baseDirRight, j->getParentRelNamePf())); - fillOneSide<false>(*j, newDirMap); //recurse into subdirectories + DirMapping& newDirMap = output.addSubDir(false, j->first, true); + fillOneSide<false>(j->second, newDirMap); //recurse into subdirectories } } } @@ -1086,33 +1042,27 @@ private: for (DirContainer::SubFileList::const_iterator i = dirCont.getSubFiles().begin(); i != dirCont.getSubFiles().end(); ++i) { if (leftSide) - output.addSubFile(i->getData(), FILE_LEFT_SIDE_ONLY, FileMapping::nullData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())); + output.addSubFile(i->second.getData(), i->first); else - output.addSubFile(FileMapping::nullData(), FILE_RIGHT_SIDE_ONLY, i->getData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())); + output.addSubFile(i->first, i->second.getData()); } for (DirContainer::SubDirList::const_iterator i = dirCont.getSubDirs().begin(); i != dirCont.getSubDirs().end(); ++i) { DirMapping& newDirMap = leftSide ? - output.addSubDir(i->getData(), DIR_LEFT_SIDE_ONLY, DirMapping::nullData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())) : - output.addSubDir(DirMapping::nullData(), DIR_RIGHT_SIDE_ONLY, i->getData(), - RelNamesBuffered(baseDirLeft, baseDirRight, i->getParentRelNamePf())); + output.addSubDir(true, i->first, false) : + output.addSubDir(false, i->first, true); - fillOneSide<leftSide>(*i, newDirMap); //recurse into subdirectories + fillOneSide<leftSide>(i->second, newDirMap); //recurse into subdirectories } } - const Zstring& baseDirLeft; - const Zstring& baseDirRight; std::vector<FileMapping*>& appendUndefined; }; -void CompareProcess::performBaseComparison(const FolderPairCfg& pair, BaseDirMapping& output, std::vector<FileMapping*>& appendUndefined) +void CompareProcess::performBaseComparison(BaseDirMapping& output, std::vector<FileMapping*>& appendUndefined) { assert(output.subDirs.empty()); assert(output.subFiles.empty()); @@ -1120,24 +1070,23 @@ void CompareProcess::performBaseComparison(const FolderPairCfg& pair, BaseDirMap //PERF_START; //scan directories - const DirContainer& directoryLeft = directoryBuffer->getDirectoryDescription(pair.leftDirectory, - pair.filterIsActive, - pair.includeFilter, - pair.excludeFilter); + const DirContainer& directoryLeft = directoryBuffer->getDirectoryDescription( + output.getBaseDir<LEFT_SIDE>(), + output.getFilter().filterActive, + output.getFilter().includeFilter, + output.getFilter().excludeFilter); - const DirContainer& directoryRight = directoryBuffer->getDirectoryDescription(pair.rightDirectory, - pair.filterIsActive, - pair.includeFilter, - pair.excludeFilter); + const DirContainer& directoryRight = directoryBuffer->getDirectoryDescription( + output.getBaseDir<RIGHT_SIDE>(), + output.getFilter().filterActive, + output.getFilter().includeFilter, + output.getFilter().excludeFilter); - statusUpdater->updateStatusText(_("Generating file list...")); + statusUpdater->updateStatusText(wxToZ(_("Generating file list..."))); statusUpdater->forceUiRefresh(); //keep total number of scanned files up to date //PERF_STOP; - MergeSides(pair.leftDirectory, - pair.rightDirectory, - appendUndefined).execute(directoryLeft, directoryRight, output); - //PERF_STOP; + MergeSides(appendUndefined).execute(directoryLeft, directoryRight, output); } diff --git a/comparison.h b/comparison.h index dc8c4b8d..28f9d8a3 100644 --- a/comparison.h +++ b/comparison.h @@ -8,69 +8,69 @@ class StatusHandler; namespace FreeFileSync { - class FilterProcess; - - struct FolderPairCfg - { - FolderPairCfg(const Zstring& leftDir, - const Zstring& rightDir, - bool filterAct, - const wxString& include, - const wxString& exclude, - const SyncConfiguration& syncCfg) : - leftDirectory(leftDir), - rightDirectory(rightDir), - filterIsActive(filterAct), - includeFilter(include), - excludeFilter(exclude), - syncConfiguration(syncCfg) {} - - Zstring leftDirectory; - Zstring rightDirectory; - - bool filterIsActive; - wxString includeFilter; - wxString excludeFilter; - - SyncConfiguration syncConfiguration; - }; - std::vector<FolderPairCfg> extractCompareCfg(const MainConfiguration& mainCfg); - - - //class handling comparison process - class CompareProcess - { - public: - CompareProcess(const bool traverseSymLinks, - const unsigned int fileTimeTol, - const bool ignoreOneHourDiff, - xmlAccess::OptionalDialogs& warnings, - StatusHandler* handler); - - void startCompareProcess(const std::vector<FolderPairCfg>& directoryPairs, - const CompareVariant cmpVar, - FolderComparison& output); - - private: - void compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); - - void compareByContent(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); - - //create comparison result table and fill relation except for files existing on both sides - void performBaseComparison(const FolderPairCfg& pair, BaseDirMapping& output, std::vector<FileMapping*>& appendUndefined); - - //buffer accesses to the same directories; useful when multiple folder pairs are used - class DirectoryBuffer; - boost::shared_ptr<DirectoryBuffer> directoryBuffer; //std::auto_ptr does not work with forward declarations! - - const unsigned int fileTimeTolerance; //max allowed file time deviation - const bool ignoreOneHourDifference; - - xmlAccess::OptionalDialogs& m_warnings; - - StatusHandler* const statusUpdater; - const Zstring txtComparingContentOfFiles; - }; +class FilterProcess; + +struct FolderPairCfg +{ + FolderPairCfg(const Zstring& leftDir, + const Zstring& rightDir, + bool filterAct, + const Zstring& include, + const Zstring& exclude, + const SyncConfiguration& syncCfg) : + leftDirectory(leftDir), + rightDirectory(rightDir), + filterIsActive(filterAct), + includeFilter(include), + excludeFilter(exclude), + syncConfiguration(syncCfg) {} + + Zstring leftDirectory; + Zstring rightDirectory; + + bool filterIsActive; + Zstring includeFilter; + Zstring excludeFilter; + + SyncConfiguration syncConfiguration; +}; +std::vector<FolderPairCfg> extractCompareCfg(const MainConfiguration& mainCfg); + + +//class handling comparison process +class CompareProcess +{ +public: + CompareProcess(const bool traverseSymLinks, + const unsigned int fileTimeTol, + const bool ignoreOneHourDiff, + xmlAccess::OptionalDialogs& warnings, + StatusHandler* handler); + + void startCompareProcess(const std::vector<FolderPairCfg>& directoryPairs, + const CompareVariant cmpVar, + FolderComparison& output); + +private: + void compareByTimeSize(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); + + void compareByContent(const std::vector<FolderPairCfg>& directoryPairsFormatted, FolderComparison& output); + + //create comparison result table and fill relation except for files existing on both sides + void performBaseComparison(BaseDirMapping& output, std::vector<FileMapping*>& appendUndefined); + + //buffer accesses to the same directories; useful when multiple folder pairs are used + class DirectoryBuffer; + boost::shared_ptr<DirectoryBuffer> directoryBuffer; //std::auto_ptr does not work with forward declarations! + + const unsigned int fileTimeTolerance; //max allowed file time deviation + const bool ignoreOneHourDifference; + + xmlAccess::OptionalDialogs& m_warnings; + + StatusHandler* const statusUpdater; + const Zstring txtComparingContentOfFiles; +}; } #endif // COMPARISON_H_INCLUDED diff --git a/fileHierarchy.cpp b/fileHierarchy.cpp index 2f4e39af..4c6c9a4b 100644 --- a/fileHierarchy.cpp +++ b/fileHierarchy.cpp @@ -1,11 +1,23 @@ #include "fileHierarchy.h" +#include <wx/wfstream.h> +#include <wx/zstream.h> +#include "shared/globalFunctions.h" +#include "shared/fileError.h" +#include <boost/scoped_array.hpp> +#include <wx/intl.h> +#include "shared/stringConv.h" +#include "shared/fileHandling.h" +#ifdef FFS_WIN +#include <wx/msw/wrapwin.h> //includes "windows.h" +#endif using namespace FreeFileSync; +using namespace globalFunctions; struct LowerID { - bool operator()(const FileSystemObject& a, FileSystemObject::ObjectID b) const + bool operator()(const FileSystemObject& a, HierarchyObject::ObjectID b) const { return a.getId() < b; } @@ -15,14 +27,14 @@ struct LowerID return a.getId() < b.getId(); } - bool operator()(FileSystemObject::ObjectID a, const FileSystemObject& b) const + bool operator()(HierarchyObject::ObjectID a, const FileSystemObject& b) const { return a < b.getId(); } }; -const FileSystemObject* HierarchyObject::retrieveById(FileSystemObject::ObjectID id) const //returns NULL if object is not found +const FileSystemObject* HierarchyObject::retrieveById(ObjectID id) const //returns NULL if object is not found { //ATTENTION: HierarchyObject::retrieveById() can only work correctly if the following conditions are fulfilled: //1. on each level, files are added first, then directories (=> file id < dir id) @@ -36,7 +48,8 @@ const FileSystemObject* HierarchyObject::retrieveById(FileSystemObject::ObjectID //search within sub-files SubFileMapping::const_iterator i = std::lower_bound(subFiles.begin(), subFiles.end(), id, LowerID()); //binary search! if (i != subFiles.end()) - { //id <= i + { + //id <= i if (LowerID()(id, *i)) return NULL; // --i < id < i else //id found @@ -45,25 +58,12 @@ const FileSystemObject* HierarchyObject::retrieveById(FileSystemObject::ObjectID else //search within sub-directories { SubDirMapping::const_iterator j = std::lower_bound(subDirs.begin(), subDirs.end(), id, LowerID()); //binary search! - if (j != subDirs.end()) //id <= j - { - if (LowerID()(id, *j)) // --j < id < j - { - if (j == subDirs.begin()) - return NULL; - else - return (--j)->retrieveById(id); - } - else //id found - return &(*j); - } - else //subdirs < id - { - if (j == subDirs.begin()) //empty vector - return NULL; - else // --j < id < j - return (--j)->retrieveById(id); - } + if (j != subDirs.end() && !LowerID()(id, *j)) //id == j + return &(*j); + else if (j == subDirs.begin()) //either begin() == end() or id < begin() + return NULL; + else + return (--j)->retrieveById(id); //j != begin() and id < j } } @@ -103,3 +103,358 @@ void FileSystemObject::removeEmpty(BaseDirMapping& baseDir) removeEmptyRec(baseDir); } + +SyncOperation FileSystemObject::getSyncOperation(const CompareFilesResult cmpResult, + const bool selectedForSynchronization, + const SyncDirectionIntern syncDir) +{ + if (!selectedForSynchronization) return SO_DO_NOTHING; + + switch (cmpResult) + { + case FILE_LEFT_SIDE_ONLY: + switch (syncDir) + { + case SYNC_DIR_INT_LEFT: + return SO_DELETE_LEFT; //delete files on left + case SYNC_DIR_INT_RIGHT: + return SO_CREATE_NEW_RIGHT; //copy files to right + case SYNC_DIR_INT_NONE: + return SO_DO_NOTHING; + case SYNC_DIR_INT_CONFLICT: + return SO_UNRESOLVED_CONFLICT; + } + break; + + case FILE_RIGHT_SIDE_ONLY: + switch (syncDir) + { + case SYNC_DIR_INT_LEFT: + return SO_CREATE_NEW_LEFT; //copy files to left + case SYNC_DIR_INT_RIGHT: + return SO_DELETE_RIGHT; //delete files on right + case SYNC_DIR_INT_NONE: + return SO_DO_NOTHING; + case SYNC_DIR_INT_CONFLICT: + return SO_UNRESOLVED_CONFLICT; + } + break; + + case FILE_LEFT_NEWER: + case FILE_RIGHT_NEWER: + case FILE_DIFFERENT: + switch (syncDir) + { + case SYNC_DIR_INT_LEFT: + return SO_OVERWRITE_LEFT; //copy from right to left + case SYNC_DIR_INT_RIGHT: + return SO_OVERWRITE_RIGHT; //copy from left to right + case SYNC_DIR_INT_NONE: + return SO_DO_NOTHING; + case SYNC_DIR_INT_CONFLICT: + return SO_UNRESOLVED_CONFLICT; + } + break; + + case FILE_CONFLICT: + switch (syncDir) + { + case SYNC_DIR_INT_LEFT: + return SO_OVERWRITE_LEFT; //copy from right to left + case SYNC_DIR_INT_RIGHT: + return SO_OVERWRITE_RIGHT; //copy from left to right + case SYNC_DIR_INT_NONE: + case SYNC_DIR_INT_CONFLICT: + return SO_UNRESOLVED_CONFLICT; + } + break; + + case FILE_EQUAL: + assert(syncDir == SYNC_DIR_INT_NONE); + return SO_DO_NOTHING; + } + + return SO_DO_NOTHING; //dummy +} + + +//------------------------------------------------------------------------------------------------- +const Zstring& FreeFileSync::getSyncDBFilename() +{ +#ifdef FFS_WIN + static Zstring output(DefaultStr("sync.ffs_db")); +#elif defined FFS_LINUX + static Zstring output(DefaultStr(".sync.ffs_db")); //files beginning with dots are hidden e.g. in Nautilus +#endif + return output; +} + + +inline +Zstring readString(wxInputStream& stream) //read string from file stream +{ + const unsigned int strLength = readNumber<unsigned int>(stream); + if (strLength <= 1000) + { + DefaultChar buffer[1000]; + stream.Read(buffer, sizeof(DefaultChar) * strLength); + return Zstring(buffer, strLength); + } + else + { + boost::scoped_array<DefaultChar> buffer(new DefaultChar[strLength]); + stream.Read(buffer.get(), sizeof(DefaultChar) * strLength); + return Zstring(buffer.get(), strLength); + } +} + + +inline +void writeString(wxOutputStream& stream, const Zstring& str) //write string to filestream +{ + globalFunctions::writeNumber<unsigned int>(stream, str.length()); + stream.Write(str.c_str(), sizeof(DefaultChar) * str.length()); +} + + +//------------------------------------------------------------------------------------------------------------------------------- +const char FILE_FORMAT_DESCR[] = "FreeFileSync"; +const int FILE_FORMAT_VER = 1; +//------------------------------------------------------------------------------------------------------------------------------- + + +template <SelectedSide side> +struct IsNonEmpty +{ + bool operator()(const FileSystemObject& fsObj) const + { + return !fsObj.isEmpty<side>(); + } +}; + + +template <SelectedSide side> +class SaveRecursively +{ +public: + SaveRecursively(const BaseDirMapping& baseMapping, const Zstring& filename, wxOutputStream& stream) : filename_(filename), stream_(stream) + { + //save file format version + writeNumberC<int>(FILE_FORMAT_VER); + + //save filter settings + writeNumberC<bool>(baseMapping.getFilter().filterActive); + writeStringC(baseMapping.getFilter().includeFilter.c_str()); + writeStringC(baseMapping.getFilter().excludeFilter.c_str()); + + //start recursion + execute(baseMapping); + } + +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); + + void execute(const HierarchyObject& hierObj) + { + writeNumberC<unsigned int>(std::count_if(hierObj.subFiles.begin(), hierObj.subFiles.end(), IsNonEmpty<side>())); //number of (existing) files + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); + + writeNumberC<unsigned int>(std::count_if(hierObj.subDirs.begin(), hierObj.subDirs.end(), IsNonEmpty<side>())); //number of (existing) directories + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); + } + + void operator()(const FileMapping& fileMap) + { + if (!fileMap.isEmpty<side>()) + { + writeStringC(fileMap.getObjShortName()); //file name + writeNumberC<long>( fileMap.getLastWriteTime<side>().GetHi()); //last modification time + writeNumberC<unsigned long>(fileMap.getLastWriteTime<side>().GetLo()); // + writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetHi()); //filesize + writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetLo()); // + } + } + + void operator()(const DirMapping& dirMap) + { + if (!dirMap.isEmpty<side>()) + { + writeStringC(dirMap.getObjShortName()); //directory name + execute(dirMap); //recurse + } + } + + template <class T> + void writeNumberC(T number) //checked write operation + { + writeNumber<T>(stream_, number); + check(); + } + + void writeStringC(const Zstring& str) //checked write operation + { + writeString(stream_, str); + check(); + } + + void check() + { + if (stream_.GetLastError() != wxSTREAM_NO_ERROR) + throw FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") + + wxT("\"") + zToWx(filename_) + wxT("\"")); + } + + const Zstring& filename_; //used for error text only + wxOutputStream& stream_; +}; + + +//save/load DirContainer +void FreeFileSync::saveToDisk(const BaseDirMapping& baseMapping, SelectedSide side, const Zstring& filename) //throw (FileError) +{ + try //(try to) delete old file: overwriting directly doesn't always work + { + removeFile(filename, false); + } + catch (...) {} + + try + { + //write format description (uncompressed) + wxFFileOutputStream uncompressed(zToWx(filename), wxT("wb")); + uncompressed.Write(FILE_FORMAT_DESCR, sizeof(FILE_FORMAT_DESCR)); + if (uncompressed.GetLastError() != wxSTREAM_NO_ERROR) + throw FileError(wxString(_("Error writing to synchronization database:")) + wxT(" \n") + + wxT("\"") + zToWx(filename) + wxT("\"")); + + wxZlibOutputStream output(uncompressed, 4, wxZLIB_ZLIB); + /* 4 - best compromise between speed and compression: (scanning 200.000 objects) + 0 (uncompressed) 8,95 MB - 422 ms + 2 2,07 MB - 470 ms + 4 1,87 MB - 500 ms + 6 1,77 MB - 613 ms + 9 (maximal compression) 1,74 MB - 3330 ms */ + + if (side == LEFT_SIDE) + SaveRecursively<LEFT_SIDE>(baseMapping, filename, output); + else + SaveRecursively<RIGHT_SIDE>(baseMapping, filename, output); + } + catch (FileError&) + { + try //(try to) delete erroneous file + { + removeFile(filename, false); + } + catch (...) {} + throw; + } + + //(try to) hide database file +#ifdef FFS_WIN + ::SetFileAttributes(filename.c_str(), FILE_ATTRIBUTE_HIDDEN); +#endif +} + + +//------------------------------------------------------------------------------------------------------------------------- +class ReadRecursively +{ +public: + ReadRecursively(wxInputStream& stream, const Zstring& filename, DirInformation& dirInfo) : filename_(filename), stream_(stream) + { + if (readNumberC<int>() != FILE_FORMAT_VER) //read file format version + throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + zToWx(filename_) + wxT("\"")); + + //save filter settings + dirInfo.filterActive = readNumberC<bool>(); + dirInfo.includeFilter = readStringC(); + dirInfo.excludeFilter = readStringC(); + + //start recursion + execute(dirInfo.baseDirContainer); + } + +private: + void execute(DirContainer& dirCont) + { + unsigned int fileCount = readNumberC<unsigned int>(); + while (fileCount-- != 0) + readSubFile(dirCont); + + unsigned int dirCount = readNumberC<unsigned int>(); + while (dirCount-- != 0) + readSubDirectory(dirCont); + } + + void readSubFile(DirContainer& dirCont) + { + //attention: order of function argument evaluation is undefined! So do it one after the other... + const Zstring shortName = readStringC(); //file name + + const long modHigh = readNumberC<long>(); + const unsigned long modLow = readNumberC<unsigned long>(); + + const unsigned long sizeHigh = readNumberC<unsigned long>(); + const unsigned long sizeLow = readNumberC<unsigned long>(); + + dirCont.addSubFile(shortName, + FileDescriptor(wxLongLong(modHigh, modLow), wxULongLong(sizeHigh, sizeLow))); + } + + void readSubDirectory(DirContainer& dirCont) + { + const Zstring shortName = readStringC(); //directory name + DirContainer& subDir = dirCont.addSubDir(shortName); + execute(subDir); //recurse + } + + void check() + { + if (stream_.GetLastError() != wxSTREAM_NO_ERROR) + throw FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") + + wxT("\"") + zToWx(filename_) + wxT("\"")); + } + + template <class T> + T readNumberC() //checked read operation + { + T output = readNumber<T>(stream_); + check(); + return output; + } + + Zstring readStringC() //checked read operation + { + Zstring output = readString(stream_); + check(); + return output; + } + + const Zstring& filename_; //used for error text only + wxInputStream& stream_; +}; + + +boost::shared_ptr<const DirInformation> FreeFileSync::loadFromDisk(const Zstring& filename) //throw (FileError) +{ + //read format description (uncompressed) + wxFFileInputStream uncompressed(zToWx(filename), wxT("rb")); + + char formatDescr[sizeof(FILE_FORMAT_DESCR)]; + uncompressed.Read(formatDescr, sizeof(formatDescr)); + formatDescr[sizeof(FILE_FORMAT_DESCR) - 1] = 0; + if (uncompressed.GetLastError() != wxSTREAM_NO_ERROR) + throw FileError(wxString(_("Error reading from synchronization database:")) + wxT(" \n") + wxT("\"") + zToWx(filename) + wxT("\"")); + if (std::string(formatDescr) != FILE_FORMAT_DESCR) + throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + zToWx(filename) + wxT("\"")); + + + wxZlibInputStream input(uncompressed, wxZLIB_ZLIB); + + boost::shared_ptr<DirInformation> dirInfo(new DirInformation); + ReadRecursively(input, filename, *dirInfo); //read file/dir information + + return dirInfo; +} diff --git a/fileHierarchy.h b/fileHierarchy.h index 755bb97d..0db44c42 100644 --- a/fileHierarchy.h +++ b/fileHierarchy.h @@ -4,323 +4,395 @@ #include "shared/zstring.h" #include "shared/systemConstants.h" #include <wx/longlong.h> +#include <map> #include <set> #include <vector> #include "structures.h" +#include <boost/shared_ptr.hpp> class DirectoryBuffer; namespace FreeFileSync { - struct FileDescriptor - { - FileDescriptor( const Zstring& shortNameIn, - const wxLongLong& lastWriteTimeRawIn, - const wxULongLong& fileSizeIn) : - shortName(shortNameIn), - lastWriteTimeRaw(lastWriteTimeRawIn), - fileSize(fileSizeIn) {} - - //fullname == baseDirectoryPf + parentRelNamePf + shortName - Zstring shortName; - wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) - wxULongLong fileSize; - }; - +struct FileDescriptor +{ + FileDescriptor(const wxLongLong& lastWriteTimeRawIn, const wxULongLong& fileSizeIn) : + lastWriteTimeRaw(lastWriteTimeRawIn), + fileSize(fileSizeIn) {} + wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) + wxULongLong fileSize; +}; - struct DirDescriptor - { - DirDescriptor(const Zstring& shortNameIn) : - shortName(shortNameIn) {} - //fullname == baseDirectoryPf + parentRelNamePf + shortName - Zstring shortName; - }; +enum SelectedSide +{ + LEFT_SIDE, + RIGHT_SIDE +}; - class FileContainer; - class FileMapping; - class DirMapping; - class CompareProcess; - class HierarchyObject; - class BaseDirMapping; +class FileContainer; +class FileMapping; +class DirMapping; +class CompareProcess; +class FileSystemObject; +class BaseDirMapping; //------------------------------------------------------------------ - /* - DirContainer FileContainer +/* + DirContainer FileContainer - ERD: - DirContainer 1 -----> 0..n DirContainer - DirContainer 1 -----> 0..n FileContainer - */ +ERD: +DirContainer 1 -----> 0..n DirContainer +DirContainer 1 -----> 0..n FileContainer +*/ //------------------------------------------------------------------ - class DirContainer +class DirContainer +{ +public: + void addSubFile(const Zstring& shortName, const FileDescriptor& fileData); + DirContainer& addSubDir(const Zstring& shortName); + + //------------------------------------------------------------------ + struct CmpFilename { - public: - void addSubFile(const FileDescriptor& fileData, const Zstring& parentRelativeNamePf); - DirContainer& addSubDir(const DirDescriptor& dirData, const Zstring& parentRelativeNamePf); + bool operator()(const Zstring& a, const Zstring& b) const; + }; - //------------------------------------------------------------------ - template <class T> - struct CmpLess : public std::binary_function<T, T, bool> - { - bool operator()(const T& a, const T& b) const; - }; + typedef std::map<Zstring, DirContainer, CmpFilename> SubDirList; //key: shortName + typedef std::map<Zstring, FileContainer, CmpFilename> SubFileList; // + //------------------------------------------------------------------ - typedef std::set<DirContainer, CmpLess<DirContainer> > SubDirList; - typedef std::set<FileContainer, CmpLess<FileContainer> > SubFileList; - //------------------------------------------------------------------ + const SubDirList& getSubDirs() const; + const SubFileList& getSubFiles() const; - const DirDescriptor& getData() const; - const Zstring& getParentRelNamePf() const; + DirContainer() {} //default constructor use for base directory only! - const SubDirList& getSubDirs() const; - const SubFileList& getSubFiles() const; +private: + SubDirList subDirs; //contained directories + SubFileList subFiles; //contained files +}; - private: - friend class CompareProcess; //only DirectoryBuffer is allowed to create (Base-)DirContainers +//------------------------------------------------------------------ +class FileContainer +{ +public: + const FileDescriptor& getData() const; - DirContainer(const DirDescriptor& dirData, const Zstring& parentRelativeNamePf) : - data(dirData), - parentRelNamePf(parentRelativeNamePf) {} +private: + friend class DirContainer; - DirContainer() : data(Zstring()) {} //default constructor used by DirectoryBuffer only! + FileContainer(const FileDescriptor& fileData) : + data(fileData) {} - const DirDescriptor data; - const Zstring parentRelNamePf; //buffer some redundant data: + const FileDescriptor data; +}; - SubDirList subDirs; //contained directories - SubFileList subFiles; //contained files - }; //------------------------------------------------------------------ - class FileContainer - { - public: - const FileDescriptor& getData() const; - const Zstring& getParentRelNamePf() const; - - private: - friend class DirContainer; - - FileContainer(const FileDescriptor& fileData, const Zstring& parentRelativeNamePf) : - data(fileData), - parentRelNamePf(parentRelativeNamePf) {} +struct DirInformation +{ + //filter settings (used when retrieving directory data) + bool filterActive; + Zstring includeFilter; + Zstring excludeFilter; + //hierarchical directory information + DirContainer baseDirContainer; +}; - const FileDescriptor data; - const Zstring parentRelNamePf; //buffer some redundant data: - }; +//save/load full directory information +const Zstring& getSyncDBFilename(); //get short filename of database file +void saveToDisk(const BaseDirMapping& baseMapping, SelectedSide side, const Zstring& filename); //throw (FileError) -> return value always bound! +boost::shared_ptr<const DirInformation> loadFromDisk(const Zstring& filename); //throw (FileError) //------------------------------------------------------------------ - /* class hierarchy: +/* class hierarchy: - FileSystemObject HierarchyObject - /|\ /|\ - ______|______ ______|______ - | | | | - FileMapping DirMapping BaseDirMapping - */ + FileSystemObject HierarchyObject + /|\ /|\ + ______|______ ______|______ + | | | | +FileMapping DirMapping BaseDirMapping +*/ //------------------------------------------------------------------ - enum SelectedSide +class HierarchyObject +{ +public: + typedef unsigned int ObjectID; + FileSystemObject* retrieveById(ObjectID id); //returns NULL if object is not found; logarithmic complexity + const FileSystemObject* retrieveById(ObjectID id) const; // + + DirMapping& addSubDir(bool existsLeft, + const Zstring& dirNameShort, + bool existsRight); + + FileMapping& addSubFile(const FileDescriptor& left, //file exists on both sides + const Zstring& fileNameShort, + CompareFilesResult defaultCmpResult, + const FileDescriptor& right); + void addSubFile(const FileDescriptor& left, //file exists on left side only + const Zstring& fileNameShort); + void addSubFile(const Zstring& fileNameShort, //file exists on right side only + const FileDescriptor& right); + + const Zstring& getRelativeNamePf() const; //get name relative to base sync dir with FILE_NAME_SEPARATOR postfix: "blah\" + template <SelectedSide side> const Zstring& getBaseDir() const //postfixed! { - LEFT_SIDE, - RIGHT_SIDE - }; + return side == LEFT_SIDE ? baseDirLeft : baseDirRight; + } + + typedef std::vector<FileMapping> SubFileMapping; + typedef std::vector<DirMapping> SubDirMapping; + + SubFileMapping subFiles; //contained file maps + SubDirMapping subDirs; //contained directory maps + +protected: + //constructor used by DirMapping + HierarchyObject(const HierarchyObject& parent, const Zstring& shortName) : + relNamePf(parent.getRelativeNamePf() + shortName + globalFunctions::FILE_NAME_SEPARATOR), + baseDirLeft(parent.getBaseDir<LEFT_SIDE>()), + baseDirRight(parent.getBaseDir<RIGHT_SIDE>()) {} + + //constructor used by BaseDirMapping + HierarchyObject(const Zstring& dirPostfixedLeft, + const Zstring& dirPostfixedRight) : + baseDirLeft(dirPostfixedLeft), + baseDirRight(dirPostfixedRight) {} + ~HierarchyObject() {} //don't need polymorphic deletion + + virtual void swap(); + +private: + Zstring relNamePf; + Zstring baseDirLeft; //directory name ending with FILE_NAME_SEPARATOR + Zstring baseDirRight; //directory name ending with FILE_NAME_SEPARATOR +}; - struct RelNamesBuffered - { - RelNamesBuffered(const Zstring& baseDirPfLIn, //base sync dir postfixed - const Zstring& baseDirPfRIn, - const Zstring& parentRelNamePfIn) : //relative parent name postfixed - baseDirPfL(baseDirPfLIn), - baseDirPfR(baseDirPfRIn), - parentRelNamePf(parentRelNamePfIn) {} - - Zstring baseDirPfL; - Zstring baseDirPfR; - Zstring parentRelNamePf; - }; //------------------------------------------------------------------ - class FileSystemObject - { - public: - typedef unsigned int ObjectID; - template <SelectedSide side> bool isEmpty() const; - template <SelectedSide side> const Zstring& getShortName() const; - template <SelectedSide side> const Zstring getRelativeName() const; //get name relative to base sync dir without FILE_NAME_SEPARATOR prefix - template <SelectedSide side> const Zstring getParentRelativeName() const; //get name relative to base sync dir without FILE_NAME_SEPARATOR postfix - template <SelectedSide side> const Zstring getFullName() const; //getFullName() == getBaseDirPf() + getRelativeName() - template <SelectedSide side> const Zstring& getBaseDirPf() const; //base sync directory postfixed with FILE_NAME_SEPARATOR - ObjectID getId() const; //get unique id; ^= logical key - - void swap(); - - template <SelectedSide side> void copyTo(); //copy one side to the other (NOT recursive!!!) - template <SelectedSide side> void removeObject(); //removes file or directory (recursively!): used by manual deletion - bool isEmpty() const; //true, if both sides are empty - static void removeEmpty(BaseDirMapping& baseDir); //remove all invalid entries (where both sides are empty) recursively - static void removeEmptyNonRec(HierarchyObject& hierObj); //remove all invalid entries (where both sides are empty) non-recursively - - //sync settings: - SyncDirection syncDir; - bool selectedForSynchronization; - - virtual CompareFilesResult getCategory() const = 0; - virtual const wxString& getConflictDescription() const = 0; - - protected: - FileSystemObject(const RelNamesBuffered& relNameBuff) : - syncDir(SYNC_DIR_NONE), - selectedForSynchronization(true), - nameBuffer(relNameBuff), - uniqueId(getUniqueId()) {} - - ~FileSystemObject() {} //don't need polymorphic deletion - - private: - virtual void swapDescriptors() = 0; - - virtual bool isEmptyL() const = 0; - virtual bool isEmptyR() const = 0; - virtual void removeObjectL() = 0; - virtual void removeObjectR() = 0; - virtual void copyToL() = 0; - virtual void copyToR() = 0; - virtual const Zstring& getShortNameL() const = 0; - virtual const Zstring& getShortNameR() const = 0; - static ObjectID getUniqueId(); - - //buffer some redundant data: - RelNamesBuffered nameBuffer; //base sync dirs + relative parent name: this does NOT belong into FileDescriptor/DirDescriptor - - ObjectID uniqueId; - }; +struct RelNamesBuffered +{ + RelNamesBuffered(const Zstring& baseDirPfLIn, //base sync dir postfixed + const Zstring& baseDirPfRIn, + const Zstring& parentRelNamePfIn) : //relative parent name postfixed + baseDirPfL(baseDirPfLIn), + baseDirPfR(baseDirPfRIn), + parentRelNamePf(parentRelNamePfIn) {} + + Zstring baseDirPfL; + Zstring baseDirPfR; + Zstring parentRelNamePf; +}; + //------------------------------------------------------------------ - class HierarchyObject - { - public: - FileSystemObject* retrieveById(FileSystemObject::ObjectID id); //returns NULL if object is not found; logarithmic complexity - const FileSystemObject* retrieveById(FileSystemObject::ObjectID id) const; // - - DirMapping& addSubDir(const DirDescriptor& left, - CompareDirResult defaultCmpResult, - const DirDescriptor& right, - const RelNamesBuffered& relNameBuff); - FileMapping& addSubFile(const FileDescriptor& left, - CompareFilesResult defaultCmpResult, - const FileDescriptor& right, - const RelNamesBuffered& relNameBuff); - - typedef std::vector<FileMapping> SubFileMapping; - typedef std::vector<DirMapping> SubDirMapping; - - SubFileMapping subFiles; //contained file maps - SubDirMapping subDirs; //contained directory maps - - protected: - HierarchyObject() {} - ~HierarchyObject() {} //don't need polymorphic deletion +class FileSystemObject +{ +public: + const Zstring getParentRelativeName() const; //get name relative to base sync dir without FILE_NAME_SEPARATOR postfix + const Zstring getObjRelativeName() const; //same as getRelativeName() but also returns value if either side is empty + const Zstring& getObjShortName() const; //same as getShortName() but also returns value if either side is empty + template <SelectedSide side> bool isEmpty() const; + template <SelectedSide side> const Zstring& getShortName() const; + template <SelectedSide side> const Zstring getRelativeName() const; //get name relative to base sync dir without FILE_NAME_SEPARATOR prefix + template <SelectedSide side> const Zstring getFullName() const; //getFullName() == getBaseDirPf() + getRelativeName() + template <SelectedSide side> const Zstring& getBaseDirPf() const; //base sync directory postfixed with FILE_NAME_SEPARATOR + + HierarchyObject::ObjectID getId() const; //get unique id; ^= logical key + + //comparison result + virtual CompareFilesResult getCategory() const = 0; + virtual const wxString& getCatConflict() const = 0; //only filled if cmpResult == FILE_CONFLICT + //sync operation + SyncOperation getSyncOperation() const; + const wxString& getSyncOpConflict() const; //only filled if syncDir == SYNC_DIR_INT_CONFLICT + SyncOperation testSyncOperation(bool selected, SyncDirection syncDir) const; //get syncOp with provided settings + + //sync settings + void setSyncDir(SyncDirection newDir); + void setSyncDirConflict(const wxString& description); //set syncDir = SYNC_DIR_INT_CONFLICT + + bool isActive() const; + void setActive(bool active); + + void synchronizeSides(); //copy one side to the other (NOT recursive!!!) + template <SelectedSide side> void removeObject(); //removes file or directory (recursively!): used by manual deletion + bool isEmpty() const; //true, if both sides are empty + static void removeEmpty(BaseDirMapping& baseDir); //remove all invalid entries (where both sides are empty) recursively + static void removeEmptyNonRec(HierarchyObject& hierObj); //remove all invalid entries (where both sides are empty) non-recursively + +protected: + FileSystemObject(bool existsLeft, bool existsRight, const Zstring& shortName, const HierarchyObject& parent) : + selectedForSynchronization(true), + syncDir(SYNC_DIR_INT_NONE), + nameBuffer(parent.getBaseDir<LEFT_SIDE>(), parent.getBaseDir<RIGHT_SIDE>(), parent.getRelativeNamePf()), + existsLeft_(existsLeft), + existsRight_(existsRight), + shortName_(shortName), + uniqueId(getUniqueId()) {} + + ~FileSystemObject() {} //don't need polymorphic deletion + + virtual void swap(); + +private: + virtual void removeObjectL() = 0; + virtual void removeObjectR() = 0; + virtual void copyToL() = 0; + virtual void copyToR() = 0; + static HierarchyObject::ObjectID getUniqueId(); + + enum SyncDirectionIntern //same as SyncDirection, but one additional conflict type + { + SYNC_DIR_INT_LEFT = SYNC_DIR_LEFT, + SYNC_DIR_INT_RIGHT = SYNC_DIR_RIGHT, + SYNC_DIR_INT_NONE = SYNC_DIR_NONE, + SYNC_DIR_INT_CONFLICT //set if automatic synchronization cannot determine a direction }; + static SyncOperation getSyncOperation(const CompareFilesResult cmpResult, + const bool selectedForSynchronization, + const SyncDirectionIntern syncDir); //evaluate comparison result and sync direction + + bool selectedForSynchronization; + SyncDirectionIntern syncDir; + wxString syncOpConflictDescr; //only filled if syncDir == SYNC_DIR_INT_CONFLICT + + + //buffer some redundant data: + RelNamesBuffered nameBuffer; //base sync dirs + relative parent name: this does NOT belong into FileDescriptor/DirDescriptor + + bool existsLeft_; + bool existsRight_; + Zstring shortName_; + HierarchyObject::ObjectID uniqueId; +}; //------------------------------------------------------------------ - class DirMapping : public FileSystemObject, public HierarchyObject - { - public: - static const DirDescriptor& nullData(); - - virtual CompareFilesResult getCategory() const; - virtual const wxString& getConflictDescription() const; - - private: - friend class CompareProcess; //only CompareProcess shall be allowed to change cmpResult - friend class HierarchyObject; - virtual void swapDescriptors(); - virtual bool isEmptyL() const; - virtual bool isEmptyR() const; - virtual void removeObjectL(); - virtual void removeObjectR(); - virtual void copyToL(); - virtual void copyToR(); - virtual const Zstring& getShortNameL() const; - virtual const Zstring& getShortNameR() const; - //------------------------------------------------------------------ - - DirMapping(const DirDescriptor& left, CompareDirResult defaultCmpResult, const DirDescriptor& right, const RelNamesBuffered& relNameBuff) : - FileSystemObject(relNameBuff), - cmpResult(defaultCmpResult), - dataLeft(left), - dataRight(right) {} - - //categorization - CompareDirResult cmpResult; - - DirDescriptor dataLeft; - DirDescriptor dataRight; - }; +class DirMapping : public FileSystemObject, public HierarchyObject +{ +public: + virtual CompareFilesResult getCategory() const; + CompareDirResult getDirCategory() const; //returns actually used subsed of CompareFilesResult + virtual const wxString& getCatConflict() const; + +private: + friend class CompareProcess; //only CompareProcess shall be allowed to change cmpResult + friend class HierarchyObject; + virtual void swap(); + virtual void removeObjectL(); + virtual void removeObjectR(); + virtual void copyToL(); + virtual void copyToR(); + //------------------------------------------------------------------ + + DirMapping(bool existsLeft, + const Zstring& dirNameShort, + bool existsRight, + const HierarchyObject& parent) : + FileSystemObject(existsLeft, existsRight, dirNameShort, parent), + HierarchyObject(parent, dirNameShort), + cmpResult(!existsRight ? DIR_LEFT_SIDE_ONLY : existsLeft ? DIR_EQUAL : DIR_RIGHT_SIDE_ONLY) {} + + //categorization + CompareDirResult cmpResult; +}; //------------------------------------------------------------------ - class FileMapping : public FileSystemObject - { - public: - template <SelectedSide side> const wxLongLong& getLastWriteTime() const; - template <SelectedSide side> const wxULongLong& getFileSize() const; - - static const FileDescriptor& nullData(); - - virtual CompareFilesResult getCategory() const; - virtual const wxString& getConflictDescription() const; - - private: - friend class CompareProcess; //only CompareProcess shall be allowed to change cmpResult - friend class HierarchyObject; - - FileMapping(const FileDescriptor& left, CompareFilesResult defaultCmpResult, const FileDescriptor& right, const RelNamesBuffered& relNameBuff) : - FileSystemObject(relNameBuff), - cmpResult(defaultCmpResult), - dataLeft(left), - dataRight(right) {} - - virtual void swapDescriptors(); - virtual bool isEmptyL() const; - virtual bool isEmptyR() const; - virtual void removeObjectL(); - virtual void removeObjectR(); - virtual void copyToL(); - virtual void copyToR(); - virtual const Zstring& getShortNameL() const; - virtual const Zstring& getShortNameR() const; - //------------------------------------------------------------------ - - //categorization - CompareFilesResult cmpResult; - wxString conflictDescription; //only filled if cmpResult == FILE_CONFLICT - - FileDescriptor dataLeft; - FileDescriptor dataRight; - }; +class FileMapping : public FileSystemObject +{ +public: + template <SelectedSide side> const wxLongLong& getLastWriteTime() const; + template <SelectedSide side> const wxULongLong& getFileSize() const; + + virtual CompareFilesResult getCategory() const; + virtual const wxString& getCatConflict() const; + +private: + friend class CompareProcess; //only CompareProcess shall be allowed to change cmpResult + friend class HierarchyObject; //construction + + template <CompareFilesResult res> + void setCategory(); + void setCategoryConflict(const wxString& description); + + FileMapping(const FileDescriptor& left, //file exists on both sides + const Zstring& fileNameShort, + CompareFilesResult defaultCmpResult, + const FileDescriptor& right, + const HierarchyObject& parent) : + FileSystemObject(true, true, fileNameShort, parent), + cmpResult(defaultCmpResult), + dataLeft(left), + dataRight(right) {} + FileMapping(const FileDescriptor& left, //file exists on left side only + const Zstring& fileNameShort, + const HierarchyObject& parent) : + FileSystemObject(true, false, fileNameShort, parent), + cmpResult(FILE_LEFT_SIDE_ONLY), + dataLeft(left), + dataRight(0, 0) {} + FileMapping(const Zstring& fileNameShort, //file exists on right side only + const FileDescriptor& right, + const HierarchyObject& parent) : + FileSystemObject(false, true, fileNameShort, parent), + cmpResult(FILE_RIGHT_SIDE_ONLY), + dataLeft(0, 0), + dataRight(right) {} + + virtual void swap(); + virtual void removeObjectL(); + virtual void removeObjectR(); + virtual void copyToL(); + virtual void copyToR(); + //------------------------------------------------------------------ + + //categorization + CompareFilesResult cmpResult; + wxString cmpConflictDescr; //only filled if cmpResult == FILE_CONFLICT + + FileDescriptor dataLeft; + FileDescriptor dataRight; +}; //------------------------------------------------------------------ - class BaseDirMapping : public HierarchyObject //synchronization base directory - { - public: - BaseDirMapping(const Zstring& dirPostfixedLeft, const Zstring& dirPostfixedRight) : - baseDirLeft(dirPostfixedLeft), - baseDirRight(dirPostfixedRight) {} +class BaseDirMapping : public HierarchyObject //synchronization base directory +{ +public: + BaseDirMapping(const Zstring& dirPostfixedLeft, + const Zstring& dirPostfixedRight, + bool filterActive, + const Zstring& includeFilter, + const Zstring& excludeFilter) : + HierarchyObject(dirPostfixedLeft, dirPostfixedRight), + filter(filterActive, includeFilter, excludeFilter) {} + + struct FilterSettings + { + FilterSettings(bool active, + const Zstring& include, + const Zstring& exclude) : + filterActive(active), + includeFilter(include), + excludeFilter(exclude) {} + bool filterActive; + Zstring includeFilter; + Zstring excludeFilter; + }; - template <SelectedSide side> const Zstring& getBaseDir() const; + const FilterSettings& getFilter() const; + template <SelectedSide side> Zstring getDBFilename() const; + virtual void swap(); - private: - Zstring baseDirLeft; //directory name ending with FILE_NAME_SEPARATOR - Zstring baseDirRight; //directory name ending with FILE_NAME_SEPARATOR - }; +private: + FilterSettings filter; +}; - typedef std::vector<BaseDirMapping> FolderComparison; +typedef std::vector<BaseDirMapping> FolderComparison; //------------------------------------------------------------------ @@ -343,33 +415,32 @@ namespace FreeFileSync //---------------Inline Implementation--------------------------------------------------- - inline - FileSystemObject* HierarchyObject::retrieveById(FileSystemObject::ObjectID id) //returns NULL if object is not found - { - //code re-use of const method: see Meyers Effective C++ - return const_cast<FileSystemObject*>(static_cast<const HierarchyObject&>(*this).retrieveById(id)); - } +inline +FileSystemObject* HierarchyObject::retrieveById(ObjectID id) //returns NULL if object is not found +{ + //code re-use of const method: see Meyers Effective C++ + return const_cast<FileSystemObject*>(static_cast<const HierarchyObject&>(*this).retrieveById(id)); +} - inline - FileSystemObject::ObjectID FileSystemObject::getId() const - { - return uniqueId; - } +inline +HierarchyObject::ObjectID FileSystemObject::getId() const +{ + return uniqueId; +} - inline - FileSystemObject::ObjectID FileSystemObject::getUniqueId() - { - static unsigned int id = 0; - return ++id; - } +inline +HierarchyObject::ObjectID FileSystemObject::getUniqueId() +{ + static unsigned int id = 0; + return ++id; +} - template <class T> - inline - bool DirContainer::CmpLess<T>::operator()(const T& a, const T& b) const - { +inline +bool DirContainer::CmpFilename::operator()(const Zstring& a, const Zstring& b) const +{ // //quick check based on string length // const size_t aLength = a.data.shortName.length(); // const size_t bLength = b.data.shortName.length(); @@ -377,418 +448,516 @@ namespace FreeFileSync // return aLength < bLength; #ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - return a.data.shortName.CmpNoCase(b.data.shortName) < 0; + return a.CmpNoCase(b) < 0; #elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case - return a.data.shortName.Cmp(b.data.shortName) < 0; + return a.Cmp(b) < 0; #endif - } +} +inline +const DirContainer::SubDirList& DirContainer::getSubDirs() const +{ + return subDirs; +} - inline - const DirDescriptor& DirContainer::getData() const - { - return data; - } +inline +const DirContainer::SubFileList& DirContainer::getSubFiles() const +{ + return subFiles; +} - inline - const Zstring& DirContainer::getParentRelNamePf() const - { - return parentRelNamePf; - } +inline +const FileDescriptor& FileContainer::getData() const +{ + return data; +} - inline - const DirContainer::SubDirList& DirContainer::getSubDirs() const - { - return subDirs; - } +inline +DirContainer& DirContainer::addSubDir(const Zstring& shortName) +{ + return subDirs.insert(std::make_pair(shortName, DirContainer())).first->second; +} - inline - const DirContainer::SubFileList& DirContainer::getSubFiles() const - { - return subFiles; - } +inline +void DirContainer::addSubFile(const Zstring& shortName, const FileDescriptor& fileData) +{ + subFiles.insert(std::make_pair(shortName, FileContainer(fileData))); +} - inline - const FileDescriptor& FileContainer::getData() const - { - return data; - } +inline +CompareFilesResult FileMapping::getCategory() const +{ + return cmpResult; +} - inline - const Zstring& FileContainer::getParentRelNamePf() const - { - return parentRelNamePf; - } +inline +const wxString& FileMapping::getCatConflict() const +{ + return cmpConflictDescr; +} - inline - DirContainer& DirContainer::addSubDir(const DirDescriptor& dirData, const Zstring& parentRelativeNamePf) - { - //const cast: another crime in the name of unproven performance optimization ;) however key part cannot be changed, so this should be safe - return const_cast<DirContainer&>(*subDirs.insert(DirContainer(dirData, parentRelativeNamePf)).first); - } +inline +CompareFilesResult DirMapping::getCategory() const +{ + return convertToFilesResult(cmpResult); +} - inline - void DirContainer::addSubFile(const FileDescriptor& fileData, const Zstring& parentRelativeNamePf) - { - subFiles.insert(FileContainer(fileData, parentRelativeNamePf)); - } +inline +CompareDirResult DirMapping::getDirCategory() const +{ + return cmpResult; +} - inline - CompareFilesResult FileMapping::getCategory() const - { - return cmpResult; - } +inline +const wxString& DirMapping::getCatConflict() const +{ + static wxString empty; + return empty; +} - inline - const wxString& FileMapping::getConflictDescription() const - { - return conflictDescription; - } +inline +void FileSystemObject::setSyncDir(SyncDirection newDir) +{ + syncDir = static_cast<SyncDirectionIntern>(newDir); //should be safe by design +} - inline - CompareFilesResult DirMapping::getCategory() const - { - return convertToFilesResult(cmpResult); - } +inline +const wxString& FileSystemObject::getSyncOpConflict() const +{ + //a sync operation conflict can occur when: + //1. category-conflict and syncDir == NONE -> problem finding category + //2. syncDir == SYNC_DIR_INT_CONFLICT -> problem finding sync direction + return syncDir == SYNC_DIR_INT_CONFLICT ? syncOpConflictDescr : getCatConflict(); +} - inline - const wxString& DirMapping::getConflictDescription() const - { - static wxString empty; - return empty; - } +inline +void FileSystemObject::setSyncDirConflict(const wxString& description) //set syncDir = SYNC_DIR_INT_CONFLICT +{ + syncDir = SYNC_DIR_INT_CONFLICT; + syncOpConflictDescr = description; +} - template <SelectedSide side> - inline - bool FileSystemObject::isEmpty() const - { - return side == LEFT_SIDE ? isEmptyL() : isEmptyR(); - } +inline +bool FileSystemObject::isActive() const +{ + return selectedForSynchronization; +} - inline - bool FileSystemObject::isEmpty() const - { - return isEmptyL() && isEmptyR(); - } +inline +void FileSystemObject::setActive(bool active) +{ + selectedForSynchronization = active; +} - template <SelectedSide side> - inline - const Zstring& FileSystemObject::getShortName() const - { - return side == LEFT_SIDE ? getShortNameL() : getShortNameR(); - } +inline +SyncOperation FileSystemObject::getSyncOperation() const +{ + return getSyncOperation(getCategory(), selectedForSynchronization, syncDir); +} - template <SelectedSide side> - inline - const Zstring FileSystemObject::getRelativeName() const - { - return isEmpty<side>() ? Zstring() : nameBuffer.parentRelNamePf + getShortName<side>(); - } +inline +SyncOperation FileSystemObject::testSyncOperation(bool selected, SyncDirection proposedDir) const +{ + return getSyncOperation(getCategory(), selected, static_cast<SyncDirectionIntern>(proposedDir)); //should be safe by design +} - template <SelectedSide side> - inline - const Zstring FileSystemObject::getParentRelativeName() const - { - return nameBuffer.parentRelNamePf.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); //returns empty string if char not found - } +template <> +inline +bool FileSystemObject::isEmpty<LEFT_SIDE>() const +{ + return !existsLeft_; +} - template <SelectedSide side> - inline - const Zstring FileSystemObject::getFullName() const - { - return isEmpty<side>() ? Zstring() : getBaseDirPf<side>() + nameBuffer.parentRelNamePf + getShortName<side>(); - } +template <> +inline +bool FileSystemObject::isEmpty<RIGHT_SIDE>() const +{ + return !existsRight_; +} - template <SelectedSide side> - inline - const Zstring& FileSystemObject::getBaseDirPf() const - { - return side == LEFT_SIDE ? nameBuffer.baseDirPfL : nameBuffer.baseDirPfR; - } +inline +bool FileSystemObject::isEmpty() const +{ + return isEmpty<LEFT_SIDE>() && isEmpty<RIGHT_SIDE>(); +} - template <SelectedSide side> - inline - void FileSystemObject::removeObject() - { - if (side == LEFT_SIDE) - removeObjectL(); - else - removeObjectR(); - } +template <SelectedSide side> +inline +const Zstring& FileSystemObject::getShortName() const +{ + static Zstring null; + return isEmpty<side>() ? null : shortName_; +} - template <SelectedSide side> - inline - void FileSystemObject::copyTo() - { - syncDir = SYNC_DIR_NONE; - if (side == LEFT_SIDE) - copyToL(); - else - copyToR(); - } +template <SelectedSide side> +inline +const Zstring FileSystemObject::getRelativeName() const +{ + return isEmpty<side>() ? Zstring() : nameBuffer.parentRelNamePf + shortName_; +} - inline - void FileSystemObject::swap() - { - //swap file descriptors - swapDescriptors(); - } +inline +const Zstring FileSystemObject::getObjRelativeName() const +{ + return nameBuffer.parentRelNamePf + shortName_; +} - inline - DirMapping& HierarchyObject::addSubDir(const DirDescriptor& left, - CompareDirResult defaultCmpResult, - const DirDescriptor& right, - const RelNamesBuffered& relNameBuff) - { - subDirs.push_back(DirMapping(left, defaultCmpResult, right, relNameBuff)); - return subDirs.back(); - } +inline +const Zstring& FileSystemObject::getObjShortName() const +{ + return shortName_; +} - inline - FileMapping& HierarchyObject::addSubFile(const FileDescriptor& left, - CompareFilesResult defaultCmpResult, - const FileDescriptor& right, - const RelNamesBuffered& relNameBuff) - { - subFiles.push_back(FileMapping(left, defaultCmpResult, right, relNameBuff)); - return subFiles.back(); - } +inline +const Zstring FileSystemObject::getParentRelativeName() const +{ + return nameBuffer.parentRelNamePf.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); //returns empty string if char not found +} - inline - void DirMapping::swapDescriptors() - { - //swap compare result - switch (cmpResult) - { - case DIR_LEFT_SIDE_ONLY: - cmpResult = DIR_RIGHT_SIDE_ONLY; - break; - case DIR_RIGHT_SIDE_ONLY: - cmpResult = DIR_LEFT_SIDE_ONLY; - break; - case DIR_EQUAL: - break; - } - - std::swap(dataLeft, dataRight); - } +template <SelectedSide side> +inline +const Zstring FileSystemObject::getFullName() const +{ + return isEmpty<side>() ? Zstring() : getBaseDirPf<side>() + nameBuffer.parentRelNamePf + shortName_; +} - inline - const DirDescriptor& DirMapping::nullData() - { - static DirDescriptor output( static_cast<Zstring>(Zstring())); - return output; - } +template <> +inline +const Zstring& FileSystemObject::getBaseDirPf<LEFT_SIDE>() const +{ + return nameBuffer.baseDirPfL; +} - inline - void DirMapping::removeObjectL() - { - cmpResult = DIR_RIGHT_SIDE_ONLY; - dataLeft = nullData(); - std::for_each(subFiles.begin(), subFiles.end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); - std::for_each(subDirs.begin(), subDirs.end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); - } +template <> +inline +const Zstring& FileSystemObject::getBaseDirPf<RIGHT_SIDE>() const +{ + return nameBuffer.baseDirPfR; +} - inline - void DirMapping::removeObjectR() - { - cmpResult = DIR_LEFT_SIDE_ONLY; - dataRight = nullData(); - std::for_each(subFiles.begin(), subFiles.end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); - std::for_each(subDirs.begin(), subDirs.end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); - } +template <> +inline +void FileSystemObject::removeObject<LEFT_SIDE>() +{ + existsLeft_ = false; + removeObjectL(); +} - inline - void DirMapping::copyToL() - { - cmpResult = DIR_EQUAL; - dataLeft = dataRight; - } +template <> +inline +void FileSystemObject::removeObject<RIGHT_SIDE>() +{ + existsRight_ = false; + removeObjectR(); +} - inline - void DirMapping::copyToR() - { - cmpResult = DIR_EQUAL; - dataRight = dataLeft; - } +inline +void FileSystemObject::synchronizeSides() +{ + switch (syncDir) + { + case SYNC_DIR_INT_LEFT: + existsLeft_ = existsRight_; + copyToL(); + break; + case SYNC_DIR_INT_RIGHT: + existsRight_ = existsLeft_; + copyToR(); + break; + case SYNC_DIR_INT_NONE: + case SYNC_DIR_INT_CONFLICT: + assert(!"if nothing's todo then why arrive here?"); + break; + } + + syncDir = SYNC_DIR_INT_NONE; +} - inline - const Zstring& DirMapping::getShortNameL() const - { - return dataLeft.shortName; - } +inline +void FileSystemObject::swap() +{ + std::swap(nameBuffer.baseDirPfL, nameBuffer.baseDirPfR); + std::swap(existsLeft_, existsRight_); +} - inline - const Zstring& DirMapping::getShortNameR() const - { - return dataRight.shortName; - } +inline +void HierarchyObject::swap() +{ + std::swap(baseDirLeft, baseDirRight); + //files + std::for_each(subFiles.begin(), subFiles.end(), std::mem_fun_ref(&FileMapping::swap)); + //directories + std::for_each(subDirs.begin(), subDirs.end(), std::mem_fun_ref(&DirMapping::swap)); +} - inline - bool DirMapping::isEmptyL() const - { - return dataLeft.shortName.empty(); - } +inline +const Zstring& HierarchyObject::getRelativeNamePf() const +{ + return relNamePf; +} - inline - bool DirMapping::isEmptyR() const - { - return dataRight.shortName.empty(); - } +inline +DirMapping& HierarchyObject::addSubDir(bool existsLeft, + const Zstring& dirNameShort, + bool existsRight) +{ + subDirs.push_back(DirMapping(existsLeft, dirNameShort, existsRight, *this)); + return subDirs.back(); +} - template <SelectedSide side> - inline - const Zstring& BaseDirMapping::getBaseDir() const - { - return side == LEFT_SIDE ? baseDirLeft : baseDirRight; - } +inline +FileMapping& HierarchyObject::addSubFile(const FileDescriptor& left, //file exists on both sides + const Zstring& fileNameShort, + CompareFilesResult defaultCmpResult, + const FileDescriptor& right) +{ + subFiles.push_back(FileMapping(left, fileNameShort, defaultCmpResult, right, *this)); + return subFiles.back(); +} + + +inline +void HierarchyObject::addSubFile(const FileDescriptor& left, //file exists on left side only + const Zstring& fileNameShort) +{ + subFiles.push_back(FileMapping(left, fileNameShort, *this)); +} + + +inline +void HierarchyObject::addSubFile(const Zstring& fileNameShort, //file exists on right side only + const FileDescriptor& right) +{ + subFiles.push_back(FileMapping(fileNameShort, right, *this)); +} + + +inline +void BaseDirMapping::swap() +{ + //call base class versions + HierarchyObject::swap(); +} - inline - void FileMapping::swapDescriptors() - { - //swap compare result - switch (cmpResult) - { - case FILE_LEFT_SIDE_ONLY: - cmpResult = FILE_RIGHT_SIDE_ONLY; - break; - case FILE_RIGHT_SIDE_ONLY: - cmpResult = FILE_LEFT_SIDE_ONLY; - break; - case FILE_LEFT_NEWER: - cmpResult = FILE_RIGHT_NEWER; - break; - case FILE_RIGHT_NEWER: - cmpResult = FILE_LEFT_NEWER; - break; - case FILE_DIFFERENT: - case FILE_EQUAL: - case FILE_CONFLICT: - break; - } - - std::swap(dataLeft, dataRight); - } +inline +void DirMapping::swap() +{ + //call base class versions + HierarchyObject::swap(); + FileSystemObject::swap(); - inline - void FileMapping::removeObjectL() + //swap compare result + switch (cmpResult) { - cmpResult = FILE_RIGHT_SIDE_ONLY; - dataLeft = nullData(); + case DIR_LEFT_SIDE_ONLY: + cmpResult = DIR_RIGHT_SIDE_ONLY; + break; + case DIR_RIGHT_SIDE_ONLY: + cmpResult = DIR_LEFT_SIDE_ONLY; + break; + case DIR_EQUAL: + break; } +} + + +inline +void DirMapping::removeObjectL() +{ + cmpResult = DIR_RIGHT_SIDE_ONLY; + std::for_each(subFiles.begin(), subFiles.end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); + std::for_each(subDirs.begin(), subDirs.end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); +} + + +inline +void DirMapping::removeObjectR() +{ + cmpResult = DIR_LEFT_SIDE_ONLY; + std::for_each(subFiles.begin(), subFiles.end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); + std::for_each(subDirs.begin(), subDirs.end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); +} + + +inline +void DirMapping::copyToL() +{ + cmpResult = DIR_EQUAL; +} + + +inline +void DirMapping::copyToR() +{ + cmpResult = DIR_EQUAL; +} + + +inline +const BaseDirMapping::FilterSettings& BaseDirMapping::getFilter() const +{ + return filter; +} + + +template <SelectedSide side> +inline +Zstring BaseDirMapping::getDBFilename() const +{ + return getBaseDir<side>() + getSyncDBFilename(); +} - inline - void FileMapping::removeObjectR() +inline +void FileMapping::swap() +{ + //call base class version + FileSystemObject::swap(); + + //swap compare result + switch (cmpResult) { + case FILE_LEFT_SIDE_ONLY: + cmpResult = FILE_RIGHT_SIDE_ONLY; + break; + case FILE_RIGHT_SIDE_ONLY: cmpResult = FILE_LEFT_SIDE_ONLY; - dataRight = nullData(); - } + break; + case FILE_LEFT_NEWER: + cmpResult = FILE_RIGHT_NEWER; + break; + case FILE_RIGHT_NEWER: + cmpResult = FILE_LEFT_NEWER; + break; + case FILE_DIFFERENT: + case FILE_EQUAL: + case FILE_CONFLICT: + break; + } + + std::swap(dataLeft, dataRight); +} - inline - void FileMapping::copyToL() - { - cmpResult = FILE_EQUAL; - dataLeft = dataRight; - } +template <CompareFilesResult res> +inline +void FileMapping::setCategory() +{ + cmpResult = res; +} +template <> +inline +void FileMapping::setCategory<FILE_CONFLICT>(); //if conflict is detected, use setCategoryConflict! => method is not defined! - inline - void FileMapping::copyToR() - { - cmpResult = FILE_EQUAL; - dataRight = dataLeft; - } +inline +void FileMapping::setCategoryConflict(const wxString& description) +{ + cmpResult = FILE_CONFLICT; + cmpConflictDescr = description; +} - inline - const FileDescriptor& FileMapping::nullData() - { - static FileDescriptor output(Zstring(), 0, 0); - return output; - } +inline +void FileMapping::removeObjectL() +{ + cmpResult = FILE_RIGHT_SIDE_ONLY; + dataLeft = FileDescriptor(0, 0); +} - inline - const Zstring& FileMapping::getShortNameL() const - { - return dataLeft.shortName; - } +inline +void FileMapping::removeObjectR() +{ + cmpResult = FILE_LEFT_SIDE_ONLY; + dataRight = FileDescriptor(0, 0); +} - inline - const Zstring& FileMapping::getShortNameR() const - { - return dataRight.shortName; - } +inline +void FileMapping::copyToL() +{ + cmpResult = FILE_EQUAL; + dataLeft = dataRight; +} - inline - bool FileMapping::isEmptyL() const - { - return dataLeft.shortName.empty(); - } +inline +void FileMapping::copyToR() +{ + cmpResult = FILE_EQUAL; + dataRight = dataLeft; +} - inline - bool FileMapping::isEmptyR() const - { - return dataRight.shortName.empty(); - } +template <> +inline +const wxLongLong& FileMapping::getLastWriteTime<LEFT_SIDE>() const +{ + return dataLeft.lastWriteTimeRaw; +} - template <SelectedSide side> - inline - const wxLongLong& FileMapping::getLastWriteTime() const - { - return side == LEFT_SIDE ? dataLeft.lastWriteTimeRaw : dataRight.lastWriteTimeRaw; - } + +template <> +inline +const wxLongLong& FileMapping::getLastWriteTime<RIGHT_SIDE>() const +{ + return dataRight.lastWriteTimeRaw; +} - template <SelectedSide side> - inline - const wxULongLong& FileMapping::getFileSize() const - { - return side == LEFT_SIDE ? dataLeft.fileSize : dataRight.fileSize; - } +template <> +inline +const wxULongLong& FileMapping::getFileSize<LEFT_SIDE>() const +{ + return dataLeft.fileSize; +} + + +template <> +inline +const wxULongLong& FileMapping::getFileSize<RIGHT_SIDE>() const +{ + return dataRight.fileSize; +} } #endif // FILEHIERARCHY_H_INCLUDED diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp index e2384526..fdb26eb5 100644 --- a/library/CustomGrid.cpp +++ b/library/CustomGrid.cpp @@ -2,7 +2,9 @@ #include "../shared/systemConstants.h" #include "resources.h" #include <wx/dc.h> -#include "../algorithm.h" +//#include "../algorithm.h" +#include "../ui/util.h" +#include "../shared/stringConv.h" #include "resources.h" #include <typeinfo> #include "../ui/gridView.h" @@ -44,18 +46,18 @@ class CustomGridTable : public wxGridTableBase { public: CustomGridTable(int initialRows = 0, int initialCols = 0) : //note: initialRows/initialCols MUST match with GetNumberRows()/GetNumberCols() at initialization!!! - wxGridTableBase(), - COLOR_BLUE( 80, 110, 255), - COLOR_GREY( 212, 208, 200), - COLOR_CMP_RED( 249, 163, 165), - COLOR_CMP_BLUE( 144, 232, 246), - COLOR_CMP_GREEN( 147, 253, 159), - COLOR_SYNC_BLUE( 201, 203, 247), - COLOR_SYNC_GREEN(197, 248, 190), - COLOR_YELLOW( 247, 252, 62), - gridDataView(NULL), - lastNrRows(initialRows), - lastNrCols(initialCols) {} + wxGridTableBase(), + COLOR_BLUE( 80, 110, 255), + COLOR_GREY( 212, 208, 200), + COLOR_CMP_RED( 249, 163, 165), + COLOR_CMP_BLUE( 144, 232, 246), + COLOR_CMP_GREEN( 147, 253, 159), + COLOR_SYNC_BLUE( 201, 203, 247), + COLOR_SYNC_GREEN(197, 248, 190), + COLOR_YELLOW( 247, 252, 62), + gridDataView(NULL), + lastNrRows(initialRows), + lastNrCols(initialCols) {} virtual ~CustomGridTable() {} @@ -256,13 +258,13 @@ protected: switch (getTypeAtPos(col)) { case xmlAccess::FULL_PATH: - return dirObj->getFullName<side>().c_str(); + return zToWx(dirObj->getFullName<side>()); case xmlAccess::FILENAME: return wxEmptyString; case xmlAccess::REL_PATH: - return dirObj->getRelativeName<side>().c_str(); + return zToWx(dirObj->getRelativeName<side>()); case xmlAccess::DIRECTORY: - return dirObj->getBaseDirPf<side>().c_str(); + return zToWx(dirObj->getBaseDirPf<side>()); case xmlAccess::SIZE: //file size return _("<Directory>"); case xmlAccess::DATE: //date @@ -277,13 +279,13 @@ protected: switch (getTypeAtPos(col)) { case xmlAccess::FULL_PATH: - return fileObj->getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR).c_str(); + return zToWx(fileObj->getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR)); case xmlAccess::FILENAME: //filename - return fileObj->getShortName<side>().c_str(); + return zToWx(fileObj->getShortName<side>()); case xmlAccess::REL_PATH: //relative path - return fileObj->getParentRelativeName<side>().c_str(); + return zToWx(fileObj->getParentRelativeName()); case xmlAccess::DIRECTORY: - return fileObj->getBaseDirPf<side>().c_str(); + return zToWx(fileObj->getBaseDirPf<side>()); case xmlAccess::SIZE: //file size return FreeFileSync::includeNumberSeparator(fileObj->getFileSize<side>().ToString()); case xmlAccess::DATE: //date @@ -305,7 +307,7 @@ private: if (fsObj) { //mark filtered rows - if (!fsObj->selectedForSynchronization) + if (!fsObj->isActive()) return COLOR_BLUE; //mark directories else if (dynamic_cast<const DirMapping*>(fsObj) != NULL) @@ -364,8 +366,8 @@ class CustomGridTableMiddle : public CustomGridTable public: //middle grid is created (first wxWidgets internal call to GetNumberCols()) with one column CustomGridTableMiddle() : - CustomGridTable(0, GetNumberCols()), //attention: static binding to virtual GetNumberCols() in a Constructor! - syncPreviewActive(false) {} + CustomGridTable(0, GetNumberCols()), //attention: static binding to virtual GetNumberCols() in a Constructor! + syncPreviewActive(false) {} virtual int GetNumberCols() { @@ -383,7 +385,7 @@ public: if (fsObj) { if (syncPreviewActive) //synchronization preview - return getSymbol(getSyncOperation(*fsObj)); + return getSymbol(fsObj->getSyncOperation()); else return getSymbol(fsObj->getCategory()); } @@ -407,22 +409,25 @@ private: if (fsObj) { //mark filtered rows - if (!fsObj->selectedForSynchronization) + if (!fsObj->isActive()) return COLOR_BLUE; if (syncPreviewActive) //synchronization preview { - switch (fsObj->syncDir) + switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction { - case SYNC_DIR_LEFT: + case SO_CREATE_NEW_LEFT: + case SO_DELETE_LEFT: + case SO_OVERWRITE_LEFT: return COLOR_SYNC_BLUE; - case SYNC_DIR_RIGHT: + case SO_CREATE_NEW_RIGHT: + case SO_DELETE_RIGHT: + case SO_OVERWRITE_RIGHT: return COLOR_SYNC_GREEN; - case SYNC_DIR_NONE: - if (fsObj->getCategory() == FILE_CONFLICT) - return COLOR_YELLOW; - else - return *wxWHITE; + case SO_UNRESOLVED_CONFLICT: + return COLOR_YELLOW; + case SO_DO_NOTHING: + return *wxWHITE; } } else //comparison results view @@ -461,12 +466,12 @@ CustomGrid::CustomGrid(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - wxGrid(parent, id, pos, size, style, name), - m_gridLeft(NULL), - m_gridMiddle(NULL), - m_gridRight(NULL), - isLeading(false), - m_marker(-1, ASCENDING) + wxGrid(parent, id, pos, size, style, name), + m_gridLeft(NULL), + m_gridMiddle(NULL), + m_gridRight(NULL), + isLeading(false), + m_marker(-1, ASCENDING) { //set color of selections wxColour darkBlue(40, 35, 140); @@ -535,7 +540,8 @@ void CustomGrid::DoPrepareDC(wxDC& dc) inline void moveCursorWhileSelecting(const int anchor, const int oldPos, const int newPos, wxGrid* grid) -{ //note: all positions are valid in this context! +{ + //note: all positions are valid in this context! grid->SetGridCursor( newPos, grid->GetGridCursorCol()); grid->MakeCellVisible(newPos, grid->GetGridCursorCol()); @@ -921,8 +927,8 @@ class GridCellRenderer : public wxGridCellStringRenderer { public: GridCellRenderer(CustomGridRim::LoadSuccess& loadIconSuccess, const CustomGridTableRim* gridDataTable) : - m_loadIconSuccess(loadIconSuccess), - m_gridDataTable(gridDataTable) {} + m_loadIconSuccess(loadIconSuccess), + m_gridDataTable(gridDataTable) {} virtual void Draw(wxGrid& grid, @@ -1038,9 +1044,9 @@ CustomGridRim::CustomGridRim(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGrid(parent, id, pos, size, style, name) + CustomGrid(parent, id, pos, size, style, name) #ifdef FFS_WIN - , fileIconsAreEnabled(false) + , fileIconsAreEnabled(false) #endif {} @@ -1126,7 +1132,8 @@ void CustomGridRim::setColumnAttributes(const xmlAccess::ColumnAttributes& attr) columnSettings.clear(); if (attr.size() == 0) - { //default settings: + { + //default settings: columnSettings = getDefaultColumnAttributes(); } else @@ -1215,7 +1222,8 @@ wxString CustomGridRim::getTypeName(xmlAccess::ColumnTypes colType) CustomGridTableRim* CustomGridRim::getGridDataTable() -{ //let the non-const call the const version: see Meyers Effective C++ +{ + //let the non-const call the const version: see Meyers Effective C++ return const_cast<CustomGridTableRim*>(static_cast<const CustomGridRim*>(this)->getGridDataTable()); } @@ -1314,9 +1322,9 @@ void CustomGridRim::getIconsToBeLoaded(std::vector<Zstring>& newLoad) //loads al //update file icons periodically: use SINGLE instance to coordinate left and right grid at once IconUpdater::IconUpdater(CustomGridLeft* leftGrid, CustomGridRight* rightGrid) : - m_leftGrid(leftGrid), - m_rightGrid(rightGrid), - m_timer(new wxTimer) //connect timer event for async. icon loading + m_leftGrid(leftGrid), + m_rightGrid(rightGrid), + m_timer(new wxTimer) //connect timer event for async. icon loading { m_timer->Connect(wxEVT_TIMER, wxEventHandler(IconUpdater::loadIconsAsynchronously), NULL, this); m_timer->Start(50); //timer interval in ms @@ -1349,8 +1357,8 @@ CustomGridLeft::CustomGridLeft(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) {} + CustomGridRim(parent, id, pos, size, style, name), + gridDataTable(NULL) {} bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) @@ -1396,8 +1404,8 @@ CustomGridRight::CustomGridRight(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGridRim(parent, id, pos, size, style, name), - gridDataTable(NULL) {} + CustomGridRim(parent, id, pos, size, style, name), + gridDataTable(NULL) {} bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) @@ -1471,13 +1479,13 @@ CustomGridMiddle::CustomGridMiddle(wxWindow *parent, const wxSize& size, long style, const wxString& name) : - CustomGrid(parent, id, pos, size, style, name), - selectionRowBegin(-1), - selectionPos(BLOCKPOS_CHECK_BOX), - highlightedRow(-1), - highlightedPos(BLOCKPOS_CHECK_BOX), - gridDataTable(NULL), - toolTip(new CustomTooltip) + CustomGrid(parent, id, pos, size, style, name), + selectionRowBegin(-1), + selectionPos(BLOCKPOS_CHECK_BOX), + highlightedRow(-1), + highlightedPos(BLOCKPOS_CHECK_BOX), + gridDataTable(NULL), + toolTip(new CustomTooltip) { //connect events for dynamic selection of sync direction GetGridWindow()->Connect(wxEVT_MOTION, wxMouseEventHandler(CustomGridMiddle::OnMouseMovement), NULL, this); @@ -1564,7 +1572,7 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) if (gridDataTable->syncPreviewIsActive()) //synchronization preview { - const SyncOperation syncOp = getSyncOperation(*fsObj); + const SyncOperation syncOp = fsObj->getSyncOperation(); switch (syncOp) { case SO_CREATE_NEW_LEFT: @@ -1589,7 +1597,7 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) toolTip->show(getDescription(syncOp), pos, GlobalResources::getInstance().bitmapSyncDirNoneAct); break; case SO_UNRESOLVED_CONFLICT: - toolTip->show(fsObj->getConflictDescription(), pos, GlobalResources::getInstance().bitmapConflictAct); + toolTip->show(fsObj->getSyncOpConflict(), pos, GlobalResources::getInstance().bitmapConflictAct); break; }; } @@ -1617,7 +1625,7 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) toolTip->show(getDescription(cmpRes), pos, GlobalResources::getInstance().bitmapEqualAct); break; case FILE_CONFLICT: - toolTip->show(fsObj->getConflictDescription(), pos, GlobalResources::getInstance().bitmapConflictAct); + toolTip->show(fsObj->getCatConflict(), pos, GlobalResources::getInstance().bitmapConflictAct); break; } } @@ -1761,13 +1769,13 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, //HIGHLIGHTNING: if (rowIsHighlighted && m_gridMiddle->highlightedPos == CustomGridMiddle::BLOCKPOS_CHECK_BOX) { - if (fsObj->selectedForSynchronization) + if (fsObj->isActive()) dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxTrueFocus, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); else dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxFalseFocus, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); } //default - else if (fsObj->selectedForSynchronization) + else if (fsObj->isActive()) dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); else dc.DrawLabel(wxEmptyString, *GlobalResources::getInstance().bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); @@ -1789,18 +1797,18 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, case CustomGridMiddle::BLOCKPOS_CHECK_BOX: break; case CustomGridMiddle::BLOCKPOS_LEFT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_LEFT), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_LEFT)), rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); break; case CustomGridMiddle::BLOCKPOS_MIDDLE: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_NONE), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_NONE)), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); break; case CustomGridMiddle::BLOCKPOS_RIGHT: - dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_RIGHT), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + dc.DrawLabel(wxEmptyString, getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT)), rectShrinked, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); break; } else //default { - const wxBitmap& syncOpIcon = getSyncOpImage(fsObj->getCategory(), fsObj->selectedForSynchronization, fsObj->syncDir); + const wxBitmap& syncOpIcon = getSyncOpImage(fsObj->getSyncOperation()); dc.DrawLabel(wxEmptyString, syncOpIcon, rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); } } @@ -1865,11 +1873,9 @@ void CustomGridMiddle::DrawColLabel(wxDC& dc, int col) } -const wxBitmap& FreeFileSync::getSyncOpImage(const CompareFilesResult cmpResult, - const bool selectedForSynchronization, - const SyncDirection syncDir) +const wxBitmap& FreeFileSync::getSyncOpImage(SyncOperation syncOp) { - switch (getSyncOperation(cmpResult, selectedForSynchronization, syncDir)) //evaluate comparison result and sync direction + switch (syncOp) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: return *GlobalResources::getInstance().bitmapCreateLeftSmall; diff --git a/library/CustomGrid.h b/library/CustomGrid.h index 08ec5f55..59bc97c0 100644 --- a/library/CustomGrid.h +++ b/library/CustomGrid.h @@ -23,11 +23,9 @@ class CustomGridRight; namespace FreeFileSync { - class GridView; +class GridView; - const wxBitmap& getSyncOpImage(const CompareFilesResult cmpResult, - const bool selectedForSynchronization, - const SyncDirection syncDir); +const wxBitmap& getSyncOpImage(SyncOperation syncOp); } //################################################################################## @@ -299,9 +297,9 @@ class FFSCheckRowsEvent : public wxCommandEvent { public: FFSCheckRowsEvent(const int from, const int to) : - wxCommandEvent(FFS_CHECK_ROWS_EVENT), - rowFrom(from), - rowTo(to) {} + wxCommandEvent(FFS_CHECK_ROWS_EVENT), + rowFrom(from), + rowTo(to) {} virtual wxEvent* Clone() const { @@ -326,10 +324,10 @@ class FFSSyncDirectionEvent : public wxCommandEvent { public: FFSSyncDirectionEvent(const int from, const int to, const FreeFileSync::SyncDirection dir) : - wxCommandEvent(FFS_SYNC_DIRECTION_EVENT), - rowFrom(from), - rowTo(to), - direction(dir) {} + wxCommandEvent(FFS_SYNC_DIRECTION_EVENT), + rowFrom(from), + rowTo(to), + direction(dir) {} virtual wxEvent* Clone() const { diff --git a/library/SyncDB.ico b/library/SyncDB.ico Binary files differnew file mode 100644 index 00000000..e70a3a16 --- /dev/null +++ b/library/SyncDB.ico diff --git a/library/errorLogging.h b/library/errorLogging.h index 5fc5dacd..7b2b32c1 100644 --- a/library/errorLogging.h +++ b/library/errorLogging.h @@ -8,36 +8,36 @@ class Zstring; namespace FreeFileSync { - class ErrorLogging +class ErrorLogging +{ +public: + ErrorLogging() : errorCount(0) {} + + void logError(const wxString& errorMessage); + void logWarning(const wxString& warningMessage); + void logInfo(const wxString& infoMessage); + + int errorsTotal() + { + return errorCount; + } + + const std::vector<wxString>& getFormattedMessages() { - public: - ErrorLogging() : errorCount(0) {} - - void logError(const wxString& errorMessage); - void logWarning(const wxString& warningMessage); - void logInfo(const wxString& infoMessage); - - int errorsTotal() - { - return errorCount; - } - - const std::vector<wxString>& getFormattedMessages() - { - return formattedMessages; - } - - size_t messageCount() - { - return formattedMessages.size(); - } - - private: - wxString assembleMessage(const wxString& prefix, const wxString& message); - - std::vector<wxString> formattedMessages; //list of non-resolved errors and warnings - int errorCount; - }; + return formattedMessages; + } + + size_t messageCount() + { + return formattedMessages.size(); + } + +private: + wxString assembleMessage(const wxString& prefix, const wxString& message); + + std::vector<wxString> formattedMessages; //list of non-resolved errors and warnings + int errorCount; +}; } #endif // ERRORLOGGING_H_INCLUDED diff --git a/library/filter.cpp b/library/filter.cpp index 30cd9341..c2d972d4 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -22,14 +22,16 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st //Linux DOES distinguish between upper/lower-case: nothing to do here #endif - static const Zstring sepAsterisk = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + wxT('*'); - static const Zstring sepQuestionMark = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + wxT('?'); - static const Zstring asteriskSep = Zstring(wxT("*")) + globalFunctions::FILE_NAME_SEPARATOR; - static const Zstring questionMarkSep = Zstring(wxT("?")) + globalFunctions::FILE_NAME_SEPARATOR; + static const Zstring sepAsterisk = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + DefaultChar('*'); + static const Zstring sepQuestionMark = Zstring() + globalFunctions::FILE_NAME_SEPARATOR + DefaultChar('?'); + static const Zstring asteriskSep = Zstring(DefaultStr("*")) + globalFunctions::FILE_NAME_SEPARATOR; + static const Zstring questionMarkSep = Zstring(DefaultStr("?")) + globalFunctions::FILE_NAME_SEPARATOR; +//-------------------------------------------------------------------------------------------------- //add some syntactic sugar: handle beginning of filtername if (filterFormatted.StartsWith(globalFunctions::FILE_NAME_SEPARATOR)) - { //remove leading separators (keep BEFORE test for Zstring::empty()!) + { + //remove leading separators (keep BEFORE test for Zstring::empty()!) filterFormatted = filterFormatted.AfterFirst(globalFunctions::FILE_NAME_SEPARATOR); } else if (filterFormatted.StartsWith(asteriskSep) || // *\abc @@ -38,7 +40,7 @@ void addFilterEntry(const Zstring& filtername, std::set<Zstring>& fileFilter, st addFilterEntry(Zstring(filterFormatted.c_str() + 1), fileFilter, directoryFilter); //prevent further recursion by prefix } - +//-------------------------------------------------------------------------------------------------- //even more syntactic sugar: handle end of filtername if (filterFormatted.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) { @@ -150,14 +152,14 @@ std::vector<Zstring> compoundStringToFilter(const Zstring& filterString) //############################################################## -FilterProcess::FilterProcess(const wxString& includeFilter, const wxString& excludeFilter) +FilterProcess::FilterProcess(const Zstring& includeFilter, const Zstring& excludeFilter) { //no need for regular expressions! In tests wxRegex was by factor of 10 slower than wxString::Matches()!! //load filter into vectors of strings //delimiters may be ';' or '\n' - const std::vector<Zstring> includeList = compoundStringToFilter(includeFilter.c_str()); - const std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter.c_str()); + const std::vector<Zstring> includeList = compoundStringToFilter(includeFilter); + const std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter); //setup include/exclude filters for files and directories std::for_each(includeList.begin(), includeList.end(), boost::bind(addFilterEntry, _1, boost::ref(filterFileIn), boost::ref(filterFolderIn))); @@ -199,101 +201,110 @@ bool FilterProcess::passDirFilter(const DefaultChar* relDirname, bool* subObjMig } -class FilterData +template <bool include> +class InOrExcludeAllRows { public: - FilterData(const FilterProcess& filterProcIn) : filterProc(filterProcIn) {} - - void operator()(FreeFileSync::FileMapping& fileObj) + void operator()(FreeFileSync::BaseDirMapping& baseDirectory) const //be careful with operator() to no get called by std::for_each! { - const Zstring relName = fileObj.isEmpty<FreeFileSync::LEFT_SIDE>() ? - fileObj.getRelativeName<FreeFileSync::RIGHT_SIDE>() : - fileObj.getRelativeName<FreeFileSync::LEFT_SIDE>(); - - fileObj.selectedForSynchronization = filterProc.passFileFilter(relName); + execute(baseDirectory); } - void operator()(FreeFileSync::DirMapping& dirObj) + void execute(FreeFileSync::HierarchyObject& hierObj) const //don't create ambiguity by replacing with operator() { - const Zstring relName = dirObj.isEmpty<FreeFileSync::LEFT_SIDE>() ? - dirObj.getRelativeName<FreeFileSync::RIGHT_SIDE>() : - dirObj.getRelativeName<FreeFileSync::LEFT_SIDE>(); + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); //files + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); //directories + } - bool subObjMightMatch = true; - dirObj.selectedForSynchronization = filterProc.passDirFilter(relName, &subObjMightMatch); +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); - if (subObjMightMatch) //use same logic like directory traversing here: evaluate filter in subdirs only if objects could match - filterProc.filterAll(dirObj); //process sub-dirs/files - else - FilterProcess::setActiveStatus(false, dirObj); //exclude all files dirs in subfolders + void operator()(FreeFileSync::FileMapping& fileObj) const + { + fileObj.setActive(include); } -private: - const FilterProcess& filterProc; + void operator()(FreeFileSync::DirMapping& dirObj) const + { + dirObj.setActive(include); + execute(dirObj); //recursion + } }; -void FilterProcess::filterAll(FreeFileSync::HierarchyObject& baseDirectory) const +class FilterData { - //files - std::for_each(baseDirectory.subFiles.begin(), baseDirectory.subFiles.end(), FilterData(*this)); +public: + FilterData(const FilterProcess& filterProcIn) : filterProc(filterProcIn) {} - //directories - std::for_each(baseDirectory.subDirs.begin(), baseDirectory.subDirs.end(), FilterData(*this)); + void execute(FreeFileSync::HierarchyObject& hierObj) + { + //files + std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); - //recursion happens in FilterData -} + //directories + std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); + }; +private: + template<typename Iterator, typename Function> + friend Function std::for_each(Iterator, Iterator, Function); -template <bool include> -struct SetSelected -{ - void operator()(FreeFileSync::FileSystemObject& fsObj) const + + void operator()(FreeFileSync::FileMapping& fileObj) + { + fileObj.setActive(filterProc.passFileFilter(fileObj.getObjRelativeName())); + } + + void operator()(FreeFileSync::DirMapping& dirObj) { - fsObj.selectedForSynchronization = include; + bool subObjMightMatch = true; + dirObj.setActive(filterProc.passDirFilter(dirObj.getObjRelativeName(), &subObjMightMatch)); + + if (subObjMightMatch) //use same logic as within directory traversing here: evaluate filter in subdirs only if objects could match + execute(dirObj); //recursion + else + InOrExcludeAllRows<false>().execute(dirObj); //exclude all files dirs in subfolders } + + const FilterProcess& filterProc; }; -template <bool include> -void inOrExcludeAllRows(FreeFileSync::HierarchyObject& hierObj) +void FilterProcess::filterAll(FreeFileSync::HierarchyObject& baseDirectory) const { - //directories - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), SetSelected<include>()); - //files - std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), SetSelected<include>()); - //recurse into sub-dirs - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), inOrExcludeAllRows<include>); + FilterData(*this).execute(baseDirectory); } void FilterProcess::setActiveStatus(bool newStatus, FreeFileSync::FolderComparison& folderCmp) { if (newStatus) - std::for_each(folderCmp.begin(), folderCmp.end(), inOrExcludeAllRows<true>); //include all rows + std::for_each(folderCmp.begin(), folderCmp.end(), InOrExcludeAllRows<true>()); //include all rows else - std::for_each(folderCmp.begin(), folderCmp.end(), inOrExcludeAllRows<false>); //exclude all rows + std::for_each(folderCmp.begin(), folderCmp.end(), InOrExcludeAllRows<false>()); //exclude all rows } void FilterProcess::setActiveStatus(bool newStatus, FreeFileSync::FileSystemObject& fsObj) { - fsObj.selectedForSynchronization = newStatus; + fsObj.setActive(newStatus); DirMapping* dirObj = dynamic_cast<DirMapping*>(&fsObj); if (dirObj) //process subdirectories also! { if (newStatus) - inOrExcludeAllRows<true>(*dirObj); + InOrExcludeAllRows<true>().execute(*dirObj); else - inOrExcludeAllRows<false>(*dirObj); + InOrExcludeAllRows<false>().execute(*dirObj); } } const FilterProcess& FilterProcess::nullFilter() //filter equivalent to include '*', exclude '' { - static FilterProcess output(wxT("*"), wxEmptyString); + static FilterProcess output(DefaultStr("*"), Zstring()); return output; } @@ -329,4 +340,3 @@ bool FilterProcess::operator<(const FilterProcess& other) const return false; //vectors equal } - diff --git a/library/filter.h b/library/filter.h index 0adf81cd..45aff69b 100644 --- a/library/filter.h +++ b/library/filter.h @@ -1,7 +1,6 @@ #ifndef FFS_FILTER_H_INCLUDED #define FFS_FILTER_H_INCLUDED -#include <wx/string.h> #include "../shared/zstring.h" #include <set> #include "../fileHierarchy.h" @@ -9,30 +8,30 @@ namespace FreeFileSync { - class FilterProcess //relative filtering - { - public: - FilterProcess(const wxString& includeFilter, const wxString& excludeFilter); - - bool passFileFilter(const DefaultChar* relFilename) const; - bool passDirFilter(const DefaultChar* relDirname, bool* subObjMightMatch) const; //subObjMightMatch: file/dir in subdirectories could(!) match - //note: variable is only set if passDirFilter returns false! - void filterAll(HierarchyObject& baseDirectory) const; //filter complete data: files and dirs - - static void setActiveStatus(bool newStatus, FolderComparison& folderCmp); //activate or deactivate all rows - static void setActiveStatus(bool newStatus, FileSystemObject& fsObj); //activate or deactivate row - - static const FilterProcess& nullFilter(); //filter equivalent to include '*', exclude '' - bool operator==(const FilterProcess& other) const; - bool operator!=(const FilterProcess& other) const; - bool operator<(const FilterProcess& other) const; - - private: - std::set<Zstring> filterFileIn; - std::set<Zstring> filterFolderIn; - std::set<Zstring> filterFileEx; - std::set<Zstring> filterFolderEx; - }; +class FilterProcess //relative filtering +{ +public: + FilterProcess(const Zstring& includeFilter, const Zstring& excludeFilter); + + bool passFileFilter(const DefaultChar* relFilename) const; + bool passDirFilter(const DefaultChar* relDirname, bool* subObjMightMatch) const; //subObjMightMatch: file/dir in subdirectories could(!) match + //note: variable is only set if passDirFilter returns false! + void filterAll(HierarchyObject& baseDirectory) const; //filter complete data: files and dirs + + static void setActiveStatus(bool newStatus, FolderComparison& folderCmp); //activate or deactivate all rows + static void setActiveStatus(bool newStatus, FileSystemObject& fsObj); //activate or deactivate row: works recursively! + + static const FilterProcess& nullFilter(); //filter equivalent to include '*', exclude '' + bool operator==(const FilterProcess& other) const; + bool operator!=(const FilterProcess& other) const; + bool operator<(const FilterProcess& other) const; + +private: + std::set<Zstring> filterFileIn; + std::set<Zstring> filterFolderIn; + std::set<Zstring> filterFileEx; + std::set<Zstring> filterFolderEx; +}; } diff --git a/library/iconBuffer.cpp b/library/iconBuffer.cpp index cf21104e..2f1e2915 100644 --- a/library/iconBuffer.cpp +++ b/library/iconBuffer.cpp @@ -45,12 +45,12 @@ private: WorkerThread::WorkerThread(IconBuffer* iconBuff) : - wxThread(wxTHREAD_JOINABLE), - threadHasMutex(false), - threadExitIsRequested(false), - threadIsListening(), - continueWork(threadIsListening), - iconBuffer(iconBuff) + wxThread(wxTHREAD_JOINABLE), + threadHasMutex(false), + threadExitIsRequested(false), + threadIsListening(), + continueWork(threadIsListening), + iconBuffer(iconBuff) { if (Create() != wxTHREAD_NO_ERROR) throw std::runtime_error("Error creating icon buffer worker thread!"); @@ -98,7 +98,8 @@ wxThread::ExitCode WorkerThread::Entry() try { wxMutexLocker dummy(threadIsListening); //this lock needs to be called from WITHIN the thread => calling it from constructor(Main thread) would be useless - { //this mutex STAYS locked all the time except of continueWork.Wait()! + { + //this mutex STAYS locked all the time except of continueWork.Wait()! wxCriticalSectionLocker dummy2(lockWorkload); threadHasMutex = true; } @@ -117,7 +118,7 @@ wxThread::ExitCode WorkerThread::Entry() } catch (const std::exception& e) //exceptions must be catched per thread { - wxMessageBox(wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + wxMessageBox(wxString::FromAscii(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); return 0; } } @@ -162,7 +163,8 @@ void WorkerThread::doWork() SHGFI_ICON | SHGFI_SMALLICON) && fileInfo.hIcon != 0) //fix for weird error: SHGetFileInfo() might return successfully WITHOUT filling fileInfo.hIcon!! - { //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080 + { + //bug report: https://sourceforge.net/tracker/?func=detail&aid=2768004&group_id=234430&atid=1093080 wxIcon newIcon; //attention: wxIcon uses reference counting! newIcon.SetHICON(fileInfo.hIcon); @@ -198,10 +200,10 @@ IconBuffer& IconBuffer::getInstance() IconBuffer::IconBuffer() : - lockIconDB( new wxCriticalSection), - buffer( new IconDB), - bufSequence(new IconDbSequence), - worker( new WorkerThread(this)) //might throw exceptions! + lockIconDB( new wxCriticalSection), + buffer( new IconDB), + bufSequence(new IconDbSequence), + worker( new WorkerThread(this)) //might throw exceptions! {} diff --git a/library/iconBuffer.h b/library/iconBuffer.h index f62a2772..0604060e 100644 --- a/library/iconBuffer.h +++ b/library/iconBuffer.h @@ -18,34 +18,34 @@ class wxIcon; namespace FreeFileSync { - class IconBuffer - { - friend class ::WorkerThread; +class IconBuffer +{ + friend class ::WorkerThread; - public: - static IconBuffer& getInstance(); +public: + static IconBuffer& getInstance(); - bool requestIcon(const Zstring& fileName, wxIcon* icon = NULL); //returns false if icon is not in buffer - void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved; + bool requestIcon(const Zstring& fileName, wxIcon* icon = NULL); //returns false if icon is not in buffer + void setWorkload(const std::vector<Zstring>& load); //(re-)set new workload of icons to be retrieved; - static const int ICON_SIZE = 16; //size in pixel + static const int ICON_SIZE = 16; //size in pixel - private: - IconBuffer(); - ~IconBuffer(); +private: + IconBuffer(); + ~IconBuffer(); - //methods used by worker thread - void insertIntoBuffer(const DefaultChar* fileName, const wxIcon& icon); + //methods used by worker thread + void insertIntoBuffer(const DefaultChar* fileName, const wxIcon& icon); //---------------------- Shared Data ------------------------- - std::auto_ptr<wxCriticalSection> lockIconDB; - std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this! + std::auto_ptr<wxCriticalSection> lockIconDB; + std::auto_ptr<IconDB> buffer; //use synchronisation when accessing this! //------------------------------------------------------------ - std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delte olderst elements + std::auto_ptr<IconDbSequence> bufSequence; //save sequence of buffer entry to delte olderst elements - std::auto_ptr<WorkerThread> worker; - }; + std::auto_ptr<WorkerThread> worker; +}; } #endif // ICONBUFFER_H_INCLUDED diff --git a/library/multithreading.cpp b/library/multithreading.cpp index 899a426b..aea4821b 100644 --- a/library/multithreading.cpp +++ b/library/multithreading.cpp @@ -40,12 +40,12 @@ class WorkerThread : public wxThread public: WorkerThread(UpdateWhileExecuting* handler) : - wxThread(wxTHREAD_DETACHED), - readyToBeginProcessing(), - beginProcessing(readyToBeginProcessing), - threadIsInitialized(false), - threadExitIsRequested(false), - threadHandler(handler) + wxThread(wxTHREAD_DETACHED), + readyToBeginProcessing(), + beginProcessing(readyToBeginProcessing), + threadIsInitialized(false), + threadExitIsRequested(false), + threadHandler(handler) { } @@ -93,9 +93,9 @@ private: UpdateWhileExecuting::UpdateWhileExecuting() : - readyToReceiveResult(), - receivingResult(readyToReceiveResult), - workDone(false) + readyToReceiveResult(), + receivingResult(readyToReceiveResult), + workDone(false) { //mutex needs to be initially locked for condition receivingResult to work properly readyToReceiveResult.Lock(); diff --git a/library/processXml.cpp b/library/processXml.cpp index e49e0b35..b248cf62 100644 --- a/library/processXml.cpp +++ b/library/processXml.cpp @@ -5,12 +5,14 @@ #include "../shared/globalFunctions.h" #include "../shared/fileHandling.h" #include "../shared/standardPaths.h" +#include "../shared/stringConv.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" #endif using namespace FreeFileSync; +using namespace xmlAccess; //functionally needed!!! class FfsXmlParser : public xmlAccess::XmlParser @@ -161,17 +163,17 @@ bool readXmlElement(const std::string& name, const TiXmlElement* parent, Compare } -bool readXmlElement(const std::string& name, const TiXmlElement* parent, SyncDirectionCfg& output) +bool readXmlElement(const std::string& name, const TiXmlElement* parent, SyncDirection& output) { std::string dummy; if (xmlAccess::readXmlElement(name, parent, dummy)) { if (dummy == "left") - output = SYNC_DIR_CFG_LEFT; + output = SYNC_DIR_LEFT; else if (dummy == "right") - output = SYNC_DIR_CFG_RIGHT; + output = SYNC_DIR_RIGHT; else //treat all other input as "none" - output = SYNC_DIR_CFG_NONE; + output = SYNC_DIR_NONE; return true; } @@ -226,7 +228,7 @@ bool readXmlElement(const std::string& name, const TiXmlElement* parent, Zstring if (!xmlAccess::readXmlElement(name, parent, dummy)) return false; - output = dummy.c_str(); + output = wxToZ(dummy); return true; } @@ -254,15 +256,17 @@ void FfsXmlParser::readXmlAlternateConfig(const TiXmlElement& folderPair, Folder //########################################################### //alternate sync configuration - const TiXmlElement* syncConfig = TiXmlHandleConst(&folderPair).FirstChild("AlternateSyncConfig").ToElement(); - if (syncConfig) + const TiXmlElement* altSyncConfig = TiXmlHandleConst(&folderPair).FirstChild("AlternateSyncConfig").ToElement(); + if (altSyncConfig) { AlternateSyncConfig* altSyncCfg = new AlternateSyncConfig; enhPair.altSyncConfig.reset(altSyncCfg); - const TiXmlElement* syncDirections = TiXmlHandleConst(syncConfig).FirstChild("Synchronization").FirstChild("Directions").ToElement(); + const TiXmlElement* syncCfg = TiXmlHandleConst(altSyncConfig).FirstChild("Synchronization").ToElement(); + const TiXmlElement* syncDirections = TiXmlHandleConst(syncCfg).FirstChild("Directions").ToElement(); //read sync configuration + readXmlElementLogging("Automatic", syncCfg, altSyncCfg->syncConfiguration.automatic); readXmlElementLogging("LeftOnly", syncDirections, altSyncCfg->syncConfiguration.exLeftSideOnly); readXmlElementLogging("RightOnly", syncDirections, altSyncCfg->syncConfiguration.exRightSideOnly); readXmlElementLogging("LeftNewer", syncDirections, altSyncCfg->syncConfiguration.leftNewer); @@ -307,9 +311,11 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) readXmlElementLogging("TraverseDirectorySymlinks", cmpSettings, mainCfg.hidden.traverseDirectorySymlinks); //########################################################### - const TiXmlElement* syncDirections = hRoot.FirstChild("MainConfig").FirstChild("Synchronization").FirstChild("Directions").ToElement(); + const TiXmlElement* syncCfg = hRoot.FirstChild("MainConfig").FirstChild("Synchronization").ToElement(); + const TiXmlElement* syncDirections = TiXmlHandleConst(syncCfg).FirstChild("Directions").ToElement(); //read sync configuration + readXmlElementLogging("Automatic", syncCfg, mainCfg.syncConfiguration.automatic); readXmlElementLogging("LeftOnly", syncDirections, mainCfg.syncConfiguration.exLeftSideOnly); readXmlElementLogging("RightOnly", syncDirections, mainCfg.syncConfiguration.exRightSideOnly); readXmlElementLogging("LeftNewer", syncDirections, mainCfg.syncConfiguration.leftNewer); @@ -350,6 +356,9 @@ void FfsXmlParser::readXmlMainConfig(MainConfiguration& mainCfg) readXmlElementLogging("Right", pairs, mainCfg.mainFolderPair.rightDirectory); pairs = pairs->NextSiblingElement(); } + else + logError("Pair"); + //read additional folder pairs mainCfg.additionalPairs.clear(); @@ -422,6 +431,8 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //check for unresolved conflicts readXmlElementLogging("CheckForUnresolvedConflicts", optionalDialogs, outputCfg.optDialogs.warningUnresolvedConflicts); + readXmlElementLogging("CheckSyncDatabase", optionalDialogs, outputCfg.optDialogs.warningSyncDatabase); + readXmlElementLogging("PopupOnConfigChange", optionalDialogs, outputCfg.optDialogs.popupOnConfigChange); readXmlElementLogging("SummaryBeforeSync", optionalDialogs, outputCfg.optDialogs.showSummaryBeforeSync); @@ -450,7 +461,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg unsigned int colPos = 0; while (leftColumn) { - xmlAccess::ColumnAttrib newAttrib; + ColumnAttrib newAttrib; newAttrib.position = colPos++; readXmlAttributeLogging("Type", leftColumn, newAttrib.type); readXmlAttributeLogging("Visible", leftColumn, newAttrib.visible); @@ -466,7 +477,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg colPos = 0; while (rightColumn) { - xmlAccess::ColumnAttrib newAttrib; + ColumnAttrib newAttrib; newAttrib.position = colPos++; readXmlAttributeLogging("Type", rightColumn, newAttrib.type); readXmlAttributeLogging("Visible", rightColumn, newAttrib.visible); @@ -543,17 +554,17 @@ void addXmlElement(const std::string& name, const CompareVariant variant, TiXmlE } -void addXmlElement(const std::string& name, const SyncDirectionCfg value, TiXmlElement* parent) +void addXmlElement(const std::string& name, const SyncDirection value, TiXmlElement* parent) { switch (value) { - case SYNC_DIR_CFG_LEFT: + case SYNC_DIR_LEFT: xmlAccess::addXmlElement(name, std::string("left"), parent); break; - case SYNC_DIR_CFG_RIGHT: + case SYNC_DIR_RIGHT: xmlAccess::addXmlElement(name, std::string("right"), parent); break; - case SYNC_DIR_CFG_NONE: + case SYNC_DIR_NONE: xmlAccess::addXmlElement(name, std::string("none"), parent); break; } @@ -596,7 +607,7 @@ void addXmlElement(const std::string& name, const FreeFileSync::DeletionPolicy v void addXmlElement(const std::string& name, const Zstring& value, TiXmlElement* parent) { - xmlAccess::addXmlElement(name, wxString(value.c_str()), parent); + xmlAccess::addXmlElement(name, wxString(zToWx(value)), parent); } @@ -627,15 +638,17 @@ void writeXmlAlternateConfig(const FolderPairEnh& enhPair, TiXmlElement& parent) syncCfg->LinkEndChild(syncSettings); //write sync configuration + addXmlElement("Automatic", altSyncConfig->syncConfiguration.automatic, syncSettings); + TiXmlElement* syncDirections = new TiXmlElement("Directions"); syncSettings->LinkEndChild(syncDirections); - ::addXmlElement("LeftOnly", altSyncConfig->syncConfiguration.exLeftSideOnly, syncDirections); - ::addXmlElement("RightOnly", altSyncConfig->syncConfiguration.exRightSideOnly, syncDirections); - ::addXmlElement("LeftNewer", altSyncConfig->syncConfiguration.leftNewer, syncDirections); - ::addXmlElement("RightNewer", altSyncConfig->syncConfiguration.rightNewer, syncDirections); - ::addXmlElement("Different", altSyncConfig->syncConfiguration.different, syncDirections); - ::addXmlElement("Conflict", altSyncConfig->syncConfiguration.conflict, syncDirections); + addXmlElement("LeftOnly", altSyncConfig->syncConfiguration.exLeftSideOnly, syncDirections); + addXmlElement("RightOnly", altSyncConfig->syncConfiguration.exRightSideOnly, syncDirections); + addXmlElement("LeftNewer", altSyncConfig->syncConfiguration.leftNewer, syncDirections); + addXmlElement("RightNewer", altSyncConfig->syncConfiguration.rightNewer, syncDirections); + addXmlElement("Different", altSyncConfig->syncConfiguration.different, syncDirections); + addXmlElement("Conflict", altSyncConfig->syncConfiguration.conflict, syncDirections); TiXmlElement* miscSettings = new TiXmlElement("Miscellaneous"); @@ -643,7 +656,7 @@ void writeXmlAlternateConfig(const FolderPairEnh& enhPair, TiXmlElement& parent) //misc addXmlElement("DeletionPolicy", altSyncConfig->handleDeletion, miscSettings); - xmlAccess::addXmlElement("CustomDeletionFolder", altSyncConfig->customDeletionDirectory, miscSettings); + addXmlElement("CustomDeletionFolder", altSyncConfig->customDeletionDirectory, miscSettings); } //########################################################### @@ -655,8 +668,8 @@ void writeXmlAlternateConfig(const FolderPairEnh& enhPair, TiXmlElement& parent) newfolderPair->LinkEndChild(filterCfg); //write filter settings - xmlAccess::addXmlElement("Include", altFilter->includeFilter, filterCfg); - xmlAccess::addXmlElement("Exclude", altFilter->excludeFilter, filterCfg); + addXmlElement("Include", altFilter->includeFilter, filterCfg); + addXmlElement("Exclude", altFilter->excludeFilter, filterCfg); } } @@ -679,35 +692,37 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) settings->LinkEndChild(cmpSettings); //write compare algorithm - ::addXmlElement("Variant", mainCfgLocal.compareVar, cmpSettings); + addXmlElement("Variant", mainCfgLocal.compareVar, cmpSettings); //max. allowed file time deviation - xmlAccess::addXmlElement("FileTimeTolerance", mainCfgLocal.hidden.fileTimeTolerance, cmpSettings); + addXmlElement("FileTimeTolerance", mainCfgLocal.hidden.fileTimeTolerance, cmpSettings); //traverse into symbolic links (to folders) - xmlAccess::addXmlElement("TraverseDirectorySymlinks", mainCfgLocal.hidden.traverseDirectorySymlinks, cmpSettings); + addXmlElement("TraverseDirectorySymlinks", mainCfgLocal.hidden.traverseDirectorySymlinks, cmpSettings); //########################################################### TiXmlElement* syncSettings = new TiXmlElement("Synchronization"); settings->LinkEndChild(syncSettings); //write sync configuration + addXmlElement("Automatic", mainCfgLocal.syncConfiguration.automatic, syncSettings); + TiXmlElement* syncDirections = new TiXmlElement("Directions"); syncSettings->LinkEndChild(syncDirections); - ::addXmlElement("LeftOnly", mainCfgLocal.syncConfiguration.exLeftSideOnly, syncDirections); - ::addXmlElement("RightOnly", mainCfgLocal.syncConfiguration.exRightSideOnly, syncDirections); - ::addXmlElement("LeftNewer", mainCfgLocal.syncConfiguration.leftNewer, syncDirections); - ::addXmlElement("RightNewer", mainCfgLocal.syncConfiguration.rightNewer, syncDirections); - ::addXmlElement("Different", mainCfgLocal.syncConfiguration.different, syncDirections); - ::addXmlElement("Conflict", mainCfgLocal.syncConfiguration.conflict, syncDirections); + addXmlElement("LeftOnly", mainCfgLocal.syncConfiguration.exLeftSideOnly, syncDirections); + addXmlElement("RightOnly", mainCfgLocal.syncConfiguration.exRightSideOnly, syncDirections); + addXmlElement("LeftNewer", mainCfgLocal.syncConfiguration.leftNewer, syncDirections); + addXmlElement("RightNewer", mainCfgLocal.syncConfiguration.rightNewer, syncDirections); + addXmlElement("Different", mainCfgLocal.syncConfiguration.different, syncDirections); + addXmlElement("Conflict", mainCfgLocal.syncConfiguration.conflict, syncDirections); //########################################################### //copy symbolic links to files - xmlAccess::addXmlElement("CopyFileSymlinks", mainCfgLocal.hidden.copyFileSymlinks, syncSettings); + addXmlElement("CopyFileSymlinks", mainCfgLocal.hidden.copyFileSymlinks, syncSettings); //verify file copying - xmlAccess::addXmlElement("VerifyCopiedFiles", mainCfgLocal.hidden.verifyFileCopy, syncSettings); + addXmlElement("VerifyCopiedFiles", mainCfgLocal.hidden.verifyFileCopy, syncSettings); //########################################################### TiXmlElement* miscSettings = new TiXmlElement("Miscellaneous"); @@ -717,13 +732,13 @@ bool writeXmlMainConfig(const MainConfiguration& mainCfg, TiXmlDocument& doc) TiXmlElement* filter = new TiXmlElement("Filter"); miscSettings->LinkEndChild(filter); - xmlAccess::addXmlElement("Active", mainCfgLocal.filterIsActive, filter); - xmlAccess::addXmlElement("Include", mainCfgLocal.includeFilter, filter); - xmlAccess::addXmlElement("Exclude", mainCfgLocal.excludeFilter, filter); + addXmlElement("Active", mainCfgLocal.filterIsActive, filter); + addXmlElement("Include", mainCfgLocal.includeFilter, filter); + addXmlElement("Exclude", mainCfgLocal.excludeFilter, filter); //other addXmlElement("DeletionPolicy", mainCfgLocal.handleDeletion, miscSettings); - xmlAccess::addXmlElement("CustomDeletionFolder", mainCfgLocal.customDeletionDirectory, miscSettings); + addXmlElement("CustomDeletionFolder", mainCfgLocal.customDeletionDirectory, miscSettings); //########################################################### TiXmlElement* pairs = new TiXmlElement("FolderPairs"); @@ -757,11 +772,11 @@ bool writeXmlGuiConfig(const xmlAccess::XmlGuiConfig& inputCfg, TiXmlDocument& d TiXmlElement* guiConfig = new TiXmlElement("GuiConfig"); root->LinkEndChild(guiConfig); - xmlAccess::addXmlElement("HideFiltered", inputCfg.hideFilteredElements, guiConfig); + addXmlElement("HideFiltered", inputCfg.hideFilteredElements, guiConfig); - ::addXmlElement("HandleError", inputCfg.ignoreErrors ? xmlAccess::ON_ERROR_IGNORE : xmlAccess::ON_ERROR_POPUP, guiConfig); + addXmlElement("HandleError", inputCfg.ignoreErrors ? xmlAccess::ON_ERROR_IGNORE : xmlAccess::ON_ERROR_POPUP, guiConfig); - xmlAccess::addXmlElement("SyncPreviewActive", inputCfg.syncPreviewEnabled, guiConfig); + addXmlElement("SyncPreviewActive", inputCfg.syncPreviewEnabled, guiConfig); return true; } @@ -780,9 +795,9 @@ bool writeXmlBatchConfig(const xmlAccess::XmlBatchConfig& inputCfg, TiXmlDocumen TiXmlElement* batchConfig = new TiXmlElement("BatchConfig"); root->LinkEndChild(batchConfig); - xmlAccess::addXmlElement("Silent", inputCfg.silent, batchConfig); - xmlAccess::addXmlElement("LogfileDirectory", inputCfg.logFileDirectory, batchConfig); - ::addXmlElement("HandleError", inputCfg.handleError, batchConfig); + addXmlElement("Silent", inputCfg.silent, batchConfig); + addXmlElement("LogfileDirectory", inputCfg.logFileDirectory, batchConfig); + addXmlElement("HandleError", inputCfg.handleError, batchConfig); return true; } @@ -799,13 +814,13 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD root->LinkEndChild(global); //program language - xmlAccess::addXmlElement("Language", inputCfg.programLanguage, global); + addXmlElement("Language", inputCfg.programLanguage, global); //ignore +/- 1 hour due to DST change - xmlAccess::addXmlElement("IgnoreOneHourDifference", inputCfg.ignoreOneHourDiff, global); + addXmlElement("IgnoreOneHourDifference", inputCfg.ignoreOneHourDiff, global); //last update check - xmlAccess::addXmlElement("LastCheckForUpdates", inputCfg.lastUpdateCheck, global); + addXmlElement("LastCheckForUpdates", inputCfg.lastUpdateCheck, global); //optional dialogs @@ -813,20 +828,22 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD global->LinkEndChild(optionalDialogs); //warning: dependent folders - xmlAccess::addXmlElement("CheckForDependentFolders", inputCfg.optDialogs.warningDependentFolders, optionalDialogs); + addXmlElement("CheckForDependentFolders", inputCfg.optDialogs.warningDependentFolders, optionalDialogs); //significant difference check - xmlAccess::addXmlElement("CheckForSignificantDifference", inputCfg.optDialogs.warningSignificantDifference, optionalDialogs); + addXmlElement("CheckForSignificantDifference", inputCfg.optDialogs.warningSignificantDifference, optionalDialogs); //check free disk space - xmlAccess::addXmlElement("CheckForFreeDiskSpace", inputCfg.optDialogs.warningNotEnoughDiskSpace, optionalDialogs); + addXmlElement("CheckForFreeDiskSpace", inputCfg.optDialogs.warningNotEnoughDiskSpace, optionalDialogs); //check for unresolved conflicts - xmlAccess::addXmlElement("CheckForUnresolvedConflicts", inputCfg.optDialogs.warningUnresolvedConflicts, optionalDialogs); + addXmlElement("CheckForUnresolvedConflicts", inputCfg.optDialogs.warningUnresolvedConflicts, optionalDialogs); + + addXmlElement("CheckSyncDatabase", inputCfg.optDialogs.warningSyncDatabase, optionalDialogs); - xmlAccess::addXmlElement("PopupOnConfigChange", inputCfg.optDialogs.popupOnConfigChange, optionalDialogs); + addXmlElement("PopupOnConfigChange", inputCfg.optDialogs.popupOnConfigChange, optionalDialogs); - xmlAccess::addXmlElement("SummaryBeforeSync", inputCfg.optDialogs.showSummaryBeforeSync, optionalDialogs); + addXmlElement("SummaryBeforeSync", inputCfg.optDialogs.showSummaryBeforeSync, optionalDialogs); //################################################################### @@ -841,54 +858,54 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD windows->LinkEndChild(mainWindow); //window size - xmlAccess::addXmlElement("Width", inputCfg.gui.widthNotMaximized, mainWindow); - xmlAccess::addXmlElement("Height", inputCfg.gui.heightNotMaximized, mainWindow); + addXmlElement("Width", inputCfg.gui.widthNotMaximized, mainWindow); + addXmlElement("Height", inputCfg.gui.heightNotMaximized, mainWindow); //window position - xmlAccess::addXmlElement("PosX", inputCfg.gui.posXNotMaximized, mainWindow); - xmlAccess::addXmlElement("PosY", inputCfg.gui.posYNotMaximized, mainWindow); - xmlAccess::addXmlElement("Maximized", inputCfg.gui.isMaximized, mainWindow); + addXmlElement("PosX", inputCfg.gui.posXNotMaximized, mainWindow); + addXmlElement("PosY", inputCfg.gui.posYNotMaximized, mainWindow); + addXmlElement("Maximized", inputCfg.gui.isMaximized, mainWindow); - xmlAccess::addXmlElement("ManualDeletionOnBothSides", inputCfg.gui.deleteOnBothSides, mainWindow); - xmlAccess::addXmlElement("ManualDeletionUseRecycler", inputCfg.gui.useRecyclerForManualDeletion, mainWindow); - xmlAccess::addXmlElement("ShowFileIconsLeft", inputCfg.gui.showFileIconsLeft, mainWindow); - xmlAccess::addXmlElement("ShowFileIconsRight", inputCfg.gui.showFileIconsRight, mainWindow); + addXmlElement("ManualDeletionOnBothSides", inputCfg.gui.deleteOnBothSides, mainWindow); + addXmlElement("ManualDeletionUseRecycler", inputCfg.gui.useRecyclerForManualDeletion, mainWindow); + addXmlElement("ShowFileIconsLeft", inputCfg.gui.showFileIconsLeft, mainWindow); + addXmlElement("ShowFileIconsRight", inputCfg.gui.showFileIconsRight, mainWindow); //write column attributes TiXmlElement* leftColumn = new TiXmlElement("LeftColumns"); mainWindow->LinkEndChild(leftColumn); - xmlAccess::addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsLeft, leftColumn); + addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsLeft, leftColumn); - xmlAccess::ColumnAttributes columnAtrribLeftCopy = inputCfg.gui.columnAttribLeft; //can't change const vector + ColumnAttributes columnAtrribLeftCopy = inputCfg.gui.columnAttribLeft; //can't change const vector sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByPositionOnly); for (unsigned int i = 0; i < columnAtrribLeftCopy.size(); ++i) { TiXmlElement* subElement = new TiXmlElement("Column"); leftColumn->LinkEndChild(subElement); - const xmlAccess::ColumnAttrib& colAttrib = columnAtrribLeftCopy[i]; + const ColumnAttrib& colAttrib = columnAtrribLeftCopy[i]; addXmlAttribute("Type", colAttrib.type, subElement); - xmlAccess::addXmlAttribute("Visible", colAttrib.visible, subElement); - xmlAccess::addXmlAttribute("Width", colAttrib.width, subElement); + addXmlAttribute("Visible", colAttrib.visible, subElement); + addXmlAttribute("Width", colAttrib.width, subElement); } TiXmlElement* rightColumn = new TiXmlElement("RightColumns"); mainWindow->LinkEndChild(rightColumn); - xmlAccess::addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsRight, rightColumn); + addXmlAttribute("AutoAdjust", inputCfg.gui.autoAdjustColumnsRight, rightColumn); - xmlAccess::ColumnAttributes columnAtrribRightCopy = inputCfg.gui.columnAttribRight; + ColumnAttributes columnAtrribRightCopy = inputCfg.gui.columnAttribRight; sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByPositionOnly); for (unsigned int i = 0; i < columnAtrribRightCopy.size(); ++i) { TiXmlElement* subElement = new TiXmlElement("Column"); rightColumn->LinkEndChild(subElement); - const xmlAccess::ColumnAttrib& colAttrib = columnAtrribRightCopy[i]; + const ColumnAttrib& colAttrib = columnAtrribRightCopy[i]; addXmlAttribute("Type", colAttrib.type, subElement); - xmlAccess::addXmlAttribute("Visible", colAttrib.visible, subElement); - xmlAccess::addXmlAttribute("Width", colAttrib.width, subElement); + addXmlAttribute("Visible", colAttrib.visible, subElement); + addXmlAttribute("Width", colAttrib.width, subElement); } //write folder history elements @@ -897,24 +914,24 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD TiXmlElement* historyRight = new TiXmlElement("FolderHistoryRight"); mainWindow->LinkEndChild(historyRight); - xmlAccess::addXmlAttribute("MaximumSize", inputCfg.gui.folderHistLeftMax, historyLeft); - xmlAccess::addXmlAttribute("MaximumSize", inputCfg.gui.folderHistRightMax, historyRight); + addXmlAttribute("MaximumSize", inputCfg.gui.folderHistLeftMax, historyLeft); + addXmlAttribute("MaximumSize", inputCfg.gui.folderHistRightMax, historyRight); - xmlAccess::addXmlElement("Folder", inputCfg.gui.folderHistoryLeft, historyLeft); - xmlAccess::addXmlElement("Folder", inputCfg.gui.folderHistoryRight, historyRight); + addXmlElement("Folder", inputCfg.gui.folderHistoryLeft, historyLeft); + addXmlElement("Folder", inputCfg.gui.folderHistoryRight, historyRight); - xmlAccess::addXmlElement("SelectedTabBottomLeft", inputCfg.gui.selectedTabBottomLeft, mainWindow); + addXmlElement("SelectedTabBottomLeft", inputCfg.gui.selectedTabBottomLeft, mainWindow); //external applications TiXmlElement* extApp = new TiXmlElement("ExternalApplications"); gui->LinkEndChild(extApp); - for (xmlAccess::ExternalApps::const_iterator i = inputCfg.gui.externelApplications.begin(); i != inputCfg.gui.externelApplications.end(); ++i) + for (ExternalApps::const_iterator i = inputCfg.gui.externelApplications.begin(); i != inputCfg.gui.externelApplications.end(); ++i) { TiXmlElement* newEntry = new TiXmlElement("Commandline"); extApp->LinkEndChild(newEntry); - xmlAccess::addXmlAttribute("Description", i->first, newEntry); + addXmlAttribute("Description", i->first, newEntry); newEntry->LinkEndChild(new TiXmlText(i->second.ToUTF8())); //commandline } @@ -922,8 +939,8 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD TiXmlElement* cfgHistory = new TiXmlElement("ConfigHistory"); gui->LinkEndChild(cfgHistory); - xmlAccess::addXmlAttribute("MaximumSize", inputCfg.gui.cfgHistoryMax, cfgHistory); - xmlAccess::addXmlElement("File", inputCfg.gui.cfgFileHistory, cfgHistory); + addXmlAttribute("MaximumSize", inputCfg.gui.cfgHistoryMax, cfgHistory); + addXmlElement("File", inputCfg.gui.cfgFileHistory, cfgHistory); //################################################################### //write global batch settings @@ -953,6 +970,7 @@ void xmlAccess::OptionalDialogs::resetDialogs() warningSignificantDifference = true; warningNotEnoughDiskSpace = true; warningUnresolvedConflicts = true; + warningSyncDatabase = true; popupOnConfigChange = true; showSummaryBeforeSync = true; } diff --git a/library/processXml.h b/library/processXml.h index 868b859b..aafd3131 100644 --- a/library/processXml.h +++ b/library/processXml.h @@ -2,214 +2,217 @@ #define PROCESSXML_H_INCLUDED #include "../structures.h" +#include <wx/intl.h> namespace xmlAccess { - enum OnError - { - ON_ERROR_POPUP, - ON_ERROR_IGNORE, - ON_ERROR_EXIT - }; +enum OnError +{ + ON_ERROR_POPUP, + ON_ERROR_IGNORE, + ON_ERROR_EXIT +}; - enum ColumnTypes - { - DIRECTORY, - FULL_PATH, - REL_PATH, - FILENAME, - SIZE, - DATE - }; - const unsigned int COLUMN_TYPE_COUNT = 6; - - struct ColumnAttrib - { - ColumnTypes type; - bool visible; - unsigned int position; - int width; - }; - typedef std::vector<ColumnAttrib> ColumnAttributes; +enum ColumnTypes +{ + DIRECTORY, + FULL_PATH, + REL_PATH, + FILENAME, + SIZE, + DATE +}; +const unsigned int COLUMN_TYPE_COUNT = 6; + +struct ColumnAttrib +{ + ColumnTypes type; + bool visible; + unsigned int position; + int width; +}; +typedef std::vector<ColumnAttrib> ColumnAttributes; - typedef wxString Description; - typedef wxString Commandline; - typedef std::vector<std::pair<Description, Commandline> > ExternalApps; +typedef wxString Description; +typedef wxString Commandline; +typedef std::vector<std::pair<Description, Commandline> > ExternalApps; //--------------------------------------------------------------------- - struct XmlGuiConfig - { - XmlGuiConfig() : - hideFilteredElements(false), - ignoreErrors(false), - syncPreviewEnabled(true) {} //initialize values +struct XmlGuiConfig +{ + XmlGuiConfig() : + hideFilteredElements(false), + ignoreErrors(false), + syncPreviewEnabled(true) {} //initialize values - FreeFileSync::MainConfiguration mainCfg; + FreeFileSync::MainConfiguration mainCfg; - bool hideFilteredElements; - bool ignoreErrors; //reaction on error situation during synchronization - bool syncPreviewEnabled; + bool hideFilteredElements; + bool ignoreErrors; //reaction on error situation during synchronization + bool syncPreviewEnabled; - bool operator==(const XmlGuiConfig& other) const - { - return mainCfg == other.mainCfg && - hideFilteredElements == other.hideFilteredElements && - ignoreErrors == other.ignoreErrors && - syncPreviewEnabled == other.syncPreviewEnabled; - } + bool operator==(const XmlGuiConfig& other) const + { + return mainCfg == other.mainCfg && + hideFilteredElements == other.hideFilteredElements && + ignoreErrors == other.ignoreErrors && + syncPreviewEnabled == other.syncPreviewEnabled; + } - bool operator!=(const XmlGuiConfig& other) const - { - return !(*this == other); - } - }; + bool operator!=(const XmlGuiConfig& other) const + { + return !(*this == other); + } +}; - struct XmlBatchConfig - { - XmlBatchConfig() : silent(false), handleError(ON_ERROR_POPUP) {} +struct XmlBatchConfig +{ + XmlBatchConfig() : silent(false), handleError(ON_ERROR_POPUP) {} - FreeFileSync::MainConfiguration mainCfg; + FreeFileSync::MainConfiguration mainCfg; - bool silent; - OnError handleError; //reaction on error situation during synchronization - wxString logFileDirectory; // - }; + bool silent; + OnError handleError; //reaction on error situation during synchronization + wxString logFileDirectory; // +}; - int retrieveSystemLanguage(); - bool recycleBinAvailable(); +int retrieveSystemLanguage(); +bool recycleBinAvailable(); - struct OptionalDialogs +struct OptionalDialogs +{ + OptionalDialogs() { - OptionalDialogs() - { - resetDialogs(); - } + resetDialogs(); + } - void resetDialogs(); + void resetDialogs(); - bool warningDependentFolders; - bool warningSignificantDifference; - bool warningNotEnoughDiskSpace; - bool warningUnresolvedConflicts; - bool popupOnConfigChange; - bool showSummaryBeforeSync; - }; + bool warningDependentFolders; + bool warningSignificantDifference; + bool warningNotEnoughDiskSpace; + bool warningUnresolvedConflicts; + bool warningSyncDatabase; + bool popupOnConfigChange; + bool showSummaryBeforeSync; +}; - struct XmlGlobalSettings - { +struct XmlGlobalSettings +{ //--------------------------------------------------------------------- - //Shared (GUI/BATCH) settings - XmlGlobalSettings() : - programLanguage(retrieveSystemLanguage()), - ignoreOneHourDiff(false), - lastUpdateCheck(0) {} + //Shared (GUI/BATCH) settings + XmlGlobalSettings() : + programLanguage(retrieveSystemLanguage()), + ignoreOneHourDiff(false), + lastUpdateCheck(0) {} - int programLanguage; - bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change - long lastUpdateCheck; //time of last update check + int programLanguage; + bool ignoreOneHourDiff; //ignore +/- 1 hour due to DST change + long lastUpdateCheck; //time of last update check - OptionalDialogs optDialogs; + OptionalDialogs optDialogs; //--------------------------------------------------------------------- - struct _Gui + struct _Gui + { + _Gui() : + widthNotMaximized(wxDefaultCoord), + heightNotMaximized(wxDefaultCoord), + posXNotMaximized(wxDefaultCoord), + posYNotMaximized(wxDefaultCoord), + isMaximized(false), + autoAdjustColumnsLeft(false), + autoAdjustColumnsRight(false), + cfgHistoryMax(10), + folderHistLeftMax(12), + folderHistRightMax(12), + selectedTabBottomLeft(0), + deleteOnBothSides(false), + useRecyclerForManualDeletion(recycleBinAvailable()), //enable if OS supports it; else user will have to activate first and then get an error message + showFileIconsLeft(true), + showFileIconsRight(true) { - _Gui() : - widthNotMaximized(wxDefaultCoord), - heightNotMaximized(wxDefaultCoord), - posXNotMaximized(wxDefaultCoord), - posYNotMaximized(wxDefaultCoord), - isMaximized(false), - autoAdjustColumnsLeft(false), - autoAdjustColumnsRight(false), - cfgHistoryMax(10), - folderHistLeftMax(12), - folderHistRightMax(12), - selectedTabBottomLeft(0), - deleteOnBothSides(false), - useRecyclerForManualDeletion(recycleBinAvailable()), //enable if OS supports it; else user will have to activate first and then get an error message - showFileIconsLeft(true), - showFileIconsRight(true) - { #ifdef FFS_WIN - externelApplications.push_back(std::make_pair(wxT("Open with Explorer"), wxT("explorer /select, %name"))); + externelApplications.push_back(std::make_pair(_("Open with Explorer"), wxT("explorer /select, %name"))); + externelApplications.push_back(std::make_pair(_("Open directly"), wxT("cmd /c start \"\" \"%name\""))); #elif defined FFS_LINUX - externelApplications.push_back(std::make_pair(wxT("Open with Konqueror"), wxT("konqueror \"%dir\""))); + externelApplications.push_back(std::make_pair(_("Open with Konqueror"), wxT("konqueror \"%dir\""))); #endif - } + } - int widthNotMaximized; - int heightNotMaximized; - int posXNotMaximized; - int posYNotMaximized; - bool isMaximized; + int widthNotMaximized; + int heightNotMaximized; + int posXNotMaximized; + int posYNotMaximized; + bool isMaximized; - ColumnAttributes columnAttribLeft; - ColumnAttributes columnAttribRight; + ColumnAttributes columnAttribLeft; + ColumnAttributes columnAttribRight; - bool autoAdjustColumnsLeft; - bool autoAdjustColumnsRight; + bool autoAdjustColumnsLeft; + bool autoAdjustColumnsRight; - ExternalApps externelApplications; + ExternalApps externelApplications; - std::vector<wxString> cfgFileHistory; - unsigned int cfgHistoryMax; + std::vector<wxString> cfgFileHistory; + unsigned int cfgHistoryMax; - std::vector<wxString> folderHistoryLeft; - unsigned int folderHistLeftMax; + std::vector<wxString> folderHistoryLeft; + unsigned int folderHistLeftMax; - std::vector<wxString> folderHistoryRight; - unsigned int folderHistRightMax; + std::vector<wxString> folderHistoryRight; + unsigned int folderHistRightMax; - int selectedTabBottomLeft; + int selectedTabBottomLeft; - bool deleteOnBothSides; - bool useRecyclerForManualDeletion; - bool showFileIconsLeft; - bool showFileIconsRight; - } gui; + bool deleteOnBothSides; + bool useRecyclerForManualDeletion; + bool showFileIconsLeft; + bool showFileIconsRight; + } gui; //--------------------------------------------------------------------- - //struct _Batch - }; + //struct _Batch +}; - inline - bool sortByType(const ColumnAttrib& a, const ColumnAttrib& b) - { - return a.type < b.type; - } +inline +bool sortByType(const ColumnAttrib& a, const ColumnAttrib& b) +{ + return a.type < b.type; +} - inline - bool sortByPositionOnly(const ColumnAttrib& a, const ColumnAttrib& b) - { - return a.position < b.position; - } +inline +bool sortByPositionOnly(const ColumnAttrib& a, const ColumnAttrib& b) +{ + return a.position < b.position; +} - inline - bool sortByPositionAndVisibility(const ColumnAttrib& a, const ColumnAttrib& b) - { - if (a.visible == false) //hidden elements shall appear at end of vector - return false; - if (b.visible == false) - return true; - return a.position < b.position; - } +inline +bool sortByPositionAndVisibility(const ColumnAttrib& a, const ColumnAttrib& b) +{ + if (a.visible == false) //hidden elements shall appear at end of vector + return false; + if (b.visible == false) + return true; + return a.position < b.position; +} - void readGuiConfig( const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError); - void readBatchConfig(const wxString& filename, XmlBatchConfig& config); //throw (xmlAccess::XmlError); - void readGlobalSettings( XmlGlobalSettings& config); //throw (xmlAccess::XmlError); +void readGuiConfig( const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError); +void readBatchConfig(const wxString& filename, XmlBatchConfig& config); //throw (xmlAccess::XmlError); +void readGlobalSettings( XmlGlobalSettings& config); //throw (xmlAccess::XmlError); - void readGuiOrBatchConfig(const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError); +void readGuiOrBatchConfig(const wxString& filename, XmlGuiConfig& config); //throw (xmlAccess::XmlError); - void writeGuiConfig( const XmlGuiConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError); - void writeBatchConfig( const XmlBatchConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError); - void writeGlobalSettings(const XmlGlobalSettings& outputCfg); //throw (xmlAccess::XmlError); +void writeGuiConfig( const XmlGuiConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError); +void writeBatchConfig( const XmlBatchConfig& outputCfg, const wxString& filename); //throw (xmlAccess::XmlError); +void writeGlobalSettings(const XmlGlobalSettings& outputCfg); //throw (xmlAccess::XmlError); } diff --git a/library/resources.cpp b/library/resources.cpp index 1b9ce12d..a42f2788 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -4,10 +4,13 @@ #include <wx/image.h> #include <wx/icon.h> #include <wx/mstream.h> +#include "../shared/stringConv.h" #include "../shared/systemConstants.h" #include <memory> #include "../shared/standardPaths.h" +using namespace FreeFileSync; + const GlobalResources& GlobalResources::getInstance() { @@ -127,7 +130,9 @@ GlobalResources::GlobalResources() bitmapResource[wxT("france.png")] = (bitmapFrance = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("germany.png")] = (bitmapGermany = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("hungary.png")] = (bitmapHungary = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("romania.png")] = (bitmapRomania = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("taiwan.png")] = (bitmapTaiwan = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("turkey.png")] = (bitmapTurkey = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("italy.png")] = (bitmapItaly = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("japan.png")] = (bitmapJapan = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("poland.png")] = (bitmapPoland = new wxBitmap(wxNullBitmap)); @@ -213,7 +218,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation) void GlobalResources::load() const { - wxFFileInputStream input(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("Resources.dat")); + wxFFileInputStream input(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("Resources.dat")); if (input.IsOk()) //if not... we don't want to react too harsh here { //activate support for .png files diff --git a/library/resources.h b/library/resources.h index 804dea7a..432498a3 100644 --- a/library/resources.h +++ b/library/resources.h @@ -123,7 +123,9 @@ public: wxBitmap* bitmapFrance; wxBitmap* bitmapGermany; wxBitmap* bitmapHungary; + wxBitmap* bitmapRomania; wxBitmap* bitmapTaiwan; + wxBitmap* bitmapTurkey; wxBitmap* bitmapItaly; wxBitmap* bitmapJapan; wxBitmap* bitmapPoland; diff --git a/library/statistics.cpp b/library/statistics.cpp index 08bb5dee..fb7f5ba4 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -3,18 +3,20 @@ #include <wx/ffile.h> #include "../shared/globalFunctions.h" #include "statusHandler.h" -#include "../algorithm.h" +//#include "../algorithm.h" +#include "../ui/util.h" #include <wx/intl.h> #include <limits> #include <wx/stopwatch.h> RetrieveStatistics::RetrieveStatistics() : - timer(new wxStopWatch) {} + timer(new wxStopWatch) {} RetrieveStatistics::~RetrieveStatistics() -{ //write statistics to a file +{ + //write statistics to a file wxFFile outputFile(wxT("statistics.dat"), wxT("w")); outputFile.Write(wxT("Time(ms);Objects;Data\n")); @@ -103,13 +105,13 @@ Statistics::Statistics(const int totalObjectCount, const double totalDataAmount, const unsigned windowSizeRemainingTime, const unsigned windowSizeBytesPerSecond) : - objectsTotal(totalObjectCount), - dataTotal(totalDataAmount), - windowSizeRemTime(windowSizeRemainingTime), - windowSizeBPS(windowSizeBytesPerSecond), - windowMax(std::max(windowSizeRemainingTime, windowSizeBytesPerSecond)), - remainingTimeLast(256*256*256*100), //something "big" - timer(new wxStopWatch) {} + objectsTotal(totalObjectCount), + dataTotal(totalDataAmount), + windowSizeRemTime(windowSizeRemainingTime), + windowSizeBPS(windowSizeBytesPerSecond), + windowMax(std::max(windowSizeRemainingTime, windowSizeBytesPerSecond)), + remainingTimeLast(256*256*256*100), //something "big" + timer(new wxStopWatch) {} void Statistics::addMeasurement(const int objectsCurrent, const double dataCurrent) diff --git a/library/tinyxml/tinystr.cpp b/library/tinyxml/tinystr.cpp deleted file mode 100644 index 2b9b5467..00000000 --- a/library/tinyxml/tinystr.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005. - */ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/library/tinyxml/tinystr.h b/library/tinyxml/tinystr.h deleted file mode 100644 index 3c2aa9d5..00000000 --- a/library/tinyxml/tinystr.h +++ /dev/null @@ -1,319 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. - * - * - completely rewritten. compact, clean, and fast implementation. - * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) - * - fixed reserve() to work as per specification. - * - fixed buggy compares operator==(), operator<(), and operator>() - * - fixed operator+=() to take a const ref argument, following spec. - * - added "copy" constructor with length, and most compare operators. - * - added swap(), clear(), size(), capacity(), operator+(). - */ - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include <assert.h> -#include <string.h> - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast<size_type>( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - // = operator - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - // = operator - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast<size_type>( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast<int*>( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/library/tinyxml/tinyxml.cpp b/library/tinyxml/tinyxml.cpp deleted file mode 100644 index aa13deec..00000000 --- a/library/tinyxml/tinyxml.cpp +++ /dev/null @@ -1,1942 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include <ctype.h> - -#ifdef TIXML_USE_STL -#include <sstream> -#include <iostream> -#endif - -#include "tinyxml.h" - - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ -#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; -#else - return fopen( filename, mode ); -#endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while ( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - -#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); -#else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); -#endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::DOCUMENT ) - { - delete node; - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) - { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) - { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( replaceThis->parent != this ) - return 0; - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ -#ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); -#else - TiXmlAttribute* node = attributeSet.Find( name ); -#endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for ( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -void TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while ( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return &node->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const char* s = Attribute( name ); - if ( i ) - { - if ( s ) - { - *i = atoi( s ); - } - else - { - *i = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const std::string* s = Attribute( name ); - if ( i ) - { - if ( s ) - { - *i = atoi( s->c_str() ); - } - else - { - *i = 0; - } - } - return s; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const char* s = Attribute( name ); - if ( d ) - { - if ( s ) - { - *d = atof( s ); - } - else - { - *d = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const std::string* s = Attribute( name ); - if ( d ) - { - if ( s ) - { - *d = atof( s->c_str() ); - } - else - { - *d = 0; - } - } - return s; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - char buf[64]; -#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); -#else - sprintf( buf, "%d", val ); -#endif - SetAttribute( name, buf ); -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - std::ostringstream oss; - oss << val; - SetAttribute( name, oss.str() ); -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - char buf[256]; -#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); -#else - sprintf( buf, "%f", val ); -#endif - SetAttribute( name, buf ); -} - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ -#ifdef TIXML_USE_STL - TIXML_STRING _name( cname ); - TIXML_STRING _value( cvalue ); -#else - const char* _name = cname; - const char* _value = cvalue; -#endif - - TiXmlAttribute* node = attributeSet.Find( _name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) -{ - TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; i<depth; i++ ) - { - fprintf( cfile, " " ); - } - - fprintf( cfile, "<%s", value.c_str() ); - - const TiXmlAttribute* attrib; - for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a <foo /> node - // 2) An element with only a text child is printed as <foo> text </foo> - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "</%s>", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for ( i=0; i<depth; ++i ) - { - fprintf( cfile, " " ); - } - fprintf( cfile, "</%s>", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for ( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) - { - const TiXmlText* childText = child->ToText(); - if ( childText ) - { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - // See STL_STRING_BUG below. - //StringToBuffer buf( value ); - - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - // See STL_STRING_BUG below. -// StringToBuffer buf( value ); -// -// if ( buf.buffer && SaveFile( buf.buffer ) ) -// return true; -// -// return false; - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - // There was a really terrifying little bug here. The code: - // value = filename - // in the STL case, cause the assignment method of the std::string to - // be called. What is strange, is that the std::string had the same - // address as it's c_str() method, and so bad things happen. Looks - // like a bug in the Microsoft STL implementation. - // Add an extra string to avoid the crash. - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // If we have a file, assume it is all one big XML file, and read it in. - // The document parser may decide the document ends sooner than the entire file, however. - TIXML_STRING data; - data.reserve( length ); - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // <snip> - // <quote> - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // </quote> - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) - { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - const char* lastPos = buf; - const char* p = buf; - - buf[length] = 0; - while ( *p ) - { - assert( p < (buf+length) ); - if ( *p == 0xa ) - { - // Newline character. No special rules for this. Append all the characters - // since the last string, and include the newline. - data.append( lastPos, (p-lastPos+1) ); // append, include the newline - ++p; // move past the newline - lastPos = p; // and point to the new buffer (may be 0) - assert( p <= (buf+length) ); - } - else if ( *p == 0xd ) - { - // Carriage return. Append what we have so far, then - // handle moving forward in the buffer. - if ( (p-lastPos) > 0 ) - { - data.append( lastPos, p-lastPos ); // do not add the CR - } - data += (char)0xa; // a proper newline - - if ( *(p+1) == 0xa ) - { - // Carriage return - new line sequence - p += 2; - lastPos = p; - assert( p <= (buf+length) ); - } - else - { - // it was followed by something else...that is presumably characters again. - ++p; - lastPos = p; - assert( p <= (buf+length) ); - } - } - else - { - ++p; - } - } - // Handle any left over characters. - if ( p-lastPos ) - { - data.append( lastPos, p-lastPos ); - } - delete [] buf; - buf = 0; - - Parse( data.c_str(), 0, encoding ); - - if ( Error() ) - return false; - else - return true; -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) - { - if ( cfile ) - { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) - { - (*str) += n; - (*str) += "=\""; - (*str) += v; - (*str) += "\""; - } - } - else - { - if ( cfile ) - { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) - { - (*str) += n; - (*str) += "='"; - (*str) += v; - (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; -#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); -#else - sprintf (buf, "%d", _value); -#endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; -#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); -#else - sprintf (buf, "%lf", _value); -#endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i<depth; i++ ) - { - fprintf( cfile, " " ); - } - fprintf( cfile, "<!--%s-->", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i<depth; i++ ) - { - fprintf( cfile, " " ); - } - fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "<?xml " ); - if ( str ) (*str) += "<?xml "; - - if ( !version.empty() ) - { - if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); - if ( str ) - { - (*str) += "version=\""; - (*str) += version; - (*str) += "\" "; - } - } - if ( !encoding.empty() ) - { - if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); - if ( str ) - { - (*str) += "encoding=\""; - (*str) += encoding; - (*str) += "\" "; - } - } - if ( !standalone.empty() ) - { - if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); - if ( str ) - { - (*str) += "standalone=\""; - (*str) += standalone; - (*str) += "\" "; - } - } - if ( cfile ) fprintf( cfile, "?>" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i<depth; i++ ) - fprintf( cfile, " " ); - fprintf( cfile, "<%s>", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ -#ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. -#else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. -#endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for ( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for ( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} -*/ -#endif - - -const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for ( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} -*/ - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && i<count; - child = child->NextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && i<count; - child = child->NextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && i<count; - child = child->NextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && i<count; - child = child->NextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for ( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += "</"; - buffer += element.Value(); - buffer += ">"; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += "<![CDATA["; - buffer += text.Value(); - buffer += "]]>"; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += "<!--"; - buffer += comment.Value(); - buffer += "-->"; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/library/tinyxml/tinyxml.h b/library/tinyxml/tinyxml.h deleted file mode 100644 index c6f40cc2..00000000 --- a/library/tinyxml/tinyxml.h +++ /dev/null @@ -1,1802 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#ifdef _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4530 ) -#pragma warning( disable : 4786 ) -#endif - -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include <string> - #include <iostream> - #include <sstream> - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SNSCANF _snscanf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SNSCANF _snscanf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SNSCANF snscanf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 5; -const int TIXML_PATCH_VERSION = 3; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simple called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, <b>no children of this node or its sibilings</b> will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_OUT_OF_MEMORY, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - DOCUMENT, - ELEMENT, - COMMENT, - UNKNOWN, - TEXT, - DECLARATION, - TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - const TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* Find( const char* _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - #ifdef TIXML_USE_STL - const TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* Find( const std::string& _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - - #endif - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - /* - This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" - but template specialization is hard to get working cross-compiler. Leaving the bug for now. - - // The above will fail for std::string because the space character is used as a seperator. - // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string - template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - */ - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - <foo>This is text</foo> - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - <foo><b>This is text</b></foo> - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - <foo>This is <b>text</b></foo> - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - <?xml version="1.0" standalone="yes"?> - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && LoadFile( f.buffer, encoding )); - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && SaveFile( f.buffer )); - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - <Document> - <Element attributeA = "valueA"> - <Child attributeB = "value1" /> - <Child attributeB = "value2" /> - </Element> - <Document> - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i<depth; ++i ) - buffer += indent; - } - void DoLineBreak() { - buffer += lineBreak; - } - - int depth; - bool simpleTextPrint; - TIXML_STRING buffer; - TIXML_STRING indent; - TIXML_STRING lineBreak; -}; - - -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - -#endif - diff --git a/library/tinyxml/tinyxmlerror.cpp b/library/tinyxml/tinyxmlerror.cpp deleted file mode 100644 index 3f068f2b..00000000 --- a/library/tinyxml/tinyxmlerror.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include "tinyxml.h" - -// The goal of the seperate error file is to make the first -// step towards localization. tinyxml (currently) only supports -// english error messages, but the could now be translated. -// -// It also cleans up the code a bit. -// - -const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = -{ - "No error", - "Error", - "Failed to open file", - "Memory allocation failed.", - "Error parsing Element.", - "Failed to read Element name", - "Error reading Element value.", - "Error reading Attributes.", - "Error: empty tag.", - "Error reading end tag.", - "Error parsing Unknown.", - "Error parsing Comment.", - "Error parsing Declaration.", - "Error document empty.", - "Error null (0) or unexpected EOF found in input stream.", - "Error parsing CDATA.", - "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", -}; diff --git a/library/tinyxml/tinyxmlparser.cpp b/library/tinyxml/tinyxmlparser.cpp deleted file mode 100644 index 539f72cf..00000000 --- a/library/tinyxml/tinyxmlparser.cpp +++ /dev/null @@ -1,1660 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include <ctype.h> -#include <stddef.h> - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include <windows.h> -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { - *length = 0; // This code won't covert this correctly anyway. - return; - } - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ -int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ -int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; -public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() - { - return cursor; - } - -private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) - { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') - { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') - { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { - p +=3; // A normal character. - ++col; - } - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if (*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if (*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( (*p && IsWhiteSpace( *p )) || *p == '\n' || *p =='\r' ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for ( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ -bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while ( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) - { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for ( i=0; i<NUM_ENTITY; ++i ) - { - if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) - { - assert( strlen( entity[i].str ) == entity[i].strLength ); - *value = entity[i].chr; - *length = 1; - return ( p + entity[i].strLength ); - } - } - - // So it wasn't an entity, its unrecognized, or something like that. - *value = *p; // Don't put back the last one, since we return it! - //*length = 1; // Leave unrecognized entities - this doesn't really work. - // Just writes strange XML. - return p+1; -} - - -bool TiXmlBase::StringEqual( const char* p, - const char* tag, - bool ignoreCase, - TiXmlEncoding encoding ) -{ - assert( p ); - assert( tag ); - if ( !p || !*p ) - { - assert( 0 ); - return false; - } - - const char* q = p; - - if ( ignoreCase ) - { - while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) ) - { - ++q; - ++tag; - } - - if ( *tag == 0 ) - return true; - } - else - { - while ( *q && *tag && *q == *tag ) - { - ++q; - ++tag; - } - - if ( *tag == 0 ) // Have we found the end of the tag, and everything equal? - return true; - } - return false; -} - -const char* TiXmlBase::ReadText( const char* p, - TIXML_STRING * text, - bool trimWhiteSpace, - const char* endTag, - bool caseInsensitive, - TiXmlEncoding encoding ) -{ - *text = ""; - if ( !trimWhiteSpace // certain tags always keep whitespace - || !condenseWhiteSpace ) // if true, whitespace is always kept - { - // Keep all the white space. - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) - ) - { - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - text->append( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p ) - p += strlen( endTag ); - return p; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '<' ) - { - return 0; - } - - TiXmlDocument* doc = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: <!-- - // - Decleration: <?xml - // - Everthing else is unknown to tinyxml. - // - - const char* xmlHeader = { "<?xml" }; - const char* commentHeader = { "<!--" }; - const char* dtdHeader = { "<!" }; - const char* cdataHeader = { "<![CDATA[" }; - - if ( StringEqual( p, xmlHeader, true, encoding ) ) - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Declaration\n" ); -#endif - returnNode = new TiXmlDeclaration(); - } - else if ( StringEqual( p, commentHeader, false, encoding ) ) - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Comment\n" ); -#endif - returnNode = new TiXmlComment(); - } - else if ( StringEqual( p, cdataHeader, false, encoding ) ) - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing CDATA\n" ); -#endif - TiXmlText* text = new TiXmlText( "" ); - text->SetCDATA( true ); - returnNode = text; - } - else if ( StringEqual( p, dtdHeader, false, encoding ) ) - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Unknown(1)\n" ); -#endif - returnNode = new TiXmlUnknown(); - } - else if ( IsAlpha( *(p+1), encoding ) - || *(p+1) == '_' ) - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Element\n" ); -#endif - returnNode = new TiXmlElement( "" ); - } - else - { -#ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Unknown(2)\n" ); -#endif - returnNode = new TiXmlUnknown(); - } - - if ( returnNode ) - { - // Set the parent, so it can report errors - returnNode->parent = this; - } - else - { - if ( doc ) - doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } - return returnNode; -} - -#ifdef TIXML_USE_STL - -void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) -{ - // We're called with some amount of pre-parsing. That is, some of "this" - // element is in "tag". Go ahead and stream to the closing ">" - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c ; - - if ( c == '>' ) - break; - } - - if ( tag->length() < 3 ) return; - - // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. - // If not, identify and stream. - - if ( tag->at( tag->length() - 1 ) == '>' - && tag->at( tag->length() - 2 ) == '/' ) - { - // All good! - return; - } - else if ( tag->at( tag->length() - 1 ) == '>' ) - { - // There is more. Could be: - // text - // cdata text (which looks like another node) - // closing tag - // another node. - for ( ;; ) - { - StreamWhiteSpace( in, tag ); - - // Do we have text? - if ( in->good() && in->peek() != '<' ) - { - // Yep, text. - TiXmlText text( "" ); - text.StreamIn( in, tag ); - - // What follows text is a closing tag or another node. - // Go around again and figure it out. - continue; - } - - // We now have either a closing tag...or another node. - // We should be at a "<", regardless. - if ( !in->good() ) return; - assert( in->peek() == '<' ); - int tagIndex = (int) tag->length(); - - bool closingTag = false; - bool firstCharFound = false; - - for ( ;; ) - { - if ( !in->good() ) - return; - - int c = in->peek(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - if ( c == '>' ) - break; - - *tag += (char) c; - in->get(); - - // Early out if we find the CDATA id. - if ( c == '[' && tag->size() >= 9 ) - { - size_t len = tag->size(); - const char* start = tag->c_str() + len - 9; - if ( strcmp( start, "<![CDATA[" ) == 0 ) - { - assert( !closingTag ); - break; - } - } - - if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) - { - firstCharFound = true; - if ( c == '/' ) - closingTag = true; - } - } - // If it was a closing tag, then read in the closing '>' to clean up the input stream. - // If it was not, the streaming will be done by the tag. - if ( closingTag ) - { - if ( !in->good() ) - return; - - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - assert( c == '>' ); - *tag += (char) c; - - // We are done, once we've found our closing tag. - return; - } - else - { - // If not a closing tag, id it, and stream. - const char* tagloc = tag->c_str() + tagIndex; - TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING ); - if ( !node ) - return; - node->StreamIn( in, tag ); - delete node; - node = 0; - - // No return: go around from the beginning: text, closing tag, or node. - } - } - } -} -#endif - -const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - TiXmlDocument* document = GetDocument(); - - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); - return 0; - } - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - if ( *p != '<' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); - return 0; - } - - p = SkipWhiteSpace( p+1, encoding ); - - // Read the name. - const char* pErr = p; - - p = ReadName( p, &value, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); - return 0; - } - - TIXML_STRING endTag ("</"); - endTag += value; - endTag += ">"; - - // Check for and read attributes. Also look for an empty - // tag or an end tag. - while ( p && *p ) - { - pErr = p; - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - if ( *p == '/' ) - { - ++p; - // Empty tag. - if ( *p != '>' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); - return 0; - } - return (p+1); - } - else if ( *p == '>' ) - { - // Done with attributes (if there were any.) - // Read the value -- which can include other - // elements -- read the end tag, and return. - ++p; - p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. - if ( !p || !*p ) - { - // We were looking for the end tag, but found nothing. - // Fix for [ 1663758 ] Failure to report error on bad XML - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; - } - - // We should find the end tag now - if ( StringEqual( p, endTag.c_str(), false, encoding ) ) - { - p += endTag.length(); - return p; - } - else - { - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; - } - } - else - { - // Try to read an attribute: - TiXmlAttribute* attrib = new TiXmlAttribute(); - if ( !attrib ) - { - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding ); - return 0; - } - - attrib->SetDocument( document ); - pErr = p; - p = attrib->Parse( p, data, encoding ); - - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); - delete attrib; - return 0; - } - - // Handle the strange case of double attributes: -#ifdef TIXML_USE_STL - TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); -#else - TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); -#endif - if ( node ) - { - node->SetValue( attrib->Value() ); - delete attrib; - return 0; - } - - attributeSet.Add( attrib ); - } - } - return p; -} - - -const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - TiXmlDocument* document = GetDocument(); - - // Read in text and elements in any order. - const char* pWithWhiteSpace = p; - p = SkipWhiteSpace( p, encoding ); - - while ( p && *p ) - { - if ( *p != '<' ) - { - // Take what we have, make a text element. - TiXmlText* textNode = new TiXmlText( "" ); - - if ( !textNode ) - { - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding ); - return 0; - } - - if ( TiXmlBase::IsWhiteSpaceCondensed() ) - { - p = textNode->Parse( p, data, encoding ); - } - else - { - // Special case: we want to keep the white space - // so that leading spaces aren't removed. - p = textNode->Parse( pWithWhiteSpace, data, encoding ); - } - - if ( !textNode->Blank() ) - LinkEndChild( textNode ); - else - delete textNode; - } - else - { - // We hit a '<' - // Have we hit a new element or an end tag? This could also be - // a TiXmlText in the "CDATA" style. - if ( StringEqual( p, "</", false, encoding ) ) - { - return p; - } - else - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, data, encoding ); - LinkEndChild( node ); - } - else - { - return 0; - } - } - } - pWithWhiteSpace = p; - p = SkipWhiteSpace( p, encoding ); - } - - if ( !p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding ); - } - return p; -} - - -#ifdef TIXML_USE_STL -void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - - -const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - TiXmlDocument* document = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - if ( !p || !*p || *p != '<' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); - return 0; - } - ++p; - value = ""; - - while ( p && *p && *p != '>' ) - { - value += *p; - ++p; - } - - if ( !p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); - } - if ( *p == '>' ) - return p+1; - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - - if ( c == '>' - && tag->at( tag->length() - 2 ) == '-' - && tag->at( tag->length() - 3 ) == '-' ) - { - // All is well. - return; - } - } -} -#endif - - -const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - TiXmlDocument* document = GetDocument(); - value = ""; - - p = SkipWhiteSpace( p, encoding ); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - const char* startTag = "<!--"; - const char* endTag = "-->"; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - <!-- declarations for <head> & <body> --> - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - -// int tabsize = 4; -// if ( document ) -// tabsize = document->TabSize(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) - { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) - { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) - { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = "<![CDATA["; - const char* const endTag = "]]>"; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while ( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i<value.length(); i++ ) - if ( !IsWhiteSpace( value[i] ) ) - return false; - return true; -} - diff --git a/resource.rc b/resource.rc index 6699cf44..21c8b8ce 100644 --- a/resource.rc +++ b/resource.rc @@ -3,3 +3,4 @@ //naming convention to set icon sequence in executable file A_PROGRAM_ICON ICON DISCARDABLE "library/FreeFileSync.ico" B_BATCH_ICON ICON DISCARDABLE "library/Batch.ico" +C_SYNC_DB_ICON ICON DISCARDABLE "library/SyncDB.ico" diff --git a/shared/appMain.cpp b/shared/appMain.cpp new file mode 100644 index 00000000..fe6d3af5 --- /dev/null +++ b/shared/appMain.cpp @@ -0,0 +1,24 @@ +#include "appMain.h" +#include <wx/window.h> +#include <wx/app.h> + +using namespace FreeFileSync; + + +bool AppMainWindow::mainWndAct = false; + + +void FreeFileSync::AppMainWindow::setMainWindow(wxWindow* window) +{ + wxTheApp->SetTopWindow(window); + wxTheApp->SetExitOnFrameDelete(true); + + assert (!mainWndAct); + mainWndAct = true; +} + + +bool AppMainWindow::mainWindowWasSet() +{ + return mainWndAct; +} diff --git a/shared/appMain.h b/shared/appMain.h new file mode 100644 index 00000000..130a6e2a --- /dev/null +++ b/shared/appMain.h @@ -0,0 +1,21 @@ +#ifndef APPMAIN_H_INCLUDED +#define APPMAIN_H_INCLUDED + +class wxWindow; + +namespace FreeFileSync +{ +//just some wrapper around a global variable representing the (logical) main application window +class AppMainWindow +{ +public: + static void setMainWindow(wxWindow* window); //set main window and enable "exit on frame delete" + static bool mainWindowWasSet(); + +private: + static bool mainWndAct; +}; +} + + +#endif // APPMAIN_H_INCLUDED diff --git a/shared/customButton.cpp b/shared/customButton.cpp index 4027d3ef..40c0397f 100644 --- a/shared/customButton.cpp +++ b/shared/customButton.cpp @@ -10,9 +10,9 @@ wxButtonWithImage::wxButtonWithImage(wxWindow *parent, long style, const wxValidator& validator, const wxString& name) : - wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name), - m_spaceAfter(0), - m_spaceBefore(0) + wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name), + m_spaceAfter(0), + m_spaceBefore(0) { setTextLabel(label); } diff --git a/shared/dragAndDrop.cpp b/shared/dragAndDrop.cpp index 9261d604..89f4da4d 100644 --- a/shared/dragAndDrop.cpp +++ b/shared/dragAndDrop.cpp @@ -19,9 +19,9 @@ class FFSFileDropEvent : public wxCommandEvent { public: FFSFileDropEvent(const wxString& nameDropped, const wxWindow* dropWindow) : - wxCommandEvent(FFS_DROP_FILE_EVENT), - nameDropped_(nameDropped), - dropWindow_(dropWindow) {} + wxCommandEvent(FFS_DROP_FILE_EVENT), + nameDropped_(nameDropped), + dropWindow_(dropWindow) {} virtual wxEvent* Clone() const { @@ -39,7 +39,7 @@ class WindowDropTarget : public wxFileDropTarget { public: WindowDropTarget(wxWindow* dropWindow) : - dropWindow_(dropWindow) {} + dropWindow_(dropWindow) {} virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) { @@ -68,10 +68,10 @@ DragDropOnMainDlg::DragDropOnMainDlg(wxWindow* dropWindow1, wxWindow* dropWindow2, wxDirPickerCtrl* dirPicker, wxComboBox* dirName) : - dropWindow1_(dropWindow1), - dropWindow2_(dropWindow2), - dirPicker_(dirPicker), - dirName_(dirName) + dropWindow1_(dropWindow1), + dropWindow2_(dropWindow2), + dirPicker_(dirPicker), + dirName_(dirName) { //prepare drag & drop dropWindow1->SetDropTarget(new WindowDropTarget(dropWindow1)); //takes ownership @@ -155,9 +155,9 @@ using FreeFileSync::DragDropOnDlg; DragDropOnDlg::DragDropOnDlg(wxWindow* dropWindow, wxDirPickerCtrl* dirPicker, wxTextCtrl* dirName) : - dropWindow_(dropWindow), - dirPicker_(dirPicker), - dirName_(dirName) + dropWindow_(dropWindow), + dirPicker_(dirPicker), + dirName_(dirName) { //prepare drag & drop dropWindow->SetDropTarget(new WindowDropTarget(dropWindow)); //takes ownership diff --git a/shared/dragAndDrop.h b/shared/dragAndDrop.h index a8c7561a..4e6bbd31 100644 --- a/shared/dragAndDrop.h +++ b/shared/dragAndDrop.h @@ -15,48 +15,48 @@ class wxFileDirPickerEvent; namespace FreeFileSync { - //add drag and drop functionality, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl +//add drag and drop functionality, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl - class DragDropOnMainDlg : private wxEvtHandler - { - public: - DragDropOnMainDlg(wxWindow* dropWindow1, - wxWindow* dropWindow2, - wxDirPickerCtrl* dirPicker, - wxComboBox* dirName); - - virtual ~DragDropOnMainDlg() {} - - virtual bool AcceptDrop(const wxString& dropName) = 0; //return true if drop should be processed +class DragDropOnMainDlg : private wxEvtHandler +{ +public: + DragDropOnMainDlg(wxWindow* dropWindow1, + wxWindow* dropWindow2, + wxDirPickerCtrl* dirPicker, + wxComboBox* dirName); - private: - void OnFilesDropped(FFSFileDropEvent& event); - void OnWriteDirManually(wxCommandEvent& event); - void OnDirSelected(wxFileDirPickerEvent& event); + virtual ~DragDropOnMainDlg() {} - const wxWindow* dropWindow1_; - const wxWindow* dropWindow2_; - wxDirPickerCtrl* dirPicker_; - wxComboBox* dirName_; - }; + virtual bool AcceptDrop(const wxString& dropName) = 0; //return true if drop should be processed +private: + void OnFilesDropped(FFSFileDropEvent& event); + void OnWriteDirManually(wxCommandEvent& event); + void OnDirSelected(wxFileDirPickerEvent& event); - class DragDropOnDlg: private wxEvtHandler - { - public: - DragDropOnDlg(wxWindow* dropWindow, - wxDirPickerCtrl* dirPicker, - wxTextCtrl* dirName); + const wxWindow* dropWindow1_; + const wxWindow* dropWindow2_; + wxDirPickerCtrl* dirPicker_; + wxComboBox* dirName_; +}; - private: - void OnFilesDropped(FFSFileDropEvent& event); - void OnWriteDirManually(wxCommandEvent& event); - void OnDirSelected(wxFileDirPickerEvent& event); - const wxWindow* dropWindow_; - wxDirPickerCtrl* dirPicker_; - wxTextCtrl* dirName_; - }; +class DragDropOnDlg: private wxEvtHandler +{ +public: + DragDropOnDlg(wxWindow* dropWindow, + wxDirPickerCtrl* dirPicker, + wxTextCtrl* dirName); + +private: + void OnFilesDropped(FFSFileDropEvent& event); + void OnWriteDirManually(wxCommandEvent& event); + void OnDirSelected(wxFileDirPickerEvent& event); + + const wxWindow* dropWindow_; + wxDirPickerCtrl* dirPicker_; + wxTextCtrl* dirName_; +}; } diff --git a/shared/fileError.h b/shared/fileError.h index f5c6bdbd..daf97910 100644 --- a/shared/fileError.h +++ b/shared/fileError.h @@ -6,20 +6,20 @@ namespace FreeFileSync { - class FileError //Exception class used to notify file/directory copy/delete errors - { - public: - FileError(const wxString& message) : - errorMessage(message) {} +class FileError //Exception class used to notify file/directory copy/delete errors +{ +public: + FileError(const wxString& message) : + errorMessage(message) {} - const wxString& show() const - { - return errorMessage; - } + const wxString& show() const + { + return errorMessage; + } - private: - wxString errorMessage; - }; +private: + wxString errorMessage; +}; } #endif // FILEERROR_H_INCLUDED diff --git a/shared/fileHandling.cpp b/shared/fileHandling.cpp index 55fd7ff5..cea701cc 100644 --- a/shared/fileHandling.cpp +++ b/shared/fileHandling.cpp @@ -1,6 +1,7 @@ #include "fileHandling.h" #include <wx/intl.h> #include "systemFunctions.h" +#include "globalFunctions.h" #include "systemConstants.h" #include "fileTraverser.h" #include <wx/file.h> @@ -8,6 +9,8 @@ #include <boost/bind.hpp> #include <algorithm> #include <wx/log.h> +#include <wx/datetime.h> +#include "stringConv.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -28,21 +31,30 @@ using FreeFileSync::FileError; Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname) -{ //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names. +{ + //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names. //Also improves usability. - Zstring dirnameTmp = dirname; + wxString dirnameTmp = zToWx(dirname); dirnameTmp.Trim(true); //remove whitespace characters from right dirnameTmp.Trim(false); //remove whitespace characters from left if (dirnameTmp.empty()) //an empty string is interpreted as "\"; this is not desired return Zstring(); - if (!dirnameTmp.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) - dirnameTmp += globalFunctions::FILE_NAME_SEPARATOR; + if (!dirnameTmp.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR))) + dirnameTmp += zToWx(globalFunctions::FILE_NAME_SEPARATOR); + + //replace macros + wxString timeNow = wxDateTime::Now().FormatISOTime(); + timeNow.Replace(wxT(":"), wxT("-")); + dirnameTmp.Replace(wxT("%time%"), timeNow.c_str()); + + const wxString dateToday = wxDateTime::Now().FormatISODate(); + dirnameTmp.Replace(wxT("%date%"), dateToday.c_str()); //don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix - return dirnameTmp; + return wxToZ(dirnameTmp); } @@ -64,7 +76,7 @@ public: private: RecycleBin() : - recycleBinAvailable(false) + recycleBinAvailable(false) { #ifdef FFS_WIN recycleBinAvailable = true; @@ -117,7 +129,8 @@ bool moveToRecycleBin(const Zstring& filename) //throw (std::logic_error) bool FreeFileSync::fileExists(const DefaultChar* filename) -{ //symbolic links (broken or not) are also treated as existing files! +{ + //symbolic links (broken or not) are also treated as existing files! #ifdef FFS_WIN // we must use GetFileAttributes() instead of the ANSI C functions because // it can cope with network (UNC) paths unlike them @@ -134,7 +147,8 @@ bool FreeFileSync::fileExists(const DefaultChar* filename) bool FreeFileSync::dirExists(const DefaultChar* dirname) -{ //symbolic links (broken or not) are also treated as existing directories! +{ + //symbolic links (broken or not) are also treated as existing directories! #ifdef FFS_WIN // we must use GetFileAttributes() instead of the ANSI C functions because // it can cope with network (UNC) paths unlike them @@ -166,15 +180,15 @@ bool FreeFileSync::symlinkExists(const DefaultChar* objname) bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo) { - wxLogNull noWxLogs; //prevent wxWidgets logging if dummy file creation failed + wxLogNull noWxLogs; //prevent wxWidgets logging if dummy file creation failed const Zstring dummyFileSource = pathFrom.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? - pathFrom + wxT("DeleteMe.tmp") : - pathFrom + globalFunctions::FILE_NAME_SEPARATOR + wxT("DeleteMe.tmp"); + pathFrom + DefaultStr("DeleteMe.tmp") : + pathFrom + globalFunctions::FILE_NAME_SEPARATOR + DefaultStr("DeleteMe.tmp"); const Zstring dummyFileTarget = pathTo.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? - pathTo + wxT("DeleteMe.tmp") : - pathTo + globalFunctions::FILE_NAME_SEPARATOR + wxT("DeleteMe.tmp"); + pathTo + DefaultStr("DeleteMe.tmp") : + pathTo + globalFunctions::FILE_NAME_SEPARATOR + DefaultStr("DeleteMe.tmp"); try { removeFile(dummyFileSource, false); @@ -184,7 +198,7 @@ bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo) //create dummy file { - wxFile dummy(dummyFileSource.c_str(), wxFile::write); + wxFile dummy(zToWx(dummyFileSource), wxFile::write); if (!dummy.IsOpened()) return false; //if there's no write access, files can't be moved neither dummy.Write(wxT("FreeFileSync dummy file. May be deleted safely.\n")); @@ -195,7 +209,7 @@ bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo) #ifdef FFS_WIN ::MoveFileEx(dummyFileSource.c_str(), //__in LPCTSTR lpExistingFileName, dummyFileTarget.c_str(), //__in_opt LPCTSTR lpNewFileName, - 0) != 0; //__in DWORD dwFlags + 0) != 0; //__in DWORD dwFlags #elif defined FFS_LINUX ::rename(dummyFileSource.c_str(), dummyFileTarget.c_str()) == 0; #endif @@ -227,7 +241,7 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin) if (useRecycleBin) { if (!moveToRecycleBin(filename)) - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + filename.c_str() + wxT("\"")); + throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(filename) + wxT("\"")); return; } @@ -237,20 +251,20 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin) filename.c_str(), //address of filename FILE_ATTRIBUTE_NORMAL)) //attributes to set { - wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } //remove file, support for \\?\-prefix if (!::DeleteFile(filename.c_str())) { - wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } #elif defined FFS_LINUX if (::unlink(filename.c_str()) != 0) { - wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } #endif @@ -286,7 +300,8 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile { if (fileExists(targetFile.c_str())) //test file existence: e.g. Linux might silently overwrite existing symlinks { - const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile + wxT("\" ->\n\"") + targetFile + wxT("\""); + const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + + zToWx(targetFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + _("Target file already existing!")); } @@ -303,7 +318,8 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile const DWORD lastError = ::GetLastError(); if (lastError != ERROR_NOT_SAME_DEVICE) { - const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + + zToWx(targetFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)); } @@ -318,14 +334,15 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile #elif defined FFS_LINUX //first try to move the file directly without copying - if (rename(sourceFile.c_str(), targetFile.c_str()) == 0) + if (::rename(sourceFile.c_str(), targetFile.c_str()) == 0) return; //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 (errno != EXDEV) { - const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(errno)); + const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + + zToWx(targetFile) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } //file is on a different volume: let's copy it @@ -349,8 +366,8 @@ public: typedef std::vector<std::pair<Zstring, Zstring> > NamePair; TraverseOneLevel(NamePair& filesShort, NamePair& dirsShort) : - m_files(filesShort), - m_dirs(dirsShort) {} + m_files(filesShort), + m_dirs(dirsShort) {} virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) { @@ -375,19 +392,22 @@ private: void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback) //throw (FileError); { + using namespace FreeFileSync; + //handle symbolic links - if (FreeFileSync::symlinkExists(sourceDir)) + if (symlinkExists(sourceDir)) { - FreeFileSync::createDirectory(targetDir, sourceDir, true); //copy symbolic link - FreeFileSync::removeDirectory(sourceDir, false); //if target is already another symlink or directory, sourceDir-symlink is silently deleted + createDirectory(targetDir, sourceDir, true); //copy symbolic link + removeDirectory(sourceDir, false); //if target is already another symlink or directory, sourceDir-symlink is silently deleted return; } - if (FreeFileSync::dirExists(targetDir)) + if (dirExists(targetDir)) { if (!ignoreExistingDirs) //directory or symlink exists { - const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir + wxT("\" ->\n\"") + targetDir + wxT("\""); + const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + + zToWx(sourceDir) + wxT("\" ->\n\"") + zToWx(targetDir) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + _("Target directory already existing!")); } } @@ -404,7 +424,8 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool const DWORD lastError = ::GetLastError(); if (lastError != ERROR_NOT_SAME_DEVICE) { - const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") + targetDir.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") + + zToWx(targetDir) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)); } #elif defined FFS_LINUX @@ -414,13 +435,14 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool //if moving failed treat as error (except when it tried to move to a different volume: in this case we will copy the directory) if (errno != EXDEV) { - const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") + targetDir.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(errno)); + const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + + zToWx(sourceDir) + wxT("\" ->\n\"") + zToWx(targetDir) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } #endif //create target - FreeFileSync::createDirectory(targetDir, sourceDir, false); //throw (FileError); + createDirectory(targetDir, sourceDir, false); //throw (FileError); } //call back once per folder @@ -431,8 +453,8 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool break; case MoveFileCallback::CANCEL: //an user aborted operation IS an error condition! - throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") + - targetDir.c_str() + wxT("\"") + wxT("\n\n") + _("Operation aborted!")); + throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") + + zToWx(targetDir) + wxT("\"") + wxT("\n\n") + _("Operation aborted!")); } //move files/folders recursively @@ -441,7 +463,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool //traverse source directory one level TraverseOneLevel traverseCallback(fileList, dirList); - FreeFileSync::traverseFolder(sourceDir, false, &traverseCallback); //traverse one level + traverseFolder(sourceDir, false, &traverseCallback); //traverse one level const Zstring targetDirFormatted = targetDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //ends with path separator targetDir : @@ -458,9 +480,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool //attention: if move-operation was cancelled an exception is thrown => sourceDir is not deleted, as we wish! //delete source - FreeFileSync::removeDirectory(sourceDir, false); //throw (FileError); - - return; + removeDirectory(sourceDir, false); //throw (FileError); } @@ -488,8 +508,8 @@ class FilesDirsOnlyTraverser : public FreeFileSync::TraverseCallback { public: FilesDirsOnlyTraverser(std::vector<Zstring>& files, std::vector<Zstring>& dirs) : - m_files(files), - m_dirs(dirs) {} + m_files(files), + m_dirs(dirs) {} virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) { @@ -529,7 +549,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc if (useRecycleBin) { if (!moveToRecycleBin(directory)) - throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + directory.c_str() + wxT("\"")); + throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(directory) + wxT("\"")); return; } @@ -561,7 +581,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc { if (::unlink(directory.c_str()) != 0) { - wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } return; @@ -585,17 +605,13 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc #ifdef FFS_WIN //remove directory, support for \\?\-prefix if (!::RemoveDirectory(directory.c_str())) - { - wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); - throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); - } #else if (::rmdir(directory.c_str()) != 0) +#endif { - wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } -#endif } @@ -697,8 +713,8 @@ public: private: KernelDllHandler() : - getFinalPathNameByHandle(NULL), - hKernel(NULL) + getFinalPathNameByHandle(NULL), + hKernel(NULL) { //get a handle to the DLL module containing required functionality hKernel = ::LoadLibrary(wxT("kernel32.dll")); @@ -748,50 +764,49 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa return targetPath; } - +//#warning teste //#include <aclapi.h> -//optionally: copy additional metadata, DO NOTHING if something fails +////optionally: copy additional metadata, DO NOTHING if something fails //void copyAdditionalMetadata(const Zstring& sourceDir, const Zstring& targetDir) //{ +// //copy NTFS permissions +// // PSECURITY_DESCRIPTOR pSD; // -// PSID pSidOwner; -// PSID pSidGroup; // PACL pDacl; -// PACL pSacl; // if (::GetNamedSecurityInfo( // const_cast<DefaultChar*>(sourceDir.c_str()), // SE_FILE_OBJECT, //file or directory -// OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, -// &pSidOwner, -// &pSidGroup, +// DACL_SECURITY_INFORMATION, +// NULL, +// NULL, // &pDacl, -// &pSacl, +// NULL, // &pSD // ) == ERROR_SUCCESS) // { // //(try to) set new security information // if (::SetNamedSecurityInfo( -// const_cast<DefaultChar*>(targetDir.c_str()), -// SE_FILE_OBJECT, //file or directory -// OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, -// pSidOwner, -// pSidGroup, -// pDacl, -// pSacl) != ERROR_SUCCESS) //return value not evalutated! -// { +// const_cast<DefaultChar*>(targetDir.c_str()), +// SE_FILE_OBJECT, //file or directory +// DACL_SECURITY_INFORMATION, +// NULL, +// NULL, +// pDacl, +// NULL) != ERROR_SUCCESS) //return value not evalutated! +// { // const wxString errorMessage = wxString(wxT("Error 2:")) + wxT("\n\"") + targetDir.c_str() + wxT("\""); // throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); // } -//warning BUG! // -// LocalFree(pSD); //pSidOwner, pSidGroup, pDacl, pSacl must not be freed! +//#warning BUG! +// LocalFree(pSD); // } // else -// { -// const wxString errorMessage = wxString(wxT("Error 1:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\""); -// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); -// } +// { +// const wxString errorMessage = wxString(wxT("Error 1:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\""); +// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); +// } // //} #endif @@ -799,6 +814,8 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa void createDirectoryRecursively(const Zstring& directory, const Zstring& templateDir, const bool copyDirectorySymLinks, const int level) { + using namespace FreeFileSync; + if (FreeFileSync::dirExists(directory)) return; @@ -882,7 +899,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat const int bytesWritten = readlink(templateDir.c_str(), buffer, BUFFER_SIZE); if (bytesWritten < 0 || bytesWritten == BUFFER_SIZE) { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + templateDir.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(templateDir) + wxT("\""); if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + FreeFileSync::getLastErrorFormatted(); throw FileError(errorMessage); } @@ -891,7 +908,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat if (symlink(buffer, directory.c_str()) != 0) { - wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } return; //symlink created successfully @@ -899,9 +916,9 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat } //default directory creation - if (mkdir(directory.c_str(), 0755) != 0 && level == 0) + if (::mkdir(directory.c_str(), 0755) != 0 && level == 0) { - wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } @@ -944,6 +961,24 @@ void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& temp } +Zstring createTempName(const Zstring& filename) +{ + Zstring output = filename + DefaultStr(".tmp"); + + //ensure uniqueness + if (FreeFileSync::fileExists(output)) + { + //if it's not unique, add a postfix number + int postfix = 1; + while (FreeFileSync::fileExists(output + DefaultChar('_') + numberToZstring(postfix))) + ++postfix; + + output += DefaultChar('_') + numberToZstring(postfix); + } + return output; +} + + #ifdef FFS_WIN #ifndef COPY_FILE_COPY_SYMLINK @@ -1011,8 +1046,8 @@ bool supportForSymbolicLinks() void FreeFileSync::copyFile(const Zstring& sourceFile, const Zstring& targetFile, const bool copyFileSymLinks, - ShadowCopy* shadowCopyHandler, - CopyFileCallback* callback) + FreeFileSync::ShadowCopy* shadowCopyHandler, + FreeFileSync::CopyFileCallback* callback) { DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS; @@ -1021,9 +1056,10 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, if (copyFileSymLinks && symlinksSupported) copyFlags |= COPY_FILE_COPY_SYMLINK; + const Zstring temporary = createTempName(targetFile); //use temporary file until a correct date has been set if (!::CopyFileEx( //same performance as CopyFile() sourceFile.c_str(), - targetFile.c_str(), + temporary.c_str(), copyCallbackInternal, callback, NULL, @@ -1039,17 +1075,26 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, lastError == ERROR_LOCK_VIOLATION)) { const Zstring shadowFilename(shadowCopyHandler->makeShadowCopy(sourceFile)); - FreeFileSync::copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied - targetFile, - copyFileSymLinks, - NULL, - callback); + copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied + targetFile, + copyFileSymLinks, + NULL, + callback); return; } const wxString errorMessage = wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)); } + + //rename temporary file + if (!::MoveFileEx(temporary.c_str(), //__in LPCTSTR lpExistingFileName, + targetFile.c_str(), //__in_opt LPCTSTR lpNewFileName, + 0)) //__in DWORD dwFlags + { + const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + temporary + wxT("\" ->\n\"") + targetFile + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + } } @@ -1079,7 +1124,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, using FreeFileSync::CopyFileCallback; if (FreeFileSync::fileExists(targetFile.c_str())) - throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"\n\n") + throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\"\n\n") + _("Target file already existing!")); //symbolic link handling @@ -1089,7 +1134,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, struct stat linkInfo; if (lstat(sourceFile.c_str(), &linkInfo) != 0) { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } @@ -1101,7 +1146,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, const int bytesWritten = readlink(sourceFile.c_str(), buffer, BUFFER_SIZE); if (bytesWritten < 0 || bytesWritten == BUFFER_SIZE) { - wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + FreeFileSync::getLastErrorFormatted(); throw FileError(errorMessage); } @@ -1110,7 +1155,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, if (symlink(buffer, targetFile.c_str()) != 0) { - const wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } @@ -1122,19 +1167,21 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, struct stat fileInfo; if (stat(sourceFile.c_str(), &fileInfo) != 0) //read file attributes from source file (resolving symlinks; but cannot be one in this context) { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } //open sourceFile for reading std::ifstream fileIn(sourceFile.c_str(), std::ios_base::binary); if (fileIn.fail()) - throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"")); //create targetFile and open it for writing - std::ofstream fileOut(targetFile.c_str(), std::ios_base::binary); + const Zstring temporary = createTempName(targetFile); //use temporary file until a correct date has been set + + std::ofstream fileOut(temporary.c_str(), std::ios_base::binary); if (fileOut.fail()) - throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"")); try { @@ -1148,16 +1195,16 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, { fileOut.write(memory.buffer, fileIn.gcount()); if (fileOut.bad()) - throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"")); + throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"")); break; } else if (fileIn.fail()) - throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\"")); + throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"")); fileOut.write(memory.buffer, memory.bufferSize); if (fileOut.bad()) - throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"")); + throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"")); totalBytesTransferred += memory.bufferSize; @@ -1171,8 +1218,8 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, case CopyFileCallback::CANCEL: //an user aborted operation IS an error condition! - throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + - targetFile.c_str() + wxT("\"\n\n") + _("Operation aborted!")); + throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + + zToWx(targetFile) + wxT("\"\n\n") + _("Operation aborted!")); } } } @@ -1183,25 +1230,35 @@ void FreeFileSync::copyFile(const Zstring& sourceFile, //adapt file modification time: struct utimbuf newTimes; - time(&newTimes.actime); //set file access time to current time + ::time(&newTimes.actime); //set file access time to current time newTimes.modtime = fileInfo.st_mtime; - if (utime(targetFile.c_str(), &newTimes) != 0) + if (utime(temporary.c_str(), &newTimes) != 0) { - wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""); + wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""); + throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); + } + + //rename temporary file + if (::rename(temporary.c_str(), targetFile.c_str()) != 0) + { + const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(temporary) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } //set file access rights - if (chmod(targetFile.c_str(), fileInfo.st_mode) != 0) + if (::chmod(targetFile.c_str(), fileInfo.st_mode) != 0) { - wxString errorMessage = wxString(_("Error writing file attributes:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error writing file attributes:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""); throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()); } } catch (...) - { //try to delete target file if error occured, or exception was thrown in callback function + { + //try to delete target file if error occured, or exception was thrown in callback function if (FreeFileSync::fileExists(targetFile)) ::unlink(targetFile); //don't handle error situations! + if (FreeFileSync::fileExists(temporary)) + ::unlink(temporary); //don't handle error situations! throw; } diff --git a/shared/fileHandling.h b/shared/fileHandling.h index 5ccd595f..d856603f 100644 --- a/shared/fileHandling.h +++ b/shared/fileHandling.h @@ -8,76 +8,74 @@ namespace FreeFileSync { - Zstring getFormattedDirectoryName(const Zstring& dirname); +Zstring getFormattedDirectoryName(const Zstring& dirname); - bool fileExists(const DefaultChar* filename); //throw() replaces wxFileExists()! - bool dirExists(const DefaultChar* dirname); //throw() replaces wxDirExists(): optional 'cause wxDirExists treats symlinks correctly - bool symlinkExists(const DefaultChar* objname); //throw() check if a symbolic link exists +bool fileExists(const DefaultChar* filename); //throw() replaces wxFileExists()! +bool dirExists(const DefaultChar* dirname); //throw() replaces wxDirExists(): optional 'cause wxDirExists treats symlinks correctly +bool symlinkExists(const DefaultChar* objname); //throw() check if a symbolic link exists - //check if files can be moved between two EXISTING paths (without copying) - bool isMovable(const Zstring& pathFrom, const Zstring& pathTo); //throw() +//check if files can be moved between two EXISTING paths (without copying) +bool isMovable(const Zstring& pathFrom, const Zstring& pathTo); //throw() - //optionally: copy directory last change date, DOES NOTHING if something fails - void copyDirLastChangeDate(const Zstring& sourceDir, const Zstring& targetDir); +//optionally: copy directory last change date, DOES NOTHING if something fails +void copyDirLastChangeDate(const Zstring& sourceDir, const Zstring& targetDir); - //recycler - bool recycleBinExists(); //test existence of Recycle Bin API on current system +//recycler +bool recycleBinExists(); //test existence of Recycle Bin API on current system - //file handling - void removeFile(const Zstring& filename, const bool useRecycleBin); //throw (FileError, std::logic_error) - void removeDirectory(const Zstring& directory, const bool useRecycleBin); //throw (FileError) +//file handling +void removeFile(const Zstring& filename, const bool useRecycleBin); //throw (FileError, std::logic_error) +void removeDirectory(const Zstring& directory, const bool useRecycleBin); //throw (FileError) - class MoveFileCallback //callback functionality +struct MoveFileCallback //callback functionality +{ + virtual ~MoveFileCallback() {} + + enum Response { - public: - virtual ~MoveFileCallback() {} - - enum Response - { - CONTINUE, - CANCEL - }; - virtual Response requestUiRefresh() = 0; //DON'T throw exceptions here, at least in Windows build! + CONTINUE, + CANCEL }; + virtual Response requestUiRefresh() = 0; //DON'T throw exceptions here, at least in Windows build! +}; - //move source to target; expectations: target not existing, all super-directories of target exist - void moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback = NULL); //throw (FileError); +//move source to target; expectations: target not existing, all super-directories of target exist +void moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback = NULL); //throw (FileError); - //move source to target including subdirectories - //"ignoreExistingDirs": existing directories will be enhanced as long as this is possible without overwriting files - void moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback = NULL); //throw (FileError); +//move source to target including subdirectories +//"ignoreExistingDirs": existing directories will be enhanced as long as this is possible without overwriting files +void moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback = NULL); //throw (FileError); - //creates superdirectories automatically: - void createDirectory(const Zstring& directory, const Zstring& templateDir = Zstring(), const bool copyDirectorySymLinks = false); //throw (FileError); +//creates superdirectories automatically: +void createDirectory(const Zstring& directory, const Zstring& templateDir = Zstring(), const bool copyDirectorySymLinks = false); //throw (FileError); + +struct CopyFileCallback //callback functionality +{ + virtual ~CopyFileCallback() {} - class CopyFileCallback //callback functionality + enum Response { - public: - virtual ~CopyFileCallback() {} - - enum Response - { - CONTINUE, - CANCEL - }; - virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build! + CONTINUE, + CANCEL }; + virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build! +}; #ifdef FFS_WIN - class ShadowCopy; +class ShadowCopy; - void copyFile(const Zstring& sourceFile, - const Zstring& targetFile, - const bool copyFileSymLinks, - ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies - CopyFileCallback* callback = NULL); //throw (FileError); +void copyFile(const Zstring& sourceFile, + const Zstring& targetFile, + const bool copyFileSymLinks, + ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies + CopyFileCallback* callback = NULL); //throw (FileError); #elif defined FFS_LINUX - void copyFile(const Zstring& sourceFile, - const Zstring& targetFile, - const bool copyFileSymLinks, - CopyFileCallback* callback = NULL); //throw (FileError); +void copyFile(const Zstring& sourceFile, + const Zstring& targetFile, + const bool copyFileSymLinks, + CopyFileCallback* callback = NULL); //throw (FileError); #endif } diff --git a/shared/fileTraverser.cpp b/shared/fileTraverser.cpp index ab223791..c323f1a3 100644 --- a/shared/fileTraverser.cpp +++ b/shared/fileTraverser.cpp @@ -2,6 +2,7 @@ #include "systemConstants.h" #include "systemFunctions.h" #include <wx/intl.h> +#include "stringConv.h" #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -108,11 +109,11 @@ private: template <bool traverseDirectorySymlinks> bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* sink, const int level) { - using FreeFileSync::TraverseCallback; + using namespace FreeFileSync; if (level == 100) //catch endless recursion { - switch (sink->onError(wxString(_("Endless loop when traversing directory:")) + wxT("\n\"") + directory + wxT("\""))) + switch (sink->onError(wxString(_("Endless loop when traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\""))) { case TraverseCallback::TRAVERSING_STOP: return false; @@ -139,7 +140,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* return true; //else: we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ; + const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError))) { case TraverseCallback::TRAVERSING_STOP: @@ -151,7 +152,8 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* CloseFindHandleOnExit dummy(searchHandle); do - { //don't return "." and ".." + { + //don't return "." and ".." const wxChar* const shortName = fileMetaData.cFileName; if ( shortName[0] == wxChar('.') && ((shortName[1] == wxChar('.') && shortName[2] == wxChar('\0')) || @@ -211,7 +213,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* return true; //everything okay //else: we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ; + const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError))) { case TraverseCallback::TRAVERSING_STOP: @@ -224,7 +226,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* DIR* dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/" if (dirObj == NULL) { - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ; + const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted())) { case TraverseCallback::TRAVERSING_STOP: @@ -245,7 +247,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* return true; //everything okay //else: we have a problem... report it: - const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ; + const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ; switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted())) { case TraverseCallback::TRAVERSING_STOP: @@ -256,7 +258,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* } //don't return "." and ".." - const wxChar* const shortName = dirEntry->d_name; + const DefaultChar* const shortName = dirEntry->d_name; if ( shortName[0] == wxChar('.') && ((shortName[1] == wxChar('.') && shortName[2] == wxChar('\0')) || shortName[1] == wxChar('\0'))) @@ -269,7 +271,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* struct stat fileInfo; if (lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks { - const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + fullName.c_str() + wxT("\""); + const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(fullName) + wxT("\""); switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted())) { case TraverseCallback::TRAVERSING_STOP: diff --git a/shared/fileTraverser.h b/shared/fileTraverser.h index d2aa7f3e..c1277d87 100644 --- a/shared/fileTraverser.h +++ b/shared/fileTraverser.h @@ -10,55 +10,55 @@ namespace FreeFileSync { - class TraverseCallback - { - public: - virtual ~TraverseCallback() {} - - enum ReturnValue - { - TRAVERSING_STOP, - TRAVERSING_CONTINUE - }; +class TraverseCallback +{ +public: + virtual ~TraverseCallback() {} - struct FileInfo - { - wxULongLong fileSize; //unit: bytes! - wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC - }; + enum ReturnValue + { + TRAVERSING_STOP, + TRAVERSING_CONTINUE + }; - class ReturnValDir - { - public: - //some proxy classes - class Stop {}; - class Ignore {}; - class Continue {}; + struct FileInfo + { + wxULongLong fileSize; //unit: bytes! + wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC + }; - ReturnValDir(const Stop&) : returnCode(TRAVERSING_STOP), subDirCb(NULL) {} - ReturnValDir(const Ignore&) : returnCode(TRAVERSING_IGNORE_DIR), subDirCb(NULL) {} - ReturnValDir(const Continue&, TraverseCallback* subDirCallback) : returnCode(TRAVERSING_CONTINUE), subDirCb(subDirCallback) {} + class ReturnValDir + { + public: + //some proxy classes + class Stop {}; + class Ignore {}; + class Continue {}; + ReturnValDir(const Stop&) : returnCode(TRAVERSING_STOP), subDirCb(NULL) {} + ReturnValDir(const Ignore&) : returnCode(TRAVERSING_IGNORE_DIR), subDirCb(NULL) {} + ReturnValDir(const Continue&, TraverseCallback* subDirCallback) : returnCode(TRAVERSING_CONTINUE), subDirCb(subDirCallback) {} - enum ReturnValueEnh - { - TRAVERSING_STOP, - TRAVERSING_IGNORE_DIR, - TRAVERSING_CONTINUE - }; - const ReturnValueEnh returnCode; - TraverseCallback* const subDirCb; + enum ReturnValueEnh + { + TRAVERSING_STOP, + TRAVERSING_IGNORE_DIR, + TRAVERSING_CONTINUE }; - //overwrite these virtual methods - virtual ReturnValue onError(const wxString& errorText) = 0; - virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) = 0; - virtual ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName) = 0; + const ReturnValueEnh returnCode; + TraverseCallback* const subDirCb; }; - //custom traverser with detail information about files - void traverseFolder(const Zstring& directory, const bool traverseDirectorySymlinks, TraverseCallback* sink); //throw() + //overwrite these virtual methods + virtual ReturnValue onError(const wxString& errorText) = 0; + virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) = 0; + virtual ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName) = 0; +}; + +//custom traverser with detail information about files +void traverseFolder(const Zstring& directory, const bool traverseDirectorySymlinks, TraverseCallback* sink); //throw() } #endif // FILETRAVERSER_H_INCLUDED diff --git a/shared/globalFunctions.cpp b/shared/globalFunctions.cpp index f50a3097..a5ebba68 100644 --- a/shared/globalFunctions.cpp +++ b/shared/globalFunctions.cpp @@ -1,49 +1,11 @@ #include "globalFunctions.h" #include <wx/msgdlg.h> #include <wx/file.h> -#include <fstream> -#include <wx/stream.h> #include <wx/stopwatch.h> #include <cmath> #include "systemConstants.h" -wxString globalFunctions::numberToWxString(const unsigned int number) -{ - return wxString::Format(wxT("%u"), number); -} - - -wxString globalFunctions::numberToWxString(const int number) -{ - return wxString::Format(wxT("%i"), number); -} - - -wxString globalFunctions::numberToWxString(const float number) -{ - return wxString::Format(wxT("%f"), number); -} - - -int globalFunctions::stringToInt(const std::string& number) -{ - return atoi(number.c_str()); -} - - -long globalFunctions::stringToLong(const std::string& number) -{ - return atol(number.c_str()); -} - - -double globalFunctions::stringToDouble(const std::string& number) -{ - return atof(number.c_str()); -} - - int globalFunctions::wxStringToInt(const wxString& number) { long result = 0; @@ -70,42 +32,10 @@ unsigned int globalFunctions::getDigitCount(const unsigned int number) //count n } -int globalFunctions::readInt(std::ifstream& stream) -{ - int result = 0; - char* buffer = reinterpret_cast<char*>(&result); - stream.read(buffer, sizeof(int)); - return result; -} - - -void globalFunctions::writeInt(std::ofstream& stream, const int number) -{ - const char* buffer = reinterpret_cast<const char*>(&number); - stream.write(buffer, sizeof(int)); -} - - -int globalFunctions::readInt(wxInputStream& stream) -{ - int result = 0; - char* buffer = reinterpret_cast<char*>(&result); - stream.Read(buffer, sizeof(int)); - return result; -} - - -void globalFunctions::writeInt(wxOutputStream& stream, const int number) -{ - const char* buffer = reinterpret_cast<const char*>(&number); - stream.Write(buffer, sizeof(int)); -} - - //############################################################################ Performance::Performance() : - resultWasShown(false), - timer(new wxStopWatch) + resultWasShown(false), + timer(new wxStopWatch) { timer->Start(); } @@ -128,8 +58,8 @@ void Performance::showResult() //############################################################################ DebugLog::DebugLog() : - lineCount(0), - logFile(NULL) + lineCount(0), + logFile(NULL) { logFile = new wxFile; logfileName = assembleFileName(); diff --git a/shared/globalFunctions.h b/shared/globalFunctions.h index b53ba596..74387959 100644 --- a/shared/globalFunctions.h +++ b/shared/globalFunctions.h @@ -9,6 +9,8 @@ #include <wx/longlong.h> #include <memory> #include <sstream> +#include <fstream> +#include <wx/stream.h> class wxInputStream; class wxOutputStream; @@ -20,129 +22,131 @@ namespace globalFunctions //------------------------------------------------ // FUNCTIONS //------------------------------------------------ - inline - int round(double d) //little rounding function - { - return static_cast<int>(d < 0 ? d - .5 : d + .5); - } +inline +int round(double d) //little rounding function +{ + return static_cast<int>(d < 0 ? d - .5 : d + .5); +} - template <class T> - inline - T abs(const T& d) //absolute value - { - return(d < 0 ? -d : d); - } +template <class T> +inline +T abs(const T& d) //absolute value +{ + return(d < 0 ? -d : d); +} - template <class T> - inline std::string numberToString(const T& number) //convert number to string the C++ way - { - std::stringstream ss; - ss << number; - return ss.str(); - } +template <class T> +inline +std::string numberToString(const T& number) //convert number to string the C++ way +{ + std::stringstream ss; + ss << number; + return ss.str(); +} - wxString numberToWxString(const unsigned int number); //convert number to wxString - wxString numberToWxString(const int number); //convert number to wxString - wxString numberToWxString(const float number); //convert number to wxString +wxString numberToWxString(const unsigned int number); //convert number to wxString +wxString numberToWxString(const int number); //convert number to wxString +wxString numberToWxString(const float number); //convert number to wxString - int stringToInt( const std::string& number); //convert String to number - long stringToLong( const std::string& number); //convert String to number - double stringToDouble(const std::string& number); //convert String to number +int stringToInt( const std::string& number); //convert String to number +long stringToLong( const std::string& number); //convert String to number +double stringToDouble(const std::string& number); //convert String to number - int wxStringToInt( const wxString& number); //convert wxString to number - double wxStringToDouble(const wxString& number); //convert wxString to number +int wxStringToInt( const wxString& number); //convert wxString to number +double wxStringToDouble(const wxString& number); //convert wxString to number - unsigned int getDigitCount(const unsigned int number); //count number of digits +unsigned int getDigitCount(const unsigned int number); //count number of digits - int readInt(std::ifstream& stream); //read int from file stream - void writeInt(std::ofstream& stream, const int number); //write int to filestream +//read/write numbers: int, long, unsigned int ... ect +template <class T> T readNumber(std::ifstream& stream); +template <class T> void writeNumber(std::ofstream& stream, T number); - int readInt(wxInputStream& stream); //read int from file stream - void writeInt(wxOutputStream& stream, const int number); //write int to filestream +template <class T> T readNumber(wxInputStream& stream); +template <class T> void writeNumber(wxOutputStream& stream, T number); - inline - wxLongLong convertToSigned(const wxULongLong number) - { - return wxLongLong(number.GetHi(), number.GetLo()); - } +inline +wxLongLong convertToSigned(const wxULongLong number) +{ + return wxLongLong(number.GetHi(), number.GetLo()); +} //Note: the following lines are a performance optimization for deleting elements from a vector: linear runtime at most! - template <class T> - void removeRowsFromVector(const std::set<unsigned int>& rowsToRemove, std::vector<T>& grid) - { - if (rowsToRemove.empty()) - return; +template <class T> +void removeRowsFromVector(const std::set<unsigned int>& rowsToRemove, std::vector<T>& grid) +{ + if (rowsToRemove.empty()) + return; - std::set<unsigned int>::const_iterator rowToSkipIndex = rowsToRemove.begin(); - unsigned int rowToSkip = *rowToSkipIndex; + std::set<unsigned int>::const_iterator rowToSkipIndex = rowsToRemove.begin(); + unsigned int rowToSkip = *rowToSkipIndex; - if (rowToSkip >= grid.size()) - return; + if (rowToSkip >= grid.size()) + return; - typename std::vector<T>::iterator insertPos = grid.begin() + rowToSkip; + typename std::vector<T>::iterator insertPos = grid.begin() + rowToSkip; - for (unsigned int i = rowToSkip; i < grid.size(); ++i) + for (unsigned int i = rowToSkip; i < grid.size(); ++i) + { + if (i != rowToSkip) { - if (i != rowToSkip) - { - *insertPos = grid[i]; - ++insertPos; - } - else - { - ++rowToSkipIndex; - if (rowToSkipIndex != rowsToRemove.end()) - rowToSkip = *rowToSkipIndex; - } + *insertPos = grid[i]; + ++insertPos; } - grid.erase(insertPos, grid.end()); - } - - //bubble sort using swap() instead of assignment: useful if assignment is very expensive - template <class VectorData, typename CompareFct> - void bubbleSwapSort(VectorData& folderCmp, CompareFct compare) - { - for (int i = folderCmp.size() - 2; i >= 0; --i) + else { - bool swapped = false; - for (int j = 0; j <= i; ++j) - if (compare(folderCmp[j + 1], folderCmp[j])) - { - folderCmp[j + 1].swap(folderCmp[j]); - swapped = true; - } - - if (!swapped) - return; + ++rowToSkipIndex; + if (rowToSkipIndex != rowsToRemove.end()) + rowToSkip = *rowToSkipIndex; } } + grid.erase(insertPos, grid.end()); +} - //enhanced binary search template: returns an iterator - template <class ForwardIterator, class T> - inline - ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value) +//bubble sort using swap() instead of assignment: useful if assignment is very expensive +template <class VectorData, typename CompareFct> +void bubbleSwapSort(VectorData& folderCmp, CompareFct compare) +{ + for (int i = folderCmp.size() - 2; i >= 0; --i) { - first = lower_bound(first, last, value); - if (first != last && !(value < *first)) - return first; - else - return last; - } + bool swapped = false; + for (int j = 0; j <= i; ++j) + if (compare(folderCmp[j + 1], folderCmp[j])) + { + folderCmp[j + 1].swap(folderCmp[j]); + swapped = true; + } - //enhanced binary search template: returns an iterator - template <class ForwardIterator, class T, typename Compare> - inline - ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) - { - first = lower_bound(first, last, value, comp); - if (first != last && !comp(value, *first)) - return first; - else - return last; + if (!swapped) + return; } } +//enhanced binary search template: returns an iterator +template <class ForwardIterator, class T> +inline +ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value) +{ + first = lower_bound(first, last, value); + if (first != last && !(value < *first)) + return first; + else + return last; +} + +//enhanced binary search template: returns an iterator +template <class ForwardIterator, class T, typename Compare> +inline +ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) +{ + first = lower_bound(first, last, value, comp); + if (first != last && !comp(value, *first)) + return first; + else + return last; +} +} + //############################################################################ class Performance @@ -185,4 +189,96 @@ wxString getCodeLocation(const wxString file, const int line); //speed alternative: wxLogDebug(wxT("text")) + DebugView + + + + + + + + + + + + + +//---------------Inline Implementation--------------------------------------------------- +template <class T> +inline +T globalFunctions::readNumber(std::ifstream& stream) +{ + T result = 0; + stream.read(reinterpret_cast<char*>(&result), sizeof(T)); + return result; +} + + +template <class T> +inline +void globalFunctions::writeNumber(std::ofstream& stream, T number) +{ + stream.write(reinterpret_cast<const char*>(&number), sizeof(T)); +} + + +template <class T> +inline +T globalFunctions::readNumber(wxInputStream& stream) +{ + T result = 0; + stream.Read(&result, sizeof(T)); + return result; +} + + +template <class T> +inline +void globalFunctions::writeNumber(wxOutputStream& stream, T number) +{ + stream.Write(&number, sizeof(T)); +} + + +inline +wxString globalFunctions::numberToWxString(const unsigned int number) +{ + return wxString::Format(wxT("%u"), number); +} + + +inline +wxString globalFunctions::numberToWxString(const int number) +{ + return wxString::Format(wxT("%i"), number); +} + + +inline +wxString globalFunctions::numberToWxString(const float number) +{ + return wxString::Format(wxT("%f"), number); +} + + +inline +int globalFunctions::stringToInt(const std::string& number) +{ + return atoi(number.c_str()); +} + + +inline +long globalFunctions::stringToLong(const std::string& number) +{ + return atol(number.c_str()); +} + + +inline +double globalFunctions::stringToDouble(const std::string& number) +{ + return atof(number.c_str()); +} + + #endif // GLOBALFUNCTIONS_H_INCLUDED diff --git a/shared/localization.cpp b/shared/localization.cpp index 20bf6d2e..ff14c980 100644 --- a/shared/localization.cpp +++ b/shared/localization.cpp @@ -1,6 +1,7 @@ #include "localization.h" #include <wx/msgdlg.h> #include "../shared/standardPaths.h" +#include "../shared/stringConv.h" #include "systemConstants.h" #include <fstream> #include <map> @@ -112,6 +113,13 @@ LocalizationInfo::LocalizationInfo() newEntry.languageFlag = wxT("brazil.png"); locMapping.push_back(newEntry); + newEntry.languageID = wxLANGUAGE_ROMANIAN; + newEntry.languageName = wxT("Română"); + newEntry.languageFile = wxT("romanian.lng"); + newEntry.translatorName = wxT("Alexandru Bogdan Munteanu"); + newEntry.languageFlag = wxT("romania.png"); + locMapping.push_back(newEntry); + newEntry.languageID = wxLANGUAGE_SLOVENIAN; newEntry.languageName = wxT("SlovenÅ¡Äina"); newEntry.languageFile = wxT("slovenian.lng"); @@ -119,6 +127,13 @@ LocalizationInfo::LocalizationInfo() newEntry.languageFlag = wxT("slovakia.png"); locMapping.push_back(newEntry); + newEntry.languageID = wxLANGUAGE_TURKISH; + newEntry.languageName = wxT("Türkçe"); + newEntry.languageFile = wxT("turkish.lng"); + newEntry.translatorName = wxT("H.Barbaros BIÇAKCI"); + newEntry.languageFlag = wxT("turkey.png"); + locMapping.push_back(newEntry); + newEntry.languageID = wxLANGUAGE_JAPANESE; newEntry.languageName = wxT("日本語"); newEntry.languageFile = wxT("japanese.lng"); @@ -236,9 +251,9 @@ CustomLocale& CustomLocale::getInstance() CustomLocale::CustomLocale() : - wxLocale(wxLANGUAGE_DEFAULT), //setting a different language needn't be supported on all systems! - translationDB(new Translation), - currentLanguage(wxLANGUAGE_ENGLISH) {} + wxLocale(wxLANGUAGE_DEFAULT), //setting a different language needn't be supported on all systems! + translationDB(new Translation), + currentLanguage(wxLANGUAGE_ENGLISH) {} inline @@ -290,7 +305,7 @@ class UnicodeFileReader { public: UnicodeFileReader(const wxString& filename) : - inputFile(NULL) + inputFile(NULL) { //workaround to get a FILE* from a unicode filename wxFFile dummyFile(filename, wxT("rb")); @@ -363,8 +378,8 @@ void CustomLocale::setLanguage(const int language) translationDB->clear(); if (!languageFile.empty()) { - UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + - wxT("Languages") + globalFunctions::FILE_NAME_SEPARATOR + languageFile); + UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + + wxT("Languages") + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + languageFile); if (langFile.isOkay()) { int rowNumber = 0; diff --git a/shared/localization.h b/shared/localization.h index 2a5ee80d..0a5ca4fb 100644 --- a/shared/localization.h +++ b/shared/localization.h @@ -10,53 +10,55 @@ class Translation; namespace FreeFileSync { - //language dependent global variables: need to be initialized by CustomLocale on program startup and language switch +//language dependent global variables: need to be initialized by CustomLocale on program startup and language switch - extern const wxChar* THOUSANDS_SEPARATOR; - extern const wxChar* DECIMAL_POINT; +extern const wxChar* THOUSANDS_SEPARATOR; +extern const wxChar* DECIMAL_POINT; - struct LocInfoLine - { - int languageID; - wxString languageName; - wxString languageFile; - wxString translatorName; - wxString languageFlag; - }; - - class LocalizationInfo - { - public: - static const std::vector<LocInfoLine>& getMapping(); +struct LocInfoLine +{ + int languageID; + wxString languageName; + wxString languageFile; + wxString translatorName; + wxString languageFlag; +}; + +class LocalizationInfo +{ +public: + static const std::vector<LocInfoLine>& getMapping(); - private: - LocalizationInfo(); +private: + LocalizationInfo(); + LocalizationInfo(const LocalizationInfo&); + LocalizationInfo& operator=(const LocalizationInfo&); - std::vector<LocInfoLine> locMapping; - }; + std::vector<LocInfoLine> locMapping; +}; - class CustomLocale : public wxLocale - { - public: - static CustomLocale& getInstance(); +class CustomLocale : public wxLocale +{ +public: + static CustomLocale& getInstance(); - void setLanguage(const int language); + void setLanguage(const int language); - int getLanguage() const - { - return currentLanguage; - } + int getLanguage() const + { + return currentLanguage; + } - virtual const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const; + virtual const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const; - private: - CustomLocale(); +private: + CustomLocale(); - std::auto_ptr<Translation> translationDB; - int currentLanguage; - }; + std::auto_ptr<Translation> translationDB; + int currentLanguage; +}; } #endif // MISC_H_INCLUDED diff --git a/shared/loki/AbstractFactory.h b/shared/loki/AbstractFactory.h new file mode 100644 index 00000000..8ff518dc --- /dev/null +++ b/shared/loki/AbstractFactory.h @@ -0,0 +1,185 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_ABSTRACTFACTORY_INC_ +#define LOKI_ABSTRACTFACTORY_INC_ + +// $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $ + + +#include "Typelist.h" +#include "Sequence.h" +#include "TypeManip.h" +#include "HierarchyGenerators.h" + +#include <cassert> + +/** + * \defgroup FactoriesGroup Factories + * \defgroup AbstractFactoryGroup Abstract Factory + * \ingroup FactoriesGroup + * \brief Implements an abstract object factory. + */ + +/** + * \class AbstractFactory + * \ingroup AbstractFactoryGroup + * \brief Implements an abstract object factory. + */ + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +// class template AbstractFactoryUnit +// The building block of an Abstract Factory +//////////////////////////////////////////////////////////////////////////////// + + template <class T> + class AbstractFactoryUnit + { + public: + virtual T* DoCreate(Type2Type<T>) = 0; + virtual ~AbstractFactoryUnit() {} + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template AbstractFactory +// Defines an Abstract Factory interface starting from a typelist +//////////////////////////////////////////////////////////////////////////////// + + template + < + class TList, + template <class> class Unit = AbstractFactoryUnit + > + class AbstractFactory : public GenScatterHierarchy<TList, Unit> + { + public: + typedef TList ProductList; + + template <class T> T* Create() + { + Unit<T>& unit = *this; + return unit.DoCreate(Type2Type<T>()); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template OpNewFactoryUnit +// Creates an object by invoking the new operator +//////////////////////////////////////////////////////////////////////////////// + + template <class ConcreteProduct, class Base> + class OpNewFactoryUnit : public Base + { + typedef typename Base::ProductList BaseProductList; + + protected: + typedef typename BaseProductList::Tail ProductList; + + public: + typedef typename BaseProductList::Head AbstractProduct; + ConcreteProduct* DoCreate(Type2Type<AbstractProduct>) + { + return new ConcreteProduct; + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template PrototypeFactoryUnit +// Creates an object by cloning a prototype +// There is a difference between the implementation herein and the one described +// in the book: GetPrototype and SetPrototype use the helper friend +// functions DoGetPrototype and DoSetPrototype. The friend functions avoid +// name hiding issues. Plus, GetPrototype takes a reference to pointer +// instead of returning the pointer by value. +//////////////////////////////////////////////////////////////////////////////// + + template <class ConcreteProduct, class Base> + class PrototypeFactoryUnit : public Base + { + typedef typename Base::ProductList BaseProductList; + + protected: + typedef typename BaseProductList::Tail ProductList; + + public: + typedef typename BaseProductList::Head AbstractProduct; + + PrototypeFactoryUnit(AbstractProduct* p = 0) + : pPrototype_(p) + {} + + template <class CP, class Base1> + friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me, + typename Base1::ProductList::Head*& pPrototype); + + template <class CP, class Base1> + friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me, + typename Base1::ProductList::Head* pObj); + + template <class U> + void GetPrototype(U*& p) + { return DoGetPrototype(*this, p); } + + template <class U> + void SetPrototype(U* pObj) + { DoSetPrototype(*this, pObj); } + + AbstractProduct* DoCreate(Type2Type<AbstractProduct>) + { + assert(pPrototype_); + return pPrototype_->Clone(); + } + + private: + AbstractProduct* pPrototype_; + }; + + template <class CP, class Base> + inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me, + typename Base::ProductList::Head*& pPrototype) + { pPrototype = me.pPrototype_; } + + template <class CP, class Base> + inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me, + typename Base::ProductList::Head* pObj) + { me.pPrototype_ = pObj; } + +//////////////////////////////////////////////////////////////////////////////// +// class template ConcreteFactory +// Implements an AbstractFactory interface +//////////////////////////////////////////////////////////////////////////////// + + template + < + class AbstractFact, + template <class, class> class Creator = OpNewFactoryUnit, + class TList = typename AbstractFact::ProductList + > + class ConcreteFactory + : public GenLinearHierarchy< + typename TL::Reverse<TList>::Result, Creator, AbstractFact> + { + public: + typedef typename AbstractFact::ProductList ProductList; + typedef TList ConcreteProductList; + }; + +} // namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/Allocator.h b/shared/loki/Allocator.h new file mode 100644 index 00000000..a79ee061 --- /dev/null +++ b/shared/loki/Allocator.h @@ -0,0 +1,153 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2008 by Rich Sposato +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_ALLOCATOR_HPP_INCLUDED +#define LOKI_ALLOCATOR_HPP_INCLUDED + +// $Id: Allocator.h 896 2008-08-08 22:20:05Z syntheticpp $ + +// Requires project to be compiled with loki/src/SmallObj.cpp and loki/src/Singleton.cpp + +#include <loki/SmallObj.h> + + +namespace Loki +{ + + +//----------------------------------------------------------------------------- + +/** @class LokiAllocator + Adapts Loki's Small-Object Allocator for STL container classes. + This class provides all the functionality required for STL allocators, but + uses Loki's Small-Object Allocator to perform actual memory operations. + Implementation comes from a post in Loki forums (by Rasmus Ekman?). + */ +template +< + typename Type, + typename AllocT = Loki::AllocatorSingleton<> +> +class LokiAllocator +{ +public: + + typedef ::std::size_t size_type; + typedef ::std::ptrdiff_t difference_type; + typedef Type * pointer; + typedef const Type * const_pointer; + typedef Type & reference; + typedef const Type & const_reference; + typedef Type value_type; + + /// Default constructor does nothing. + inline LokiAllocator( void ) throw() { } + + /// Copy constructor does nothing. + inline LokiAllocator( const LokiAllocator & ) throw() { } + + /// Type converting allocator constructor does nothing. + template < typename Type1 > + inline LokiAllocator( const LokiAllocator< Type1 > & ) throw() { } + + /// Destructor does nothing. + inline ~LokiAllocator() throw() { } + + /// Convert an allocator<Type> to an allocator <Type1>. + template < typename Type1 > + struct rebind + { + typedef LokiAllocator< Type1 > other; + }; + + /// Return address of reference to mutable element. + pointer address( reference elem ) const { return &elem; } + + /// Return address of reference to const element. + const_pointer address( const_reference elem ) const { return &elem; } + + /** Allocate an array of count elements. Warning! The true parameter in + the call to Allocate means this function can throw exceptions. This is + better than not throwing, and returning a null pointer in case the caller + assumes the return value is not null. + @param count # of elements in array. + @param hint Place where caller thinks allocation should occur. + @return Pointer to block of memory. + */ + pointer allocate( size_type count, const void * hint = 0 ) + { + (void)hint; // Ignore the hint. + void * p = AllocT::Instance().Allocate( count * sizeof( Type ), true ); + return reinterpret_cast< pointer >( p ); + } + + /// Ask allocator to release memory at pointer with size bytes. + void deallocate( pointer p, size_type size ) + { + AllocT::Instance().Deallocate( p, size * sizeof( Type ) ); + } + + /// Calculate max # of elements allocator can handle. + size_type max_size( void ) const throw() + { + // A good optimizer will see these calculations always produce the same + // value and optimize this function away completely. + const size_type max_bytes = size_type( -1 ); + const size_type bytes = max_bytes / sizeof( Type ); + return bytes; + } + + /// Construct an element at the pointer. + void construct( pointer p, const Type & value ) + { + // A call to global placement new forces a call to copy constructor. + ::new( p ) Type( value ); + } + + /// Destruct the object at pointer. + void destroy( pointer p ) + { + // If the Type has no destructor, then some compilers complain about + // an unreferenced parameter, so use the void cast trick to prevent + // spurious warnings. + (void)p; + p->~Type(); + } + +}; + +//----------------------------------------------------------------------------- + +/** All equality operators return true since LokiAllocator is basically a + monostate design pattern, so all instances of it are identical. + */ +template < typename Type > +inline bool operator == ( const LokiAllocator< Type > &, const LokiAllocator< Type > & ) +{ + return true; +} + +/** All inequality operators return false since LokiAllocator is basically a + monostate design pattern, so all instances of it are identical. + */ +template < typename Type > +inline bool operator != ( const LokiAllocator< Type > & , const LokiAllocator< Type > & ) +{ + return false; +} + +//----------------------------------------------------------------------------- + +} // namespace Loki + +#endif // LOKI_ALLOCATOR_INCLUDED diff --git a/shared/loki/AssocVector.h b/shared/loki/AssocVector.h new file mode 100644 index 00000000..905e0963 --- /dev/null +++ b/shared/loki/AssocVector.h @@ -0,0 +1,358 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_ASSOCVECTOR_INC_ +#define LOKI_ASSOCVECTOR_INC_ + +// $Id: AssocVector.h 765 2006-10-18 13:55:32Z syntheticpp $ + + +#include <algorithm> +#include <functional> +#include <vector> +#include <utility> + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template AssocVectorCompare +// Used by AssocVector +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class Value, class C> + class AssocVectorCompare : public C + { + typedef std::pair<typename C::first_argument_type, Value> + Data; + typedef typename C::first_argument_type first_argument_type; + + public: + AssocVectorCompare() + {} + + AssocVectorCompare(const C& src) : C(src) + {} + + bool operator()(const first_argument_type& lhs, + const first_argument_type& rhs) const + { return C::operator()(lhs, rhs); } + + bool operator()(const Data& lhs, const Data& rhs) const + { return operator()(lhs.first, rhs.first); } + + bool operator()(const Data& lhs, + const first_argument_type& rhs) const + { return operator()(lhs.first, rhs); } + + bool operator()(const first_argument_type& lhs, + const Data& rhs) const + { return operator()(lhs, rhs.first); } + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template AssocVector +// An associative vector built as a syntactic drop-in replacement for std::map +// BEWARE: AssocVector doesn't respect all map's guarantees, the most important +// being: +// * iterators are invalidated by insert and erase operations +// * the complexity of insert/erase is O(N) not O(log N) +// * value_type is std::pair<K, V> not std::pair<const K, V> +// * iterators are random +//////////////////////////////////////////////////////////////////////////////// + + + template + < + class K, + class V, + class C = std::less<K>, + class A = std::allocator< std::pair<K, V> > + > + class AssocVector + : private std::vector< std::pair<K, V>, A > + , private Private::AssocVectorCompare<V, C> + { + typedef std::vector<std::pair<K, V>, A> Base; + typedef Private::AssocVectorCompare<V, C> MyCompare; + + public: + typedef K key_type; + typedef V mapped_type; + typedef typename Base::value_type value_type; + + typedef C key_compare; + typedef A allocator_type; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::size_type size_type; + typedef typename Base::difference_type difference_type; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename Base::reverse_iterator reverse_iterator; + typedef typename Base::const_reverse_iterator const_reverse_iterator; + + class value_compare + : public std::binary_function<value_type, value_type, bool> + , private key_compare + { + friend class AssocVector; + + protected: + value_compare(key_compare pred) : key_compare(pred) + {} + + public: + bool operator()(const value_type& lhs, const value_type& rhs) const + { return key_compare::operator()(lhs.first, rhs.first); } + }; + + // 23.3.1.1 construct/copy/destroy + + explicit AssocVector(const key_compare& comp = key_compare(), + const A& alloc = A()) + : Base(alloc), MyCompare(comp) + {} + + template <class InputIterator> + AssocVector(InputIterator first, InputIterator last, + const key_compare& comp = key_compare(), + const A& alloc = A()) + : Base(first, last, alloc), MyCompare(comp) + { + MyCompare& me = *this; + std::sort(begin(), end(), me); + } + + AssocVector& operator=(const AssocVector& rhs) + { + AssocVector(rhs).swap(*this); + return *this; + } + + // iterators: + // The following are here because MWCW gets 'using' wrong + iterator begin() { return Base::begin(); } + const_iterator begin() const { return Base::begin(); } + iterator end() { return Base::end(); } + const_iterator end() const { return Base::end(); } + reverse_iterator rbegin() { return Base::rbegin(); } + const_reverse_iterator rbegin() const { return Base::rbegin(); } + reverse_iterator rend() { return Base::rend(); } + const_reverse_iterator rend() const { return Base::rend(); } + + // capacity: + bool empty() const { return Base::empty(); } + size_type size() const { return Base::size(); } + size_type max_size() { return Base::max_size(); } + + // 23.3.1.2 element access: + mapped_type& operator[](const key_type& key) + { return insert(value_type(key, mapped_type())).first->second; } + + // modifiers: + std::pair<iterator, bool> insert(const value_type& val) + { + bool found(true); + iterator i(lower_bound(val.first)); + + if (i == end() || this->operator()(val.first, i->first)) + { + i = Base::insert(i, val); + found = false; + } + return std::make_pair(i, !found); + } + //Section [23.1.2], Table 69 + //http://developer.apple.com/documentation/DeveloperTools/gcc-3.3/libstdc++/23_containers/howto.html#4 + iterator insert(iterator pos, const value_type& val) + { + if( (pos == begin() || this->operator()(*(pos-1),val)) && + (pos == end() || this->operator()(val, *pos)) ) + { + return Base::insert(pos, val); + } + return insert(val).first; + } + + template <class InputIterator> + void insert(InputIterator first, InputIterator last) + { for (; first != last; ++first) insert(*first); } + + void erase(iterator pos) + { Base::erase(pos); } + + size_type erase(const key_type& k) + { + iterator i(find(k)); + if (i == end()) return 0; + erase(i); + return 1; + } + + void erase(iterator first, iterator last) + { Base::erase(first, last); } + + void swap(AssocVector& other) + { + Base::swap(other); + MyCompare& me = *this; + MyCompare& rhs = other; + std::swap(me, rhs); + } + + void clear() + { Base::clear(); } + + // observers: + key_compare key_comp() const + { return *this; } + + value_compare value_comp() const + { + const key_compare& comp = *this; + return value_compare(comp); + } + + // 23.3.1.3 map operations: + iterator find(const key_type& k) + { + iterator i(lower_bound(k)); + if (i != end() && this->operator()(k, i->first)) + { + i = end(); + } + return i; + } + + const_iterator find(const key_type& k) const + { + const_iterator i(lower_bound(k)); + if (i != end() && this->operator()(k, i->first)) + { + i = end(); + } + return i; + } + + size_type count(const key_type& k) const + { return find(k) != end(); } + + iterator lower_bound(const key_type& k) + { + MyCompare& me = *this; + return std::lower_bound(begin(), end(), k, me); + } + + const_iterator lower_bound(const key_type& k) const + { + const MyCompare& me = *this; + return std::lower_bound(begin(), end(), k, me); + } + + iterator upper_bound(const key_type& k) + { + MyCompare& me = *this; + return std::upper_bound(begin(), end(), k, me); + } + + const_iterator upper_bound(const key_type& k) const + { + const MyCompare& me = *this; + return std::upper_bound(begin(), end(), k, me); + } + + std::pair<iterator, iterator> equal_range(const key_type& k) + { + MyCompare& me = *this; + return std::equal_range(begin(), end(), k, me); + } + + std::pair<const_iterator, const_iterator> equal_range( + const key_type& k) const + { + const MyCompare& me = *this; + return std::equal_range(begin(), end(), k, me); + } + + template <class K1, class V1, class C1, class A1> + friend bool operator==(const AssocVector<K1, V1, C1, A1>& lhs, + const AssocVector<K1, V1, C1, A1>& rhs); + + bool operator<(const AssocVector& rhs) const + { + const Base& me = *this; + const Base& yo = rhs; + return me < yo; + } + + template <class K1, class V1, class C1, class A1> + friend bool operator!=(const AssocVector<K1, V1, C1, A1>& lhs, + const AssocVector<K1, V1, C1, A1>& rhs); + + template <class K1, class V1, class C1, class A1> + friend bool operator>(const AssocVector<K1, V1, C1, A1>& lhs, + const AssocVector<K1, V1, C1, A1>& rhs); + + template <class K1, class V1, class C1, class A1> + friend bool operator>=(const AssocVector<K1, V1, C1, A1>& lhs, + const AssocVector<K1, V1, C1, A1>& rhs); + + template <class K1, class V1, class C1, class A1> + friend bool operator<=(const AssocVector<K1, V1, C1, A1>& lhs, + const AssocVector<K1, V1, C1, A1>& rhs); + }; + + template <class K, class V, class C, class A> + inline bool operator==(const AssocVector<K, V, C, A>& lhs, + const AssocVector<K, V, C, A>& rhs) + { + const std::vector<std::pair<K, V>, A>& me = lhs; + return me == rhs; + } + + template <class K, class V, class C, class A> + inline bool operator!=(const AssocVector<K, V, C, A>& lhs, + const AssocVector<K, V, C, A>& rhs) + { return !(lhs == rhs); } + + template <class K, class V, class C, class A> + inline bool operator>(const AssocVector<K, V, C, A>& lhs, + const AssocVector<K, V, C, A>& rhs) + { return rhs < lhs; } + + template <class K, class V, class C, class A> + inline bool operator>=(const AssocVector<K, V, C, A>& lhs, + const AssocVector<K, V, C, A>& rhs) + { return !(lhs < rhs); } + + template <class K, class V, class C, class A> + inline bool operator<=(const AssocVector<K, V, C, A>& lhs, + const AssocVector<K, V, C, A>& rhs) + { return !(rhs < lhs); } + + + // specialized algorithms: + template <class K, class V, class C, class A> + void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs) + { lhs.swap(rhs); } + +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/CachedFactory.h b/shared/loki/CachedFactory.h new file mode 100644 index 00000000..15c9a801 --- /dev/null +++ b/shared/loki/CachedFactory.h @@ -0,0 +1,1167 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 by Guillaume Chatelet +// +// Code covered by the MIT License +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The authors make no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +// +// This code DOES NOT accompany the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_CACHEDFACTORY_INC_ +#define LOKI_CACHEDFACTORY_INC_ + +// $Id: CachedFactory.h 950 2009-01-26 19:45:54Z syntheticpp $ + +#include <functional> +#include <algorithm> +#include <iostream> +#include <vector> +#include <iterator> +#include <map> +#include <cassert> +#include <loki/Key.h> + +#ifdef DO_EXTRA_LOKI_TESTS + #define D( x ) x +#else + #define D( x ) ; +#endif + +#if defined(_MSC_VER) || defined(__CYGWIN__) +#include <time.h> +#endif + +/** + * \defgroup FactoriesGroup Factories + * \defgroup CachedFactoryGroup Cached Factory + * \ingroup FactoriesGroup + * \brief CachedFactory provides an extension of a Factory with caching + * support. + * + * Once used objects are returned to the CachedFactory that manages its + * destruction. + * If your code uses lots of "long to construct/destruct objects" using the + * CachedFactory will surely speedup the execution. + */ +namespace Loki +{ +/** + * \defgroup EncapsulationPolicyCachedFactoryGroup Encapsulation policies + * \ingroup CachedFactoryGroup + * \brief Defines how the object is returned to the client + */ + /** + * \class SimplePointer + * \ingroup EncapsulationPolicyCachedFactoryGroup + * \brief No encaspulation : returns the pointer + * + * This implementation does not make any encapsulation. + * It simply returns the object's pointer. + */ + template<class AbstractProduct> + class SimplePointer + { + protected: + typedef AbstractProduct* ProductReturn; + ProductReturn encapsulate(AbstractProduct* pProduct) + { + return pProduct; + } + + AbstractProduct* release(ProductReturn &pProduct) + { + AbstractProduct* pPointer(pProduct); + pProduct=NULL; + return pPointer; + } + const char* name(){return "pointer";} + }; + +/** + * \defgroup CreationPolicyCachedFactoryGroup Creation policies + * \ingroup CachedFactoryGroup + * \brief Defines a way to limit the creation operation. + * + * For instance one may want to be alerted (Exception) when + * - Cache has created a more than X object within the last x seconds + * - Cache creation rate has increased dramatically + * . + * which may result from bad caching strategy, or critical overload + */ + /** + * \class NeverCreate + * \ingroup CreationPolicyCachedFactoryGroup + * \brief Never allows creation. Testing purposes only. + * + * Using this policy will throw an exception. + */ + class NeverCreate + { + protected: + struct Exception : public std::exception + { + const char* what() const throw() { return "NeverFetch Policy : No Fetching allowed"; } + }; + + bool canCreate() + { + throw Exception(); + } + + void onCreate(){} + void onDestroy(){} + const char* name(){return "never";} + }; + + /** + * \class AlwaysCreate + * \ingroup CreationPolicyCachedFactoryGroup + * \brief Always allows creation. + * + * Doesn't limit the creation in any way + */ + class AlwaysCreate + { + protected: + bool canCreate() + { + return true; + } + + void onCreate(){} + void onDestroy(){} + const char* name(){return "always";} + }; + + + /** + * \class RateLimitedCreation + * \ingroup CreationPolicyCachedFactoryGroup + * \brief Limit in rate. + * + * This implementation will prevent from Creating more than maxCreation objects + * within byTime ms by throwing an exception. + * Could be usefull to detect prevent loads (http connection for instance). + * Use the setRate method to set the rate parameters. + * default is 10 objects in a second. + */ + // !! CAUTION !! + // The std::clock() function is not quite precise + // under linux this policy might not work. + // TODO : get a better implementation (platform dependant) + class RateLimitedCreation + { + private: + typedef std::vector< clock_t > Vector; + Vector m_vTimes; + unsigned maxCreation; + clock_t timeValidity; + clock_t lastUpdate; + + void cleanVector() + { + using namespace std; + clock_t currentTime = clock(); + D( cout << "currentTime = " << currentTime<< endl; ) + D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; ) + if(currentTime - lastUpdate > timeValidity) + { + m_vTimes.clear(); + D( cout << " is less than time validity " << timeValidity; ) + D( cout << " so clearing vector" << endl; ) + } + else + { + D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; ) + D( displayVector(); ) + Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity)); + // this rearrangement might be costly, consider optimization + // by calling cleanVector in less used onCreate function + // ... although it may not be correct + m_vTimes.erase(newEnd, m_vTimes.end()); + D( displayVector(); ) + } + lastUpdate = currentTime; + } +#ifdef DO_EXTRA_LOKI_TESTS + void displayVector() + { + std::cout << "Vector : "; + copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " ")); + std::cout << std::endl; + } +#endif + protected: + RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock()) + {} + + struct Exception : public std::exception + { + const char* what() const throw() { return "RateLimitedCreation Policy : Exceeded the authorized creation rate"; } + }; + + bool canCreate() + { + cleanVector(); + if(m_vTimes.size()>maxCreation) + throw Exception(); + else + return true; + } + + void onCreate() + { + m_vTimes.push_back(clock()); + } + + void onDestroy() + { + } + const char* name(){return "rate limited";} + public: + // set the creation rate + // No more than maxCreation within byTime milliseconds + void setRate(unsigned maxCreation, unsigned byTime) + { + assert(byTime>0); + this->maxCreation = maxCreation; + this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000); + D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; ) + } + }; + + /** + * \class AmountLimitedCreation + * \ingroup CreationPolicyCachedFactoryGroup + * \brief Limit by number of objects + * + * This implementation will prevent from Creating more than maxCreation objects + * within byTime ms by calling eviction policy. + * Use the setRate method to set the rate parameters. + * default is 10 objects. + */ + class AmountLimitedCreation + { + private: + unsigned maxCreation; + unsigned created; + + protected: + AmountLimitedCreation() : maxCreation(10), created(0) + {} + + bool canCreate() + { + return !(created>=maxCreation); + } + + void onCreate() + { + ++created; + } + + void onDestroy() + { + --created; + } + const char* name(){return "amount limited";} + public: + // set the creation max amount + void setMaxCreation(unsigned maxCreation) + { + assert(maxCreation>0); + this->maxCreation = maxCreation; + D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; ) + } + }; + +/** + * \defgroup EvictionPolicyCachedFactoryGroup Eviction policies + * \ingroup CachedFactoryGroup + * \brief Gathers informations about the stored objects and choose a + * candidate for eviction. + */ + + class EvictionException : public std::exception + { + public: + const char* what() const throw() { return "Eviction Policy : trying to make room but no objects are available"; } + }; + + // The following class is intented to provide helpers to sort + // the container that will hold an eviction score + template + < + typename ST, // Score type + typename DT // Data type + > + class EvictionHelper + { + protected: + typedef typename std::map< DT, ST > HitMap; + typedef typename HitMap::iterator HitMapItr; + private: + typedef std::pair< ST, DT > SwappedPair; + typedef std::multimap< ST, DT > SwappedHitMap; + typedef typename SwappedHitMap::iterator SwappedHitMapItr; + protected: + HitMap m_mHitCount; + + // This function sorts the map according to the score + // and returns the lower bound of the sorted container + DT& getLowerBound(){ + assert(!m_mHitCount.empty()); + // inserting the swapped pair into a multimap + SwappedHitMap copyMap; + for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr) + copyMap.insert(SwappedPair((*itr).second, (*itr).first)); + if((*copyMap.rbegin()).first == 0) // the higher score is 0 ... + throw EvictionException(); // there is no key evict + return (*copyMap.begin()).second; + } + }; + + /** + * \class EvictLRU + * \ingroup EvictionPolicyCachedFactoryGroup + * \brief Evicts least accessed objects first. + * + * Implementation of the Least recent used algorithm as + * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms . + * + * WARNING : If an object is heavily fetched + * (more than ULONG_MAX = UINT_MAX = 4294967295U) + * it could unfortunately be removed from the cache. + */ + template + < + typename DT, // Data Type (AbstractProduct*) + typename ST = unsigned // default data type to use as Score Type + > + class EvictLRU : public EvictionHelper< ST , DT > + { + private: + typedef EvictionHelper< ST , DT > EH; + protected: + + virtual ~EvictLRU(){} + + // OnStore initialize the counter for the new key + // If the key already exists, the counter is reseted + void onCreate(const DT& key) + { + EH::m_mHitCount[key] = 0; + } + + void onFetch(const DT&) + { + } + + // onRelease increments the hit counter associated with the object + void onRelease(const DT& key) + { + ++(EH::m_mHitCount[key]); + } + + void onDestroy(const DT& key) + { + EH::m_mHitCount.erase(key); + } + + // this function is implemented in Cache and redirected + // to the Storage Policy + virtual void remove(DT const key)=0; + + // LRU Eviction policy + void evict() + { + remove(EH::getLowerBound()); + } + const char* name(){return "LRU";} + }; + + /** + * \class EvictAging + * \ingroup EvictionPolicyCachedFactoryGroup + * \brief LRU aware of the time span of use + * + * Implementation of the Aging algorithm as + * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms . + * + * This method is much more costly than evict LRU so + * if you need extreme performance consider switching to EvictLRU + */ + template + < + typename DT, // Data Type (AbstractProduct*) + typename ST = unsigned // default data type to use as Score Type + > + class EvictAging : public EvictionHelper< ST, DT > + { + private: + EvictAging(const EvictAging&); + EvictAging& operator=(const EvictAging&); + typedef EvictionHelper< ST, DT > EH; + typedef typename EH::HitMap HitMap; + typedef typename EH::HitMapItr HitMapItr; + + // update the counter + template<class T> struct updateCounter : public std::unary_function<T, void> + { + updateCounter(const DT& key): key_(key){} + void operator()(T x) + { + x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1); + D( std::cout << x.second << std::endl; ) + } + const DT &key_; + updateCounter(const updateCounter& rhs) : key_(rhs.key_){} + private: + updateCounter& operator=(const updateCounter& rhs); + }; + protected: + EvictAging(){} + virtual ~EvictAging(){} + + // OnStore initialize the counter for the new key + // If the key already exists, the counter is reseted + void onCreate(const DT& key){ + EH::m_mHitCount[key] = 0; + } + + void onFetch(const DT&){} + + // onRelease increments the hit counter associated with the object + // Updating every counters by iterating over the map + // If the key is the key of the fetched object : + // the counter is shifted to the right and it's MSB is set to 1 + // else + // the counter is shifted to the left + void onRelease(const DT& key) + { + std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key)); + } + + void onDestroy(const DT& key) + { + EH::m_mHitCount.erase(key); + } + + // this function is implemented in Cache and redirected + // to the Storage Policy + virtual void remove(DT const key)=0; + + // LRU with Aging Eviction policy + void evict() + { + remove(EH::getLowerBound()); + } + const char* name(){return "LRU with aging";} + }; + + /** + * \class EvictRandom + * \ingroup EvictionPolicyCachedFactoryGroup + * \brief Evicts a random object + * + * Implementation of the Random algorithm as + * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms . + */ + template + < + typename DT, // Data Type (AbstractProduct*) + typename ST = void // Score Type not used by this policy + > + class EvictRandom + { + private: + std::vector< DT > m_vKeys; + typedef typename std::vector< DT >::size_type size_type; + typedef typename std::vector< DT >::iterator iterator; + + protected: + + virtual ~EvictRandom(){} + + void onCreate(const DT&){ + } + + void onFetch(const DT& ){ + } + + void onRelease(const DT& key){ + m_vKeys.push_back(key); + } + + void onDestroy(const DT& key){ + using namespace std; + m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end()); + } + + // Implemented in Cache and redirected to the Storage Policy + virtual void remove(DT const key)=0; + + // Random Eviction policy + void evict() + { + if(m_vKeys.empty()) + throw EvictionException(); + size_type random = static_cast<size_type>((m_vKeys.size()*rand())/(static_cast<size_type>(RAND_MAX) + 1)); + remove(*(m_vKeys.begin()+random)); + } + const char* name(){return "random";} + }; + +/** + * \defgroup StatisticPolicyCachedFactoryGroup Statistic policies + * \ingroup CachedFactoryGroup + * \brief Gathers information about the cache. + * + * For debugging purpose this policy proposes to gather informations + * about the cache. This could be useful to determine whether the cache is + * mandatory or if the policies are well suited to the application. + */ + /** + * \class NoStatisticPolicy + * \ingroup StatisticPolicyCachedFactoryGroup + * \brief Do nothing + * + * Should be used in release code for better performances + */ + class NoStatisticPolicy + { + protected: + void onDebug(){} + void onFetch(){} + void onRelease(){} + void onCreate(){} + void onDestroy(){} + const char* name(){return "no";} + }; + + /** + * \class SimpleStatisticPolicy + * \ingroup StatisticPolicyCachedFactoryGroup + * \brief Simple statistics + * + * Provides the following informations about the cache : + * - Created objects + * - Fetched objects + * - Destroyed objects + * - Cache hit + * - Cache miss + * - Currently allocated + * - Currently out + * - Cache overall efficiency + */ + class SimpleStatisticPolicy + { + private: + unsigned allocated, created, hit, out, fetched; + protected: + SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0) + { + } + + void onDebug() + { + using namespace std; + cout << "############################" << endl; + cout << "## About this cache " << this << endl; + cout << "## + Created objects : " << created << endl; + cout << "## + Fetched objects : " << fetched << endl; + cout << "## + Destroyed objects : " << created - allocated << endl; + cout << "## + Cache hit : " << hit << endl; + cout << "## + Cache miss : " << fetched - hit << endl; + cout << "## + Currently allocated : " << allocated << endl; + cout << "## + Currently out : " << out << endl; + cout << "############################" << endl; + if(fetched!=0){ + cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl; + cout << "############################" << endl; + } + cout << endl; + } + + void onFetch() + { + ++fetched; + ++out; + ++hit; + } + void onRelease() + { + --out; + } + void onCreate() + { + ++created; + ++allocated; + --hit; + } + void onDestroy() + { + --allocated; + } + + const char* name(){return "simple";} + public: + unsigned getCreated(){return created;} + unsigned getFetched(){return fetched;} + unsigned getHit(){return hit;} + unsigned getMissed(){return fetched - hit;} + unsigned getAllocated(){return allocated;} + unsigned getOut(){return out;} + unsigned getDestroyed(){return created-allocated;} + }; + + /////////////////////////////////////////////////////////////////////////// + // Cache Factory definition + /////////////////////////////////////////////////////////////////////////// + class CacheException : public std::exception + { + public: + const char* what() const throw() { return "Internal Cache Error"; } + }; + + /** + * \class CachedFactory + * \ingroup CachedFactoryGroup + * \brief Factory with caching support + * + * This class acts as a Factory (it creates objects) + * but also keeps the already created objects to prevent + * long constructions time. + * + * Note this implementation do not retain ownership. + */ + template + < + class AbstractProduct, + typename IdentifierType, + typename CreatorParmTList = NullType, + template<class> class EncapsulationPolicy = SimplePointer, + class CreationPolicy = AlwaysCreate, + template <typename , typename> class EvictionPolicy = EvictRandom, + class StatisticPolicy = NoStatisticPolicy, + template<typename, class> class FactoryErrorPolicy = DefaultFactoryError, + class ObjVector = std::vector<AbstractProduct*> + > + class CachedFactory : + protected EncapsulationPolicy<AbstractProduct>, + public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct * , unsigned > + { + private: + typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> MyFactory; + typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl; + typedef Functor< AbstractProduct* , CreatorParmTList > ProductCreator; + typedef EncapsulationPolicy<AbstractProduct> NP; + typedef CreationPolicy CP; + typedef StatisticPolicy SP; + typedef EvictionPolicy< AbstractProduct* , unsigned > EP; + + typedef typename Impl::Parm1 Parm1; + typedef typename Impl::Parm2 Parm2; + typedef typename Impl::Parm3 Parm3; + typedef typename Impl::Parm4 Parm4; + typedef typename Impl::Parm5 Parm5; + typedef typename Impl::Parm6 Parm6; + typedef typename Impl::Parm7 Parm7; + typedef typename Impl::Parm8 Parm8; + typedef typename Impl::Parm9 Parm9; + typedef typename Impl::Parm10 Parm10; + typedef typename Impl::Parm11 Parm11; + typedef typename Impl::Parm12 Parm12; + typedef typename Impl::Parm13 Parm13; + typedef typename Impl::Parm14 Parm14; + typedef typename Impl::Parm15 Parm15; + + public: + typedef typename NP::ProductReturn ProductReturn; + private: + typedef Key< Impl, IdentifierType > MyKey; + typedef std::map< MyKey, ObjVector > KeyToObjVectorMap; + typedef std::map< AbstractProduct*, MyKey > FetchedObjToKeyMap; + + MyFactory factory; + KeyToObjVectorMap fromKeyToObjVector; + FetchedObjToKeyMap providedObjects; + unsigned outObjects; + + ObjVector& getContainerFromKey(MyKey key){ + return fromKeyToObjVector[key]; + } + + AbstractProduct* const getPointerToObjectInContainer(ObjVector &entry) + { + if(entry.empty()) // No object available + { // the object will be created in the calling function. + // It has to be created in the calling function because of + // the variable number of parameters for CreateObject(...) method + return NULL; + } + else + { // returning the found object + AbstractProduct* pObject(entry.back()); + assert(pObject!=NULL); + entry.pop_back(); + return pObject; + } + } + + bool shouldCreateObject(AbstractProduct * const pProduct){ + if(pProduct!=NULL) // object already exists + return false; + if(CP::canCreate()==false) // Are we allowed to Create ? + EP::evict(); // calling Eviction Policy to clean up + return true; + } + + void ReleaseObjectFromContainer(ObjVector &entry, AbstractProduct * const object) + { + entry.push_back(object); + } + + void onFetch(AbstractProduct * const pProduct) + { + SP::onFetch(); + EP::onFetch(pProduct); + ++outObjects; + } + + void onRelease(AbstractProduct * const pProduct) + { + SP::onRelease(); + EP::onRelease(pProduct); + --outObjects; + } + + void onCreate(AbstractProduct * const pProduct) + { + CP::onCreate(); + SP::onCreate(); + EP::onCreate(pProduct); + } + + void onDestroy(AbstractProduct * const pProduct) + { + CP::onDestroy(); + SP::onDestroy(); + EP::onDestroy(pProduct); + } + + // delete the object + template<class T> struct deleteObject : public std::unary_function<T, void> + { + void operator()(T x){ delete x; } + }; + + // delete the objects in the vector + template<class T> struct deleteVectorObjects : public std::unary_function<T, void> + { + void operator()(T x){ + ObjVector &vec(x.second); + std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>()); + } + }; + + // delete the keys of the map + template<class T> struct deleteMapKeys : public std::unary_function<T, void> + { + void operator()(T x){ delete x.first; } + }; + + protected: + virtual void remove(AbstractProduct * const pProduct) + { + typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct); + if(fetchedItr!=providedObjects.end()) // object is unreleased. + throw CacheException(); + bool productRemoved = false; + typename KeyToObjVectorMap::iterator objVectorItr; + typename ObjVector::iterator objItr; + for(objVectorItr=fromKeyToObjVector.begin();objVectorItr!=fromKeyToObjVector.end();++objVectorItr) + { + ObjVector &v((*objVectorItr).second); + objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct*>(), pProduct)); + if(objItr != v.end()) // we found the vector containing pProduct and removed it + { + onDestroy(pProduct); // warning policies we are about to destroy an object + v.erase(objItr, v.end()); // real removing + productRemoved = true; + break; + } + } + if(productRemoved==false) + throw CacheException(); // the product is not in the cache ?! + delete pProduct; // deleting it + } + + public: + CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0) + { + } + + ~CachedFactory() + { + using namespace std; + // debug information + SP::onDebug(); + // cleaning the Cache + for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(), + deleteVectorObjects< typename KeyToObjVectorMap::value_type >() + ); + if(!providedObjects.empty()) + { + // The factory is responsible for the creation and destruction of objects. + // If objects are out during the destruction of the Factory : deleting anyway. + // This might not be a good idea. But throwing an exception in a destructor is + // considered as a bad pratice and asserting might be too much. + // What to do ? Leaking memory or corrupting in use pointers ? hmm... + D( cout << "====>> Cache destructor : deleting "<< providedObjects.size()<<" in use objects <<====" << endl << endl; ) + for_each(providedObjects.begin(), providedObjects.end(), + deleteMapKeys< typename FetchedObjToKeyMap::value_type >() + ); + } + } + + /////////////////////////////////// + // Acts as the proxy pattern and // + // forwards factory methods // + /////////////////////////////////// + + bool Register(const IdentifierType& id, ProductCreator creator) + { + return factory.Register(id, creator); + } + + template <class PtrObj, typename CreaFn> + bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn) + { + return factory.Register(id, p, fn); + } + + bool Unregister(const IdentifierType& id) + { + return factory.Unregister(id); + } + + /// Return the registered ID in this Factory + std::vector<IdentifierType>& RegisteredIds() + { + return factory.RegisteredIds(); + } + + ProductReturn CreateObject(const IdentifierType& id) + { + MyKey key(id); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1) + { + MyKey key(id,p1); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2) + { + MyKey key(id,p1,p2); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3) + { + MyKey key(id,p1,p2,p3); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { + MyKey key(id,p1,p2,p3,p4); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { + MyKey key(id,p1,p2,p3,p4,p5); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { + MyKey key(id,p1,p2,p3,p4,p5,p6); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7 ) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12 + ,key.p13); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12 + ,key.p13,key.p14); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + ProductReturn CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15); + AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key))); + if(shouldCreateObject(pProduct)) + { + pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3 + ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12 + ,key.p13,key.p14,key.p15); + onCreate(pProduct); + } + onFetch(pProduct); + providedObjects[pProduct] = key; + return NP::encapsulate(pProduct); + } + + /// Use this function to release the object + /** + * if execution brakes in this function then you tried + * to release an object that wasn't provided by this Cache + * ... which is bad :-) + */ + void ReleaseObject(ProductReturn &object) + { + AbstractProduct* pProduct(NP::release(object)); + typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct); + if(itr == providedObjects.end()) + throw CacheException(); + onRelease(pProduct); + ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct); + providedObjects.erase(itr); + } + + /// display the cache configuration + void displayCacheType() + { + using namespace std; + cout << "############################" << endl; + cout << "## Cache configuration" << endl; + cout << "## + Encapsulation " << NP::name() << endl; + cout << "## + Creating " << CP::name() << endl; + cout << "## + Eviction " << EP::name() << endl; + cout << "## + Statistics " << SP::name() << endl; + cout << "############################" << endl; + } + }; +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/CheckReturn.h b/shared/loki/CheckReturn.h new file mode 100644 index 00000000..fbe63ed0 --- /dev/null +++ b/shared/loki/CheckReturn.h @@ -0,0 +1,165 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2007 by Rich Sposato +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_CHECK_RETURN_INC_ +#define LOKI_CHECK_RETURN_INC_ + +// $Id$ + + +#include <assert.h> +#include <stdio.h> +#include <stdexcept> + + +namespace Loki +{ + +// ---------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// \class CheckReturn +/// +/// \par Purpose +/// C++ provides no mechanism within the language itself to force code to +/// check the return value from a function call. This simple class provides +/// a mechanism by which programmers can force calling functions to check the +/// return value. Or at least make them consciously choose to disregard the +/// return value. If the calling function fails to use or store the return +/// value, the destructor calls the OnError policy. +/// +/// \par Template Parameters +/// CheckReturn has two template parameters, Value and OnError. +/// - Value is the return type from the function. CheckReturn stores a copy of +/// it rather than a reference or pointer since return value could be local to +/// a function. CheckReturn works best when the return type is a built-in +/// primitive (bool, int, etc...) a pointer, or an enum (such as an error +/// condition enum). It can work with other types that have cheap copy +/// operations. +/// - OnError is a policy class indicating how to handle the situation when a +/// caller does not check or copy the returned value. Loki provides some +/// policy classs and you may also write your own. For example, you can write +/// a policy to create a message box when the function ignores the return value. +/// That would quickly tell you places where code ignores the function call. +/// If your write your own, you only need a templated class or struct with a +/// public function named "run" that accepts a reference to a const value. +/// +/// @par Provided Policy Classes +/// - IgnoreReturnValue Deliberately ignores when the caller ignores the return value. +/// - TriggerAssert Asserts in debug builds if the caller ignores the return value. +/// - FprintfStderr Prints out an error message if the caller ignores the return value. +/// - ThrowTheValue Throws the ignored value as an exception. +/// - ThrowLogicError Throws a logic_error exception to indicate a programming error. +//////////////////////////////////////////////////////////////////////////////// + + +template<class T> +struct IgnoreReturnValue +{ + static void run(const T&) + { + /// Do nothing at all. + } +}; + +template<class T> +struct ThrowTheValue +{ + static void run(const T & value ) + { + throw value; + } +}; + +template<class T> +struct ThrowLogicError +{ + static void run( const T & ) + { + throw ::std::logic_error( "CheckReturn: return value was not checked.\n" ); + } +}; + +template<class T> +struct TriggerAssert +{ + static void run(const T&) + { + assert( 0 ); + } +}; + +template<class T> +struct FprintfStderr +{ + static void run(const T&) + { + fprintf(stderr, "CheckReturn: return value was not checked.\n"); + } +}; + + + +template < class Value , template<class> class OnError = TriggerAssert > +class CheckReturn +{ +public: + + /// Conversion constructor changes Value type to CheckReturn type. + inline CheckReturn( const Value & value ) : + m_value( value ), m_checked( false ) {} + + /// Copy-constructor allows functions to call another function within the + /// return statement. The other CheckReturn's m_checked flag is set since + /// its duty has been passed to the m_checked flag in this one. + inline CheckReturn( const CheckReturn & that ) : + m_value( that.m_value ), m_checked( false ) + { that.m_checked = true; } + + /// Destructor checks if return value was used. + inline ~CheckReturn( void ) + { + // If m_checked is false, then a function failed to check the + // return value from a function call. + if (!m_checked) + OnError<Value>::run(m_value); + } + + /// Conversion operator changes CheckReturn back to Value type. + inline operator Value ( void ) + { + m_checked = true; + return m_value; + } + +private: + /// Default constructor not implemented. + CheckReturn( void ); + + /// Copy-assignment operator not implemented. + CheckReturn & operator = ( const CheckReturn & that ); + + /// Copy of returned value. + Value m_value; + + /// Flag for whether calling function checked return value yet. + mutable bool m_checked; +}; + +// ---------------------------------------------------------------------------- + +} // namespace Loki + +#endif // end file guardian + +// $Log$ + diff --git a/shared/loki/Checker.h b/shared/loki/Checker.h new file mode 100644 index 00000000..19350679 --- /dev/null +++ b/shared/loki/Checker.h @@ -0,0 +1,516 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// The Loki Library +// Copyright (c) 2008 Rich Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The author makes no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +// +//////////////////////////////////////////////////////////////////////////////// + +// $Id$ + +/// @file Checker.h This file provides Loki's Checker facility. + + +// ---------------------------------------------------------------------------- + +#ifndef LOKI_CHECKER_H_INCLUDED +#define LOKI_CHECKER_H_INCLUDED + +#include <exception> // needed for calls to uncaught_exception. +#include <assert.h> + + +namespace Loki +{ + +/** @par ContractChecker and StaticChecker Overview + The ContractChecker and StaticChecker classes have two purposes: + - provide a mechanism by which programmers can determine which functions + violate class/data invariants, + - and determine which exception safety a function provides. + + @par Class & Data Invariants + The ContractChecker and StaticChecker define invariants as "expressions that + are true for particular data". They uses a function which returns true if all + data are valid, and returns false if any datum is invalid. This is called the + validator function, and the host class or function provides a pointer to it. + The validator could also assert for any invariant which fails rather than + return false. If the validator is a static member function, you can use it + with checkers in any function, but especially standalone functions and class + static functions. If the validator is a non-static member function, you can + use it only within non-static member functions. + + @par Exception Safety Levels + Years ago, David Abrahams formalized a framework for assessing the exception + safety level a function provides. His framework describes three levels of + guarantees. Any function which does not provide any of these levels is + considered unsafe. ContractChecker and StaticChecker determine a function's + safety level through the use of policy classes. Checker's policy classes can + show if a function provides any of these three guarantees. Since there is no + universal way to detect leaks, this facility provides no mechanism for finding + leaks, but users may create their own validators which do. StaticChecker's + policy classes only provide direct checking for the no-throw and invariant + guarantees. With some finesse, a programmer can write a validator for + StaticChecker that checks for the Strong guarantee. + + - No-throw guarantee: A function will not throw any exceptions. + - Strong guarantee: A function will not change data if an exception occurs. + (Which I call the no-change guarantee.) + - Basic guarantee: A function will not leak resources and data will remain + in a valid state if an exception occurs. (Which I call either the no-leak + or no-break guarantee depending on context.) + */ + +// ---------------------------------------------------------------------------- + +/** @class CheckForNoThrow + + @par Exception Safety Level: + This exception-checking policy class for ContractChecker asserts if an + exception exists. Host classes can use this to show that a member function + provides the no-throw exception safety guarantees. + + @par Requirements For Host Class: + This policy imposes no requirements on a host class. + */ +template < class Host > +class CheckForNoThrow +{ +public: + + inline explicit CheckForNoThrow( const Host * ) {} + + inline bool Check( const Host * ) const + { + const bool okay = ( !::std::uncaught_exception() ); + assert( okay ); + return okay; + } +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckForNoChange + + @par Exception Safety Level: + This exception-checking policy class for ContractChecker asserts only if a + copy of the host differs from the host object when an exception occurs. Host + classes can use this policy to show which member functions provide the strong + exception guarantee. + + @par Requirements: + This policy requires hosts to provide both the copy-constructor and the + equality operator, and is intended for classes with value semantics. + equality operator. + */ + +template < class Host > +class CheckForNoChange +{ +public: + + inline explicit CheckForNoChange( const Host * host ) : + m_compare( *host ) {} + + inline bool Check( const Host * host ) const + { + const bool okay = ( !::std::uncaught_exception() ) + || ( m_compare == *host ); + assert( okay ); + return okay; + } + +private: + Host m_compare; +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckForNoChangeOrThrow + + @par Exception Safety Level: + This exception-checking policy class for ContractChecker asserts either if a + copy of the host differs from the original host object, or if an exception + occurs. Host classes can use this policy to show which member functions provide + the no-throw exception guarantee, and would never change data anyway. + + @par Requirements For Host Class: + This policy requires hosts to provide both the copy-constructor and the + equality operator, and is intended for classes with value semantics. + */ + +template < class Host > +class CheckForNoChangeOrThrow +{ +public: + + inline explicit CheckForNoChangeOrThrow( const Host * host ) : + m_compare( *host ) {} + + inline bool Check( const Host * host ) const + { + bool okay = ( !::std::uncaught_exception() ); + assert( okay ); + okay = ( m_compare == *host ); + assert( okay ); + return okay; + } + +private: + Host m_compare; +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckForEquality + + @par Exception Safety Level: + This exception-checking policy class for ContractChecker asserts if a copy of the host differs from the host object regardless of whether an exception occurs. + Host classes can use this policy to show which member functions never change + data members, and thereby provide the strong exception safety level by default. + + @par Requirements For Host Class: + This policy requires hosts to provide both the copy-constructor and the + equality operator, and is intended for classes with value semantics. + */ + +template < class Host > +class CheckForEquality +{ +public: + + inline explicit CheckForEquality( const Host * host ) : + m_compare( *host ) {} + + inline bool Check( const Host * host ) const + { + const bool okay = ( m_compare == *host ); + assert( okay ); + return okay; + } + +private: + Host m_compare; +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckForNothing + + @par Exception Safety Level: + This exception-checking policy class for ContractChecker does nothing when + called. Host classes can use this to show which member functions provide + neither the strong nor no-throw exception guarantees. The best guarantee such + functions can provide is that nothing gets leaked. + + @par Requirements For Host Class: + This policy imposes no requirements on a host class. + */ + +template < class Host > +class CheckForNothing +{ +public: + inline explicit CheckForNothing( const Host * ) {} + inline bool Check( const Host * ) const { return true; } +}; + +// ---------------------------------------------------------------------------- + +/** @class ContractChecker + This class determines if a function violated any class invariant, but it also + determines if a function fulfills its contract with client code. In the + "Design by Contract" paradigm, each function has certain pre-conditions and + post-conditions which may differ from the class invariants. This asserts if a + check for an invariant fails as well as if any pre- or post-condition fails. + It also demonstrate which exception safety level a function provides. + + @par Usage + -# Implement a function that checks each class invariant. The function must + have the signature similar to the Validator type. Something like: + "bool Host::IsValid( void ) const;" + - The function should return true if everything is okay, but false if + something is wrong. + - Or it could assert if anything is wrong. + - Ideally, it should be private. + -# Implement similar functions to check for pre-conditions and post-conditions. + Functions which verify pre-conditions and post-conditions do not need to + check all class invariants, just conditions specific to certain public + functions in the host class. + -# Declare some typedef's inside the class declaration like these. Make one + typedef for each exception policy you use. I typedef'ed the CheckForNothing + policy as CheckInvariants because even if a function can't provide either the + no-throw nor the no-change policies, it should still make sure the object + remains in a valid state. + - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNoThrow > CheckForNoThrow; + - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNoChange > CheckForNoChange; + - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForEquality > CheckForEquality; + - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNothing > CheckInvariants; + -# Construct a checker near the top of each member function - except in the + validator member function. Pass the this pointer and the address of your + validator function into the checker's constructor. You may also pass in pointers + to function which check pre- and post-conditions. + - If the function never throws, then use the CheckForNoThrow policy. + - If the function never changes any data members, then use CheckForEquality + policy. + - If the function's normal execution flow changes data, but must make sure + data remains unchanged when any exceptions occur, then use the + CheckForNoChange policy. + - Otherwise use the CheckInvariants policy. + -# Recompile a debug version of your program, run the program and all the unit + tests, and look for which assertions failed. + */ + +template +< + class Host, + template < class > class ExceptionPolicy +> +class ContractChecker : public ExceptionPolicy< Host > +{ + /// Shorthand for the ExceptionPolicy class. + typedef ExceptionPolicy< Host > Ep; + +public: + + /// Signature for the validation function. + typedef bool ( Host:: * Validator )( void ) const; + + /** The constructor makes sure the host is valid at the time the checker + was created, thus insuring the host object was not corrupt from the start. + @par host Pointer to host object. + @par validator Pointer to function that checks class invariants. + @par pre Optional pointer to function that checks pre-conditions. + @par post Optional pointer to function that checks post-conditions. + */ + inline ContractChecker( const Host * host, Validator validator, + Validator pre = 0, Validator post = 0 ) : + Ep( host ), + m_host( host ), + m_validator( validator ), + m_pre( pre ), + m_post( post ) + { + assert( Check() ); + if ( 0 != m_pre ) + assert( ( m_host->*( m_pre ) )() ); + } + + /** The destructor checks if any Host invariants failed, and then calls the + ExceptionPolicy's Check function to determine what to do in case of an + exception. + */ + inline ~ContractChecker( void ) + { + assert( Check() ); + if ( 0 != m_post ) + assert( ( m_host->*( m_post ) )() ); + assert( Ep::Check( m_host ) ); + } + + /** This first checks the invariants for ContractChecker, and then calls the + validator function for the host to make sure no class invariants were + broken by the host within the Host's member function body. The host + member function can call Check directly to verify the object remains valid + at any time. This does not care if the pre- and post-condition validator + pointers are null since a host class may pass in NULL pointers for either + to indicate the pre-conditions or post-conditions are the same as the + overall class invariants. + */ + inline bool Check( void ) const + { + assert( 0 != this ); + assert( 0 != m_host ); + assert( 0 != m_validator ); + // Now that this confirms the pointers to the host and validation + // functions are not null, go ahead and validate the host object. + const bool okay = ( m_host->*( m_validator ) )(); + assert( okay ); + return okay; + } + +private: + + /// Default constructor is not implemented. + ContractChecker( void ); + /// Copy constructor is not implemented. + ContractChecker( const ContractChecker & ); + /// Copy-assignment operator is not implemented. + ContractChecker & operator = ( const ContractChecker & ); + + /// Pointer to the host object. + const Host * m_host; + + /// Pointer to member function that checks Host object's invariants. + Validator m_validator; + + /// Pointer to member function that checks Host object's pre-conditions. + Validator m_pre; + + /// Pointer to member function that checks Host object's post-conditions. + Validator m_post; + +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckStaticForNoThrow + + @par Exception Safety Level: + This exception-checking policy class for StaticChecker asserts if an exception + exists. Functions can use this to show they provide the no-throw exception + safety guarantee. + */ +class CheckStaticForNoThrow +{ +public: + inline bool Check( void ) + { + const bool okay = !::std::uncaught_exception(); + assert( okay ); + return okay; + } +}; + +// ---------------------------------------------------------------------------- + +/** @class CheckStaticForNothing + + @par Exception Safety Level: + This exception-checking policy class for StaticChecker does nothing when called. + Functions can use this to show they might provide the weak exception guarantee. + The best guarantee such functions can provide is that nothing gets leaked. + */ +class CheckStaticForNothing +{ +public: + inline bool Check( void ) { return true; } +}; + +// ---------------------------------------------------------------------------- + +/** @class StaticChecker + This class checks if a function provides the no-throw exception safety level + and if the function violated any invariants. Invariants for stand-alone and + static functions act as pre-conditions and post-conditions. + + @par Usage + -# Implement a function that checks the invariants associated with a function, + or with the static data for a class. The function must + have the signature similar to the Validator type. Something like: + "static bool Host::StaticIsValid( void );" or "bool IsOkay( void );" + - The function should return true if everything is okay, but false if + something is wrong. + - Or it could assert if anything is wrong. + -# If the checker is for static functions within a class, declare typedef's + inside the class declaration like these. Make one typedef for each policy + you use. I typedef'ed the CheckForNothing policy as CheckInvariants because + even if a function can't provide the no-throw guarantee, it should still + make sure that static data remains in a valid state. + - typedef ::Loki::StaticChecker< ::Loki::CheckForNoThrow > CheckStaticForNoThrow; + - typedef ::Loki::StaticChecker< ::Loki::CheckForNothing > CheckStaticInvariants; + -# Construct a checker near the top of each member function - except in the + validator member function. Pass the address of your validator function into + the checker's constructor. + - If the function never throws, then use the CheckForNoThrow policy. + - Otherwise use the CheckInvariants policy. + -# Recompile a debug version of your program, run it, and see if an assertion + fails. + */ + +template +< + class ExceptionPolicy +> +class StaticChecker : public ExceptionPolicy +{ + /// Shorthand for the ExceptionPolicy class. + typedef ExceptionPolicy Ep; + +public: + + /// Signature for the validation function. + typedef bool ( * Validator )( void ); + + /** The constructor makes sure the host is valid at the time the checker + was created, thus insuring the host object was not corrupt from the start. + @par validator Pointer to function that checks class invariants. + @par pre Optional pointer to function that checks pre-conditions. + @par post Optional pointer to function that checks post-conditions. + */ + inline explicit StaticChecker( Validator validator, + Validator pre = 0, Validator post = 0 ) : + Ep(), + m_validator( validator ), + m_pre( pre ), + m_post( post ) + { + assert( Check() ); + if ( 0 != m_pre ) + assert( m_pre() ); + } + + /** The destructor checks if any Host invariants failed, and then calls the + ExceptionPolicy's Check function to determine what to do in case of an + exception. + */ + inline ~StaticChecker( void ) + { + assert( Check() ); + if ( 0 != m_post ) + assert( m_post() ); + assert( Ep::Check() ); + } + + /** This first checks its own invariants, and then calls the validator + function to make sure no invariants were broken by the function which + created this checker. That function can call Check directly to verify the + data remains valid at any time. This does not care if the pre- and post- + condition validator pointers are null since a host class may pass in NULL + pointers for either to indicate the pre-conditions or post-conditions are + the same as the overall class invariants. + */ + inline bool Check( void ) const + { + assert( 0 != this ); + assert( 0 != m_validator ); + // Now that this confirms the pointers to the host and validation + // functions are not null, go ahead and validate the host object. + const bool okay = m_validator(); + assert( okay ); + return okay; + } + +private: + + /// Default constructor is not implemented. + StaticChecker( void ); + /// Copy constructor is not implemented. + StaticChecker( const StaticChecker & ); + /// Copy-assignment operator is not implemented. + StaticChecker & operator = ( const StaticChecker & ); + + /// Pointer to member function that checks Host object's invariants. + Validator m_validator; + + /// Pointer to member function that checks Host object's pre-conditions. + Validator m_pre; + + /// Pointer to member function that checks Host object's post-conditions. + Validator m_post; + +}; + +// ---------------------------------------------------------------------------- + +}; // end namespace Loki + +#endif diff --git a/shared/loki/ConstPolicy.h b/shared/loki/ConstPolicy.h new file mode 100644 index 00000000..74c9e5aa --- /dev/null +++ b/shared/loki/ConstPolicy.h @@ -0,0 +1,61 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Richard Sposato +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The authors make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_CONST_POLICY_INC_ +#define LOKI_CONST_POLICY_INC_ + +// $Id: ConstPolicy.h 769 2006-10-26 10:58:19Z syntheticpp $ + + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +/// @note These policy classes are used in LockingPtr and SmartPtr to define +/// how const is propagated from the pointee. +//////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////// +/// \class DontPropagateConst +/// +/// \ingroup ConstGroup +/// Don't propagate constness of pointed or referred object. +//////////////////////////////////////////////////////////////////////////////// + + template< class T > + struct DontPropagateConst + { + typedef T Type; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class PropagateConst +/// +/// \ingroup ConstGroup +/// Propagate constness of pointed or referred object. +//////////////////////////////////////////////////////////////////////////////// + + template< class T > + struct PropagateConst + { + typedef const T Type; + }; + +// default will not break existing code +#ifndef LOKI_DEFAULT_CONSTNESS +#define LOKI_DEFAULT_CONSTNESS ::Loki::DontPropagateConst +#endif + +} // end namespace Loki + +#endif // end file guardian diff --git a/shared/loki/DataGenerators.h b/shared/loki/DataGenerators.h new file mode 100644 index 00000000..1c8e2df0 --- /dev/null +++ b/shared/loki/DataGenerators.h @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Data Generator by Shannon Barber +// This code DOES NOT accompany the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// +// Code covered by the MIT License +// The author makes no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_DATAGENERATORS_INC_ +#define LOKI_DATAGENERATORS_INC_ + +// $Id: DataGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +#include "Typelist.h" + +//Reference version + +/************************************************************************************ +// class template GenData +// Iteratates a Typelist, and invokes the functor GenFunc<T> +// for each type in the list, passing a functor along the way. +// The functor is designed to be an insertion iterator which GenFunc<T> +// can use to output information about the types in the list. +// + +Example Use + +template<typename T> +struct ExtractDataType + { + some_type operator()() + { + return create_value_from_type<T>; + } + }; + +Loki::IterateTypes<parameter_tl, ExtractDataType> gendata; +std::vector<some_type> stuff; +gendata(std::back_inserter(stuff)); +*******************************************************************************/ +namespace Loki +{ + namespace TL + { + template<typename T> + struct nameof_type + { + const char* operator()() + { + return typeid(T).name(); + } + }; + template<typename T> + struct sizeof_type + { + size_t operator()() + { + return sizeof(T); + } + }; + template <class TList, template <class> class GenFunc> + struct IterateTypes; + + template <class T1, class T2, template <class> class GenFunc> + struct IterateTypes<Typelist<T1, T2>, GenFunc> + { + typedef IterateTypes<T1, GenFunc> head_t; + head_t head; + typedef IterateTypes<T2, GenFunc> tail_t; + tail_t tail; + template<class II> + void operator()(II ii) + { + head.operator()(ii); + tail.operator()(ii); + } + }; + + template <class AtomicType, template <class> class GenFunc> + struct IterateTypes + { + template<class II> + void operator()(II ii) + { + GenFunc<AtomicType> genfunc; + *ii = genfunc(); + ++ii; //Is this even needed? + } + }; + + template <template <class> class GenFunc> + struct IterateTypes<NullType, GenFunc> + { + template<class II> + void operator()(II ii) + {} + }; + + template<typename Types, template <class> class UnitFunc, typename II> + void iterate_types(II ii) + { + Loki::TL::IterateTypes<Types, UnitFunc> it; + it(ii); + } + }//ns TL +}//ns Loki + +#endif // end file guardian + diff --git a/shared/loki/EmptyType.h b/shared/loki/EmptyType.h new file mode 100644 index 00000000..b228e2e8 --- /dev/null +++ b/shared/loki/EmptyType.h @@ -0,0 +1,49 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_EMPTYTYPE_INC_ +#define LOKI_EMPTYTYPE_INC_ + +// $Id: EmptyType.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class EmptyType +// Used as a class type that doesn't hold anything +// Useful as a strawman class +//////////////////////////////////////////////////////////////////////////////// + + class EmptyType {}; + + + inline bool operator==(const EmptyType&, const EmptyType&) + { + return true; + } + + inline bool operator<(const EmptyType&, const EmptyType&) + { + return false; + } + + inline bool operator>(const EmptyType&, const EmptyType&) + { + return false; + } +} + +#endif // end file guardian + diff --git a/shared/loki/Factory.h b/shared/loki/Factory.h new file mode 100644 index 00000000..c4c3b22a --- /dev/null +++ b/shared/loki/Factory.h @@ -0,0 +1,1084 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// Copyright (c) 2005 by Peter Kuemmel +// This code DOES NOT accompany the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// +// Code covered by the MIT License +// The authors make no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_FACTORYPARM_INC_ +#define LOKI_FACTORYPARM_INC_ + +// $Id: Factory.h 788 2006-11-24 22:30:54Z clitte_bbt $ + + +#include "LokiTypeInfo.h" +#include "Functor.h" +#include "AssocVector.h" +#include "SmallObj.h" +#include "Sequence.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) +//unreachable code if OnUnknownType throws an exception +#endif + +/** + * \defgroup FactoriesGroup Factories + * \defgroup FactoryGroup Factory + * \ingroup FactoriesGroup + * \brief Implements a generic object factory. + * + * <i>The Factory Method pattern is an object-oriented design pattern. + * Like other creational patterns, it deals with the problem of creating objects + * (products) without specifying the exact class of object that will be created. + * Factory Method, one of the patterns from the Design Patterns book, handles + * this problem by defining a separate method for creating the objects, which + * subclasses can then override to specify the derived type of product that will + * be created. + * <br> + * More generally, the term Factory Method is often used to refer to any method + * whose main purpose is creation of objects.</i> + * <div ALIGN="RIGHT"><a href="http://en.wikipedia.org/wiki/Factory_method_pattern"> + * Wikipedia</a></div> + * + * Loki proposes a generic version of the Factory. Here is a typical use.<br> + * <code><br> + * 1. Factory< AbstractProduct, int > aFactory;<br> + * 2. aFactory.Register( 1, createProductNull );<br> + * 3. aFactory.CreateObject( 1 ); <br> + * </code><br> + * <br> + * - 1. The declaration<br> + * You want a Factory that produces AbstractProduct.<br> + * The client will refer to a creation method through an int.<br> + * - 2.The registration<br> + * The code that will contribute to the Factory will now need to declare its + * ProductCreator by registering them into the Factory.<br> + * A ProductCreator is a just a function that will return the right object. ie <br> + * <code> + * Product* createProductNull()<br> + * {<br> + * return new Product<br> + * }<br> + * </code><br> + * - 3. The use<br> + * Now the client can create object by calling the Factory's CreateObject method + * with the right identifier. If the ProductCreator were to have arguments + * (<i>ie :Product* createProductParm( int a, int b )</i>) + */ + +namespace Loki +{ + +/** + * \defgroup FactoryErrorPoliciesGroup Factory Error Policies + * \ingroup FactoryGroup + * \brief Manages the "Unknown Type" error in an object factory + * + * \class DefaultFactoryError + * \ingroup FactoryErrorPoliciesGroup + * \brief Default policy that throws an exception + * + */ + + template <typename IdentifierType, class AbstractProduct> + struct DefaultFactoryError + { + struct Exception : public std::exception + { + const char* what() const throw() { return "Unknown Type"; } + }; + + static AbstractProduct* OnUnknownType(IdentifierType) + { + throw Exception(); + } + }; + + +#define LOKI_ENABLE_NEW_FACTORY_CODE +#ifdef LOKI_ENABLE_NEW_FACTORY_CODE + + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +//////////////////////////////////////////////////////////////////////////////// + + struct FactoryImplBase + { + typedef EmptyType Parm1; + typedef EmptyType Parm2; + typedef EmptyType Parm3; + typedef EmptyType Parm4; + typedef EmptyType Parm5; + typedef EmptyType Parm6; + typedef EmptyType Parm7; + typedef EmptyType Parm8; + typedef EmptyType Parm9; + typedef EmptyType Parm10; + typedef EmptyType Parm11; + typedef EmptyType Parm12; + typedef EmptyType Parm13; + typedef EmptyType Parm14; + typedef EmptyType Parm15; + }; + + template <typename AP, typename Id, typename TList > + struct FactoryImpl; + + template<typename AP, typename Id> + struct FactoryImpl<AP, Id, NullType> + : public FactoryImplBase + { + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id & id ) = 0; + }; +template <typename AP, typename Id, typename P1 > + struct FactoryImpl<AP,Id, Seq<P1> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2 > + struct FactoryImpl<AP, Id, Seq<P1, P2> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2,typename P3 > + struct FactoryImpl<AP, Id, Seq<P1, P2, P3> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2,typename P3,typename P4 > + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4 ) = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5 > + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5 ) = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6 ) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7 ) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12,Parm13) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13,typename P14> + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm8,Parm10, + Parm11,Parm12,Parm13,Parm14) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13,typename P14,typename P15 > + struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> > + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + typedef typename TypeTraits<P15>::ParameterType Parm15; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12,Parm13,Parm14,Parm15 ) + = 0; + }; + +#ifndef LOKI_DISABLE_TYPELIST_MACROS + + template <typename AP, typename Id, typename P1 > + struct FactoryImpl<AP,Id, LOKI_TYPELIST_1( P1 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2 > + struct FactoryImpl<AP, Id, LOKI_TYPELIST_2( P1, P2 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2,typename P3 > + struct FactoryImpl<AP, Id, LOKI_TYPELIST_3( P1, P2, P3 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3 ) = 0; + }; + + template<typename AP, typename Id, typename P1,typename P2,typename P3,typename P4 > + struct FactoryImpl<AP, Id, LOKI_TYPELIST_4( P1, P2, P3, P4 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4 ) = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5 > + struct FactoryImpl<AP, Id, LOKI_TYPELIST_5( P1, P2, P3, P4, P5 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5 ) = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_6( P1, P2, P3, P4, P5, P6 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6 ) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_7( P1, P2, P3, P4, P5, P6, P7 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7 ) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_8( P1, P2, P3, P4, P5, P6, P7, P8 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_9( P1, P2, P3, P4, P5, P6, P7, P8, P9 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_10( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_11( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_12( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_13( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12,Parm13) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13,typename P14> + struct FactoryImpl<AP, Id, LOKI_TYPELIST_14( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm8,Parm10, + Parm11,Parm12,Parm13,Parm14) + = 0; + }; + + template<typename AP, typename Id, + typename P1,typename P2,typename P3,typename P4,typename P5, + typename P6,typename P7,typename P8,typename P9,typename P10, + typename P11,typename P12,typename P13,typename P14,typename P15 > + struct FactoryImpl<AP, Id, LOKI_TYPELIST_15( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15 )> + : public FactoryImplBase + { + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + typedef typename TypeTraits<P15>::ParameterType Parm15; + virtual ~FactoryImpl() {} + virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5, + Parm6, Parm7, Parm8, Parm9,Parm10, + Parm11,Parm12,Parm13,Parm14,Parm15 ) + = 0; + }; + +#endif //LOKI_DISABLE_TYPELIST_MACROS + + +//////////////////////////////////////////////////////////////////////////////// +/// \class Factory +/// +/// \ingroup FactoryGroup +/// Implements a generic object factory. +/// +/// Create functions can have up to 15 parameters. +/// +/// \par Singleton lifetime when used with Loki::SingletonHolder +/// Because Factory uses internally Functors which inherits from +/// SmallObject you must use the singleton lifetime +/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode +/// Alternatively you could suppress for Functor the inheritance +/// from SmallObject by defining the macro: +/// \code LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT \endcode +//////////////////////////////////////////////////////////////////////////////// + template + < + class AbstractProduct, + typename IdentifierType, + typename CreatorParmTList = NullType, + template<typename, class> class FactoryErrorPolicy = DefaultFactoryError + > + class Factory : public FactoryErrorPolicy<IdentifierType, AbstractProduct> + { + typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl; + + typedef typename Impl::Parm1 Parm1; + typedef typename Impl::Parm2 Parm2; + typedef typename Impl::Parm3 Parm3; + typedef typename Impl::Parm4 Parm4; + typedef typename Impl::Parm5 Parm5; + typedef typename Impl::Parm6 Parm6; + typedef typename Impl::Parm7 Parm7; + typedef typename Impl::Parm8 Parm8; + typedef typename Impl::Parm9 Parm9; + typedef typename Impl::Parm10 Parm10; + typedef typename Impl::Parm11 Parm11; + typedef typename Impl::Parm12 Parm12; + typedef typename Impl::Parm13 Parm13; + typedef typename Impl::Parm14 Parm14; + typedef typename Impl::Parm15 Parm15; + + typedef Functor<AbstractProduct*, CreatorParmTList> ProductCreator; + + typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap; + + IdToProductMap associations_; + + public: + + Factory() + : associations_() + { + } + + ~Factory() + { + associations_.erase(associations_.begin(), associations_.end()); + } + + bool Register(const IdentifierType& id, ProductCreator creator) + { + return associations_.insert( + typename IdToProductMap::value_type(id, creator)).second != 0; + } + + template <class PtrObj, typename CreaFn> + bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn) + { + ProductCreator creator( p, fn ); + return associations_.insert( + typename IdToProductMap::value_type(id, creator)).second != 0; + } + + bool Unregister(const IdentifierType& id) + { + return associations_.erase(id) != 0; + } + + std::vector<IdentifierType> RegisteredIds() + { + std::vector<IdentifierType> ids; + for(typename IdToProductMap::iterator it = associations_.begin(); + it != associations_.end(); ++it) + { + ids.push_back(it->first); + } + return ids; + } + + AbstractProduct* CreateObject(const IdentifierType& id) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7 ) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9 ); + return this->OnUnknownType(id); + } + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14 ); + return this->OnUnknownType(id); + } + + AbstractProduct* CreateObject(const IdentifierType& id, + Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, + Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15 ); + return this->OnUnknownType(id); + } + + }; + +#else + + template + < + class AbstractProduct, + typename IdentifierType, + typename ProductCreator = AbstractProduct* (*)(), + template<typename, class> + class FactoryErrorPolicy = DefaultFactoryError + > + class Factory + : public FactoryErrorPolicy<IdentifierType, AbstractProduct> + { + public: + bool Register(const IdentifierType& id, ProductCreator creator) + { + return associations_.insert( + typename IdToProductMap::value_type(id, creator)).second != 0; + } + + bool Unregister(const IdentifierType& id) + { + return associations_.erase(id) != 0; + } + + AbstractProduct* CreateObject(const IdentifierType& id) + { + typename IdToProductMap::iterator i = associations_.find(id); + if (i != associations_.end()) + { + return (i->second)(); + } + return this->OnUnknownType(id); + } + + private: + typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap; + IdToProductMap associations_; + }; + +#endif //#define ENABLE_NEW_FACTORY_CODE + +/** + * \defgroup CloneFactoryGroup Clone Factory + * \ingroup FactoriesGroup + * \brief Creates a copy from a polymorphic object. + * + * \class CloneFactory + * \ingroup CloneFactoryGroup + * \brief Creates a copy from a polymorphic object. + */ + + template + < + class AbstractProduct, + class ProductCreator = + AbstractProduct* (*)(const AbstractProduct*), + template<typename, class> + class FactoryErrorPolicy = DefaultFactoryError + > + class CloneFactory + : public FactoryErrorPolicy<TypeInfo, AbstractProduct> + { + public: + bool Register(const TypeInfo& ti, ProductCreator creator) + { + return associations_.insert( + typename IdToProductMap::value_type(ti, creator)).second != 0; + } + + bool Unregister(const TypeInfo& id) + { + return associations_.erase(id) != 0; + } + + AbstractProduct* CreateObject(const AbstractProduct* model) + { + if (model == NULL) + { + return NULL; + } + + typename IdToProductMap::iterator i = + associations_.find(typeid(*model)); + + if (i != associations_.end()) + { + return (i->second)(model); + } + return this->OnUnknownType(typeid(*model)); + } + + private: + typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap; + IdToProductMap associations_; + }; + +} // namespace Loki + + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif // end file guardian + diff --git a/shared/loki/Function.h b/shared/loki/Function.h new file mode 100644 index 00000000..2d0ad4bb --- /dev/null +++ b/shared/loki/Function.h @@ -0,0 +1,373 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2005 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_FUNCTION_INC_ +#define LOKI_FUNCTION_INC_ + +// $Id: Function.h 841 2008-03-24 23:58:28Z rich_sposato $ + + +#define LOKI_ENABLE_FUNCTION + +#include <stdexcept> + +#include <loki/Functor.h> +#include <loki/Sequence.h> + +namespace Loki +{ + + //////////////////////////////////////////////////////////////////////////////// + /// \struct Function + /// + /// \ingroup FunctorGroup + /// Allows a boost/TR1 like usage of Functor. + /// + /// \par Usage + /// + /// - free functions: e.g. \code Function<int(int,int)> f(&freeFunction); + /// \endcode + /// - member functions: e.g \code Function<int()> f(&object,&ObjectType::memberFunction); + /// \endcode + /// + /// see also test/Function/FunctionTest.cpp (the modified test program from boost) + //////////////////////////////////////////////////////////////////////////////// + + template<class R = void()> + struct Function; + + + template<class R> + struct Function<R()> : public Functor<R> + { + typedef Functor<R> FBase; + + Function() : FBase() {} + + Function(const Function& func) : FBase() + { + if( !func.empty()) + FBase::operator=(func); + } + + // test on emptiness + template<class R2> + Function(Function<R2()> func) : FBase() + { + if(!func.empty()) + FBase::operator=(func); + } + + // clear by '= 0' + Function(const int i) : FBase() + { + if(i==0) + FBase::clear(); + else + throw std::runtime_error("Loki::Function(const int i): i!=0"); + } + + template<class Func> + Function(Func func) : FBase(func) {} + + template<class Host, class Func> + Function(const Host& host, const Func& func) : FBase(host,func) {} + + }; + + +//////////////////////////////////////////////////////////////////////////////// +// macros for the repetitions +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_FUNCTION_BODY \ + \ + Function() : FBase() {} \ + \ + Function(const Function& func) : FBase() \ + { \ + if( !func.empty()) \ + FBase::operator=(func); \ + } \ + \ + Function(const int i) : FBase() \ + { \ + if(i==0) \ + FBase::clear(); \ + else \ + throw std::runtime_error( \ + "Loki::Function(const int i): i!=0"); \ + } \ + \ + template<class Func> \ + Function(Func func) : FBase(func) {} \ + \ + template<class Host, class Func> \ + Function(const Host& host, const Func& func): FBase(host,func) {} + + +#define LOKI_FUNCTION_R2_CTOR_BODY \ + \ + : FBase() \ + { \ + if(!func.empty()) \ + FBase::operator=(func); \ + } + + +//////////////////////////////////////////////////////////////////////////////// +// repetitions +//////////////////////////////////////////////////////////////////////////////// + + template<> + struct Function<> + : public Loki::Functor<> + { + typedef Functor<> FBase; + + template<class R2> + Function(Function<R2()> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY // if compilation breaks here then + // Function.h was not included before + // Functor.h, check your include order + // or define LOKI_ENABLE_FUNCTION + }; + + template<class R,class P01> + struct Function<R(P01)> + : public Loki::Functor<R, Seq<P01> > + { + typedef Functor<R, Seq<P01> > FBase; + + template<class R2,class Q01> + Function(Function<R2(Q01)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R,class P01,class P02> + struct Function<R(P01,P02)> + : public Functor<R, Seq<P01,P02> > + { + typedef Functor<R, Seq<P01,P02> > FBase; + + template<class R2,class Q01, class Q02> + Function(Function<R2(Q01,Q02)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R,class P01,class P02, class P03> + struct Function<R(P01,P02,P03)> + : public Functor<R, Seq<P01,P02,P03> > + { + typedef Functor<R, Seq<P01,P02,P03> > FBase; + + template<class R2,class Q01, class Q02,class Q03> + Function(Function<R2(Q01,Q02,Q03)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R,class P01,class P02, class P03,class P04> + struct Function<R(P01,P02,P03,P04)> + : public Functor<R, Seq<P01,P02,P03,P04> > + { + typedef Functor<R, Seq<P01,P02,P03,P04> > FBase; + + template<class R2,class Q01,class Q02, class Q03,class Q04> + Function(Function<R2(Q01,Q02,Q03,Q04)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R,class P01,class P02, class P03,class P04,class P05> + struct Function<R(P01,P02,P03,P04,P05)> + : public Functor<R, Seq<P01,P02,P03,P04,P05> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05> > FBase; + + template<class R2,class Q01,class Q02, class Q03,class Q04,class Q05> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06> + struct Function<R(P01,P02,P03,P04,P05,P06)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07> + struct Function<R(P01,P02,P03,P04,P05,P06,P07)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09 > > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10, + class P11> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11> >FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10, + class Q11> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10, + class P11,class P12> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10, + class Q11,class Q12> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10, + class P11,class P12, class P13> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10, + class Q11,class Q12, class Q13> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10, + class P11,class P12, class P13,class P14> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14> > FBase; + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10, + class Q11,class Q12, class Q13,class Q14> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + + template<class R, class P01,class P02, class P03,class P04,class P05, + class P06,class P07, class P08,class P09,class P10, + class P11,class P12, class P13,class P14,class P15> + struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15)> + : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15> > + { + typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15> > FBase; + + template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05, + class Q06,class Q07, class Q08,class Q09,class Q10, + class Q11,class Q12, class Q13,class Q14,class Q15> + Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14,Q15)> func) + LOKI_FUNCTION_R2_CTOR_BODY + + LOKI_FUNCTION_BODY + }; + +}// namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/Functor.h b/shared/loki/Functor.h new file mode 100644 index 00000000..bcba855d --- /dev/null +++ b/shared/loki/Functor.h @@ -0,0 +1,1789 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_FUNCTOR_INC_ +#define LOKI_FUNCTOR_INC_ + +// $Id: Functor.h 750 2006-10-17 19:50:02Z syntheticpp $ + + +#include "Typelist.h" +#include "Sequence.h" +#include "EmptyType.h" +#include "SmallObj.h" +#include "TypeTraits.h" +#include <typeinfo> +#include <memory> + +/// \defgroup FunctorGroup Function objects + +#ifndef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT +//#define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT +#endif + +#ifndef LOKI_FUNCTORS_ARE_COMPARABLE +//#define LOKI_FUNCTORS_ARE_COMPARABLE +#endif + + +/// \namespace Loki +/// All classes of Loki are in the Loki namespace +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl (internal) +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <typename R, template <class, class> class ThreadingModel> + struct FunctorImplBase +#ifdef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT + { +#else + : public SmallValueObject<ThreadingModel> + { + inline FunctorImplBase() : + SmallValueObject<ThreadingModel>() {} + inline FunctorImplBase(const FunctorImplBase&) : + SmallValueObject<ThreadingModel>() {} +#endif + + typedef R ResultType; + typedef FunctorImplBase<R, ThreadingModel> FunctorImplBaseType; + + typedef EmptyType Parm1; + typedef EmptyType Parm2; + typedef EmptyType Parm3; + typedef EmptyType Parm4; + typedef EmptyType Parm5; + typedef EmptyType Parm6; + typedef EmptyType Parm7; + typedef EmptyType Parm8; + typedef EmptyType Parm9; + typedef EmptyType Parm10; + typedef EmptyType Parm11; + typedef EmptyType Parm12; + typedef EmptyType Parm13; + typedef EmptyType Parm14; + typedef EmptyType Parm15; + + + virtual ~FunctorImplBase() + {} + + virtual FunctorImplBase* DoClone() const = 0; + + template <class U> + static U* Clone(U* pObj) + { + if (!pObj) return 0; + U* pClone = static_cast<U*>(pObj->DoClone()); + assert(typeid(*pClone) == typeid(*pObj)); + return pClone; + } + + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + virtual bool operator==(const FunctorImplBase&) const = 0; + +#endif + + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// macro LOKI_DEFINE_CLONE_FUNCTORIMPL +// Implements the DoClone function for a functor implementation +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_DEFINE_CLONE_FUNCTORIMPL(Cls) \ + virtual Cls* DoClone() const { return new Cls(*this); } + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// The base class for a hierarchy of functors. The FunctorImpl class is not used +// directly; rather, the Functor class manages and forwards to a pointer to +// FunctorImpl +// You may want to derive your own functors from FunctorImpl. +// Specializations of FunctorImpl for up to 15 parameters follow +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, class TList, + template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL> + class FunctorImpl; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 0 (zero) parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, template <class, class> class ThreadingModel> + class FunctorImpl<R, NullType, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + virtual R operator()() = 0; + }; + + //////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 1 parameter +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + virtual R operator()(Parm1) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 2 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + virtual R operator()(Parm1, Parm2) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 3 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + virtual R operator()(Parm1, Parm2, Parm3) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 4 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 5 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 6 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 7 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7>, ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 8 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 9 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 10 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, + template <class, class> class ThreadingModel> + class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 11 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 12 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 13 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 14 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, typename P14, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, + P14>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 15 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, typename P14, + typename P15, template <class, class> class ThreadingModel> + class FunctorImpl<R, + Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, + P14, P15>, + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + typedef typename TypeTraits<P15>::ParameterType Parm15; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14, + Parm15) = 0; + }; + +#ifndef LOKI_DISABLE_TYPELIST_MACROS + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 1 parameter +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_1(P1), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + virtual R operator()(Parm1) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 2 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_2(P1, P2), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + virtual R operator()(Parm1, Parm2) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 3 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_3(P1, P2, P3), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + virtual R operator()(Parm1, Parm2, Parm3) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 4 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_4(P1, P2, P3, P4), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 5 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_5(P1, P2, P3, P4, P5), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 6 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_6(P1, P2, P3, P4, P5, P6), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 7 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_7(P1, P2, P3, P4, P5, P6, P7), ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 8 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_8(P1, P2, P3, P4, P5, P6, P7, P8), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 9 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_9(P1, P2, P3, P4, P5, P6, P7, P8, P9), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 10 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, + template <class, class> class ThreadingModel> + class FunctorImpl<R, LOKI_TYPELIST_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 11 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + LOKI_TYPELIST_11(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 12 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + LOKI_TYPELIST_12(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 13 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + LOKI_TYPELIST_13(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 14 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, typename P14, + template <class, class> class ThreadingModel> + class FunctorImpl<R, + LOKI_TYPELIST_14(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, + P14), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorImpl +// Specialization for 15 parameters +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7, typename P8, typename P9, + typename P10, typename P11, typename P12, typename P13, typename P14, + typename P15, template <class, class> class ThreadingModel> + class FunctorImpl<R, + LOKI_TYPELIST_15(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, + P14, P15), + ThreadingModel> + : public Private::FunctorImplBase<R, ThreadingModel> + { + public: + typedef R ResultType; + typedef typename TypeTraits<P1>::ParameterType Parm1; + typedef typename TypeTraits<P2>::ParameterType Parm2; + typedef typename TypeTraits<P3>::ParameterType Parm3; + typedef typename TypeTraits<P4>::ParameterType Parm4; + typedef typename TypeTraits<P5>::ParameterType Parm5; + typedef typename TypeTraits<P6>::ParameterType Parm6; + typedef typename TypeTraits<P7>::ParameterType Parm7; + typedef typename TypeTraits<P8>::ParameterType Parm8; + typedef typename TypeTraits<P9>::ParameterType Parm9; + typedef typename TypeTraits<P10>::ParameterType Parm10; + typedef typename TypeTraits<P11>::ParameterType Parm11; + typedef typename TypeTraits<P12>::ParameterType Parm12; + typedef typename TypeTraits<P13>::ParameterType Parm13; + typedef typename TypeTraits<P14>::ParameterType Parm14; + typedef typename TypeTraits<P15>::ParameterType Parm15; + virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6, + Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14, + Parm15) = 0; + }; + +#endif //LOKI_DISABLE_TYPELIST_MACROS + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorHandler +// Wraps functors and pointers to functions +//////////////////////////////////////////////////////////////////////////////// + + template <class ParentFunctor, typename Fun> + class FunctorHandler + : public ParentFunctor::Impl + { + typedef typename ParentFunctor::Impl Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + + FunctorHandler(const Fun& fun) : f_(fun) {} + + LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler) + + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + + bool operator==(const typename Base::FunctorImplBaseType& rhs) const + { + // there is no static information if Functor holds a member function + // or a free function; this is the main difference to tr1::function + if(typeid(*this) != typeid(rhs)) + return false; // cannot be equal + + const FunctorHandler& fh = static_cast<const FunctorHandler&>(rhs); + // if this line gives a compiler error, you are using a function object. + // you need to implement bool MyFnObj::operator == (const MyFnObj&) const; + return f_==fh.f_; + } +#endif + // operator() implementations for up to 15 arguments + + ResultType operator()() + { return f_(); } + + ResultType operator()(Parm1 p1) + { return f_(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f_(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f_(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f_(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f_(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f_(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return f_(p1, p2, p3, p4, p5, p6, p7); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15); + } + + private: + Fun f_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorHandler +// Wraps pointers to member functions +//////////////////////////////////////////////////////////////////////////////// + + template <class ParentFunctor, typename PointerToObj, + typename PointerToMemFn> + class MemFunHandler : public ParentFunctor::Impl + { + typedef typename ParentFunctor::Impl Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + + MemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn) + : pObj_(pObj), pMemFn_(pMemFn) + {} + + LOKI_DEFINE_CLONE_FUNCTORIMPL(MemFunHandler) + + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + bool operator==(const typename Base::FunctorImplBaseType& rhs) const + { + if(typeid(*this) != typeid(rhs)) + return false; // cannot be equal + + const MemFunHandler& mfh = static_cast<const MemFunHandler&>(rhs); + // if this line gives a compiler error, you are using a function object. + // you need to implement bool MyFnObj::operator == (const MyFnObj&) const; + return pObj_==mfh.pObj_ && pMemFn_==mfh.pMemFn_; + } +#endif + + ResultType operator()() + { return ((*pObj_).*pMemFn_)(); } + + ResultType operator()(Parm1 p1) + { return ((*pObj_).*pMemFn_)(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return ((*pObj_).*pMemFn_)(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return ((*pObj_).*pMemFn_)(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15); + } + + private: + PointerToObj pObj_; + PointerToMemFn pMemFn_; + }; + +//////////////////////////////////////////////////////////////////////////////// +// TR1 exception +////////////////////////////////////////////////////////////////////////////////// + +#ifdef LOKI_ENABLE_FUNCTION + + class bad_function_call : public std::runtime_error + { + public: + bad_function_call() : std::runtime_error("bad_function_call in Loki::Functor") + {} + }; + +#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL if(empty()) throw bad_function_call(); + +#else + +#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// \class Functor +/// +/// \ingroup FunctorGroup +/// A generalized functor implementation with value semantics +/// +/// \par Macro: LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT +/// Define +/// \code LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT \endcode +/// to avoid static instantiation/delete +/// order problems. +/// It often helps against crashes when using static Functors and multi threading. +/// Defining also removes problems when unloading Dlls which hosts +/// static Functor objects. +/// +/// \par Macro: LOKI_FUNCTORS_ARE_COMPARABLE +/// To enable the operator== define the macro +/// \code LOKI_FUNCTORS_ARE_COMPARABLE \endcode +/// The macro is disabled by default, because it breaks compiling functor +/// objects which have no operator== implemented, keep in mind when you enable +/// operator==. +//////////////////////////////////////////////////////////////////////////////// + template <typename R = void, class TList = NullType, + template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL> + class Functor + { + public: + // Handy type definitions for the body type + typedef FunctorImpl<R, TList, ThreadingModel> Impl; + typedef R ResultType; + typedef TList ParmList; + typedef typename Impl::Parm1 Parm1; + typedef typename Impl::Parm2 Parm2; + typedef typename Impl::Parm3 Parm3; + typedef typename Impl::Parm4 Parm4; + typedef typename Impl::Parm5 Parm5; + typedef typename Impl::Parm6 Parm6; + typedef typename Impl::Parm7 Parm7; + typedef typename Impl::Parm8 Parm8; + typedef typename Impl::Parm9 Parm9; + typedef typename Impl::Parm10 Parm10; + typedef typename Impl::Parm11 Parm11; + typedef typename Impl::Parm12 Parm12; + typedef typename Impl::Parm13 Parm13; + typedef typename Impl::Parm14 Parm14; + typedef typename Impl::Parm15 Parm15; + + // Member functions + + Functor() : spImpl_(0) + {} + + Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())) + {} + + Functor(std::auto_ptr<Impl> spImpl) : spImpl_(spImpl) + {} + + template <typename Fun> + Functor(Fun fun) + : spImpl_(new FunctorHandler<Functor, Fun>(fun)) + {} + + template <class PtrObj, typename MemFn> + Functor(const PtrObj& p, MemFn memFn) + : spImpl_(new MemFunHandler<Functor, PtrObj, MemFn>(p, memFn)) + {} + + typedef Impl * (std::auto_ptr<Impl>::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const + { + return spImpl_.get() ? &std::auto_ptr<Impl>::get : 0; + } + + Functor& operator=(const Functor& rhs) + { + Functor copy(rhs); + // swap auto_ptrs by hand + Impl* p = spImpl_.release(); + spImpl_.reset(copy.spImpl_.release()); + copy.spImpl_.reset(p); + return *this; + } + +#ifdef LOKI_ENABLE_FUNCTION + + bool empty() const + { + return spImpl_.get() == 0; + } + + void clear() + { + spImpl_.reset(0); + } +#endif + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + bool operator==(const Functor& rhs) const + { + if(spImpl_.get()==0 && rhs.spImpl_.get()==0) + return true; + if(spImpl_.get()!=0 && rhs.spImpl_.get()!=0) + return *spImpl_.get() == *rhs.spImpl_.get(); + else + return false; + } + + bool operator!=(const Functor& rhs) const + { + return !(*this==rhs); + } +#endif + + // operator() implementations for up to 15 arguments + + ResultType operator()() const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(); + } + + ResultType operator()(Parm1 p1) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1); + } + + ResultType operator()(Parm1 p1, Parm2 p2) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13, p14); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) const + { + LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL + return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, + p12, p13, p14, p15); + } + + private: + std::auto_ptr<Impl> spImpl_; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// +// BindersFirst and Chainer +// +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class Fctor> struct BinderFirstTraits; + + template <typename R, class TList, template <class, class> class ThreadingModel> + struct BinderFirstTraits< Functor<R, TList, ThreadingModel> > + { + typedef Functor<R, TList, ThreadingModel> OriginalFunctor; + + typedef typename TL::Erase<TList,typename TL::TypeAt<TList, 0>::Result> + ::Result + ParmList; + + typedef typename TL::TypeAt<TList, 0>::Result OriginalParm1; + + typedef Functor<R, ParmList, ThreadingModel> BoundFunctorType; + + typedef typename BoundFunctorType::Impl Impl; + + }; + + + template<class T> + struct BinderFirstBoundTypeStorage; + + template<class T> + struct BinderFirstBoundTypeStorage + { + typedef typename TypeTraits<T>::ParameterType RefOrValue; + }; + + template <typename R, class TList, template <class, class> class ThreadingModel> + struct BinderFirstBoundTypeStorage< Functor<R, TList, ThreadingModel> > + { + typedef Functor<R, TList, ThreadingModel> OriginalFunctor; + typedef const typename TypeTraits<OriginalFunctor>::ReferredType RefOrValue; + }; + + + } // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +/// \class BinderFirst +/// +/// \ingroup FunctorGroup +/// Binds the first parameter of a Functor object to a specific value +//////////////////////////////////////////////////////////////////////////////// + + template <class OriginalFunctor> + class BinderFirst + : public Private::BinderFirstTraits<OriginalFunctor>::Impl + { + typedef typename Private::BinderFirstTraits<OriginalFunctor>::Impl Base; + typedef typename OriginalFunctor::ResultType ResultType; + + typedef typename OriginalFunctor::Parm1 BoundType; + + typedef typename Private::BinderFirstBoundTypeStorage< + typename Private::BinderFirstTraits<OriginalFunctor> + ::OriginalParm1> + ::RefOrValue + BoundTypeStorage; + + typedef typename OriginalFunctor::Parm2 Parm1; + typedef typename OriginalFunctor::Parm3 Parm2; + typedef typename OriginalFunctor::Parm4 Parm3; + typedef typename OriginalFunctor::Parm5 Parm4; + typedef typename OriginalFunctor::Parm6 Parm5; + typedef typename OriginalFunctor::Parm7 Parm6; + typedef typename OriginalFunctor::Parm8 Parm7; + typedef typename OriginalFunctor::Parm9 Parm8; + typedef typename OriginalFunctor::Parm10 Parm9; + typedef typename OriginalFunctor::Parm11 Parm10; + typedef typename OriginalFunctor::Parm12 Parm11; + typedef typename OriginalFunctor::Parm13 Parm12; + typedef typename OriginalFunctor::Parm14 Parm13; + typedef typename OriginalFunctor::Parm15 Parm14; + typedef EmptyType Parm15; + + public: + + BinderFirst(const OriginalFunctor& fun, BoundType bound) + : f_(fun), b_(bound) + {} + + LOKI_DEFINE_CLONE_FUNCTORIMPL(BinderFirst) + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + bool operator==(const typename Base::FunctorImplBaseType& rhs) const + { + if(typeid(*this) != typeid(rhs)) + return false; // cannot be equal + // if this line gives a compiler error, you are using a function object. + // you need to implement bool MyFnObj::operator == (const MyFnObj&) const; + return f_ == ((static_cast<const BinderFirst&> (rhs)).f_) && + b_ == ((static_cast<const BinderFirst&> (rhs)).b_); + } +#endif + + // operator() implementations for up to 15 arguments + + ResultType operator()() + { return f_(b_); } + + ResultType operator()(Parm1 p1) + { return f_(b_, p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f_(b_, p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f_(b_, p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f_(b_, p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f_(b_, p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f_(b_, p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + private: + OriginalFunctor f_; + BoundTypeStorage b_; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// Binds the first parameter of a Functor object to a specific value +/// \ingroup FunctorGroup +//////////////////////////////////////////////////////////////////////////////// + + template <class Fctor> + typename Private::BinderFirstTraits<Fctor>::BoundFunctorType + BindFirst( + const Fctor& fun, + typename Fctor::Parm1 bound) + { + typedef typename Private::BinderFirstTraits<Fctor>::BoundFunctorType + Outgoing; + + return Outgoing(std::auto_ptr<typename Outgoing::Impl>( + new BinderFirst<Fctor>(fun, bound))); + } + +//////////////////////////////////////////////////////////////////////////////// +/// \class Chainer +/// +/// \ingroup FunctorGroup +/// Chains two functor calls one after another +//////////////////////////////////////////////////////////////////////////////// + + template <typename Fun1, typename Fun2> + class Chainer : public Fun2::Impl + { + typedef Fun2 Base; + + public: + typedef typename Base::ResultType ResultType; + typedef typename Base::Parm1 Parm1; + typedef typename Base::Parm2 Parm2; + typedef typename Base::Parm3 Parm3; + typedef typename Base::Parm4 Parm4; + typedef typename Base::Parm5 Parm5; + typedef typename Base::Parm6 Parm6; + typedef typename Base::Parm7 Parm7; + typedef typename Base::Parm8 Parm8; + typedef typename Base::Parm9 Parm9; + typedef typename Base::Parm10 Parm10; + typedef typename Base::Parm11 Parm11; + typedef typename Base::Parm12 Parm12; + typedef typename Base::Parm13 Parm13; + typedef typename Base::Parm14 Parm14; + typedef typename Base::Parm15 Parm15; + + Chainer(const Fun1& fun1, const Fun2& fun2) : f1_(fun1), f2_(fun2) {} + + LOKI_DEFINE_CLONE_FUNCTORIMPL(Chainer) + +#ifdef LOKI_FUNCTORS_ARE_COMPARABLE + + bool operator==(const typename Base::Impl::FunctorImplBaseType& rhs) const + { + if(typeid(*this) != typeid(rhs)) + return false; // cannot be equal + // if this line gives a compiler error, you are using a function object. + // you need to implement bool MyFnObj::operator == (const MyFnObj&) const; + return f1_ == ((static_cast<const Chainer&> (rhs)).f2_) && + f2_ == ((static_cast<const Chainer&> (rhs)).f1_); + } +#endif + + // operator() implementations for up to 15 arguments + + ResultType operator()() + { return f1_(), f2_(); } + + ResultType operator()(Parm1 p1) + { return f1_(p1), f2_(p1); } + + ResultType operator()(Parm1 p1, Parm2 p2) + { return f1_(p1, p2), f2_(p1, p2); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) + { return f1_(p1, p2, p3), f2_(p1, p2, p3); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) + { return f1_(p1, p2, p3, p4), f2_(p1, p2, p3, p4); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) + { return f1_(p1, p2, p3, p4, p5), f2_(p1, p2, p3, p4, p5); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6) + { return f1_(p1, p2, p3, p4, p5, p6), f2_(p1, p2, p3, p4, p5, p6); } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7) + { + return f1_(p1, p2, p3, p4, p5, p6, p7), + f2_(p1, p2, p3, p4, p5, p6, p7); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8), + f2_(p1, p2, p3, p4, p5, p6, p7, p8); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14); + } + + ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5, + Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11, + Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) + { + return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15), + f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, + p14, p15); + } + + private: + Fun1 f1_; + Fun2 f2_; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// Chains two functor calls one after another +/// \ingroup FunctorGroup +//////////////////////////////////////////////////////////////////////////////// + + + template <class Fun1, class Fun2> + Fun2 Chain( + const Fun1& fun1, + const Fun2& fun2) + { + return Fun2(std::auto_ptr<typename Fun2::Impl>( + new Chainer<Fun1, Fun2>(fun1, fun2))); + } + +} // namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/HierarchyGenerators.h b/shared/loki/HierarchyGenerators.h new file mode 100644 index 00000000..3fa11ffc --- /dev/null +++ b/shared/loki/HierarchyGenerators.h @@ -0,0 +1,291 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_HIERARCHYGENERATORS_INC_ +#define LOKI_HIERARCHYGENERATORS_INC_ + +// $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +#include "Typelist.h" +#include "TypeTraits.h" +#include "EmptyType.h" + +namespace Loki +{ +#if defined(_MSC_VER) && _MSC_VER >= 1300 +#pragma warning( push ) + // 'class1' : base-class 'class2' is already a base-class of 'class3' +#pragma warning( disable : 4584 ) +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// class template GenScatterHierarchy +// Generates a scattered hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Unit is a template of one arg): +// GenScatterHierarchy<TList, Unit> +// The generated class inherits all classes generated by instantiating the +// template 'Unit' with the types contained in TList +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + // The following type helps to overcome subtle flaw in the original + // implementation of GenScatterHierarchy. + // The flaw is revealed when the input type list of GenScatterHierarchy + // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). + // In this case GenScatterHierarchy will contain multiple bases of the same + // type and some of them will not be reachable (per 10.3). + // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)> + // is not reachable in any way! + template<class, class> + struct ScatterHierarchyTag; + } + + template <class TList, template <class> class Unit> + class GenScatterHierarchy; + + template <class T1, class T2, template <class> class Unit> + class GenScatterHierarchy<Typelist<T1, T2>, Unit> + : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> + , public GenScatterHierarchy<T2, Unit> + { + public: + typedef Typelist<T1, T2> TList; + // Insure that LeftBase is unique and therefore reachable + typedef GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> LeftBase; + typedef GenScatterHierarchy<T2, Unit> RightBase; + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + + // In the middle *unique* class that resolve possible ambiguity + template <class T1, class T2, template <class> class Unit> + class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> + : public GenScatterHierarchy<T1, Unit> + { + }; + + template <class AtomicType, template <class> class Unit> + class GenScatterHierarchy : public Unit<AtomicType> + { + typedef Unit<AtomicType> LeftBase; + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + + template <template <class> class Unit> + class GenScatterHierarchy<NullType, Unit> + { + template <typename T> struct Rebind + { + typedef Unit<T> Result; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Field +// Accesses a field in an object of a type generated with GenScatterHierarchy +// Invocation (obj is an object of a type H generated with GenScatterHierarchy, +// T is a type in the typelist used to generate H): +// Field<T>(obj) +// returns a reference to Unit<T>, where Unit is the template used to generate H +//////////////////////////////////////////////////////////////////////////////// + + template <class T, class H> + typename H::template Rebind<T>::Result& Field(H& obj) + { + return obj; + } + + template <class T, class H> + const typename H::template Rebind<T>::Result& Field(const H& obj) + { + return obj; + } + +//////////////////////////////////////////////////////////////////////////////// +// function template TupleUnit +// The building block of tuples +//////////////////////////////////////////////////////////////////////////////// + + template <class T> + struct TupleUnit + { + T value_; + operator T&() { return value_; } + operator const T&() const { return value_; } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Tuple +// Implements a tuple class that holds a number of values and provides field +// access to them via the Field function (below) +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> + struct Tuple : public GenScatterHierarchy<TList, TupleUnit> + { + }; + +//////////////////////////////////////////////////////////////////////////////// +// helper class template FieldHelper +// See Field below +//////////////////////////////////////////////////////////////////////////////// + + template <class H, unsigned int i> struct FieldHelper; + + template <class H> + struct FieldHelper<H, 0> + { + typedef typename H::TList::Head ElementType; + typedef typename H::template Rebind<ElementType>::Result UnitType; + + enum + { + isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, + isConst = TypeTraits<H>::isConst + }; + + typedef const typename H::LeftBase ConstLeftBase; + + typedef typename Select<isConst, ConstLeftBase, + typename H::LeftBase>::Result LeftBase; + + typedef typename Select<isTuple, ElementType, + UnitType>::Result UnqualifiedResultType; + + typedef typename Select<isConst, const UnqualifiedResultType, + UnqualifiedResultType>::Result ResultType; + + static ResultType& Do(H& obj) + { + LeftBase& leftBase = obj; + return leftBase; + } + }; + + template <class H, unsigned int i> + struct FieldHelper + { + typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType; + typedef typename H::template Rebind<ElementType>::Result UnitType; + + enum + { + isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, + isConst = TypeTraits<H>::isConst + }; + + typedef const typename H::RightBase ConstRightBase; + + typedef typename Select<isConst, ConstRightBase, + typename H::RightBase>::Result RightBase; + + typedef typename Select<isTuple, ElementType, + UnitType>::Result UnqualifiedResultType; + + typedef typename Select<isConst, const UnqualifiedResultType, + UnqualifiedResultType>::Result ResultType; + + static ResultType& Do(H& obj) + { + RightBase& rightBase = obj; + return FieldHelper<RightBase, i - 1>::Do(rightBase); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// function template Field +// Accesses a field in an object of a type generated with GenScatterHierarchy +// Invocation (obj is an object of a type H generated with GenScatterHierarchy, +// i is the index of a type in the typelist used to generate H): +// Field<i>(obj) +// returns a reference to Unit<T>, where Unit is the template used to generate H +// and T is the i-th type in the typelist +//////////////////////////////////////////////////////////////////////////////// + + template <int i, class H> + typename FieldHelper<H, i>::ResultType& + Field(H& obj) + { + return FieldHelper<H, i>::Do(obj); + } + +// template <int i, class H> +// const typename FieldHelper<H, i>::ResultType& +// Field(const H& obj) +// { +// return FieldHelper<H, i>::Do(obj); +// } + +//////////////////////////////////////////////////////////////////////////////// +// class template GenLinearHierarchy +// Generates a linear hierarchy starting from a typelist and a template +// Invocation (TList is a typelist, Unit is a template of two args): +// GenScatterHierarchy<TList, Unit> +//////////////////////////////////////////////////////////////////////////////// + + template + < + class TList, + template <class AtomicType, class Base> class Unit, + class Root = EmptyType + > + class GenLinearHierarchy; + + template + < + class T1, + class T2, + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root> + : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> > + { + }; + + template + < + class T, + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root> + : public Unit<T, Root> + { + }; + + template + < + template <class, class> class Unit, + class Root + > + class GenLinearHierarchy<NullType , Unit, Root> + : public Root // is this better: Unit<NullType, Root> ? + { + }; + +#if defined(_MSC_VER) && _MSC_VER >= 1300 +#pragma warning( pop ) +#endif +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/Key.h b/shared/loki/Key.h new file mode 100644 index 00000000..4daaa603 --- /dev/null +++ b/shared/loki/Key.h @@ -0,0 +1,764 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 by Guillaume Chatelet +// +// Code covered by the MIT License +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The authors make no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +// +// This code DOES NOT accompany the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_KEY_INC_ +#define LOKI_KEY_INC_ + +// $Id: Key.h 771 2006-10-27 18:05:03Z clitte_bbt $ + + +#include <loki/Factory.h> + +namespace Loki +{ + + template< + class Factory, + typename IdentifierType + > + class Key; + + template<class F, typename I> + bool operator==(const Key<F, I> &k1, const Key<F, I> &k2); + + template<class F, typename I> + bool operator<(const Key<F, I> &k1, const Key<F, I> &k2); + + + /** + * A Key class + */ + template< + class Factory, + typename IdentifierType + > + class Key + { + typedef typename Factory::Parm1 Parm1; + typedef typename Factory::Parm2 Parm2; + typedef typename Factory::Parm3 Parm3; + typedef typename Factory::Parm4 Parm4; + typedef typename Factory::Parm5 Parm5; + typedef typename Factory::Parm6 Parm6; + typedef typename Factory::Parm7 Parm7; + typedef typename Factory::Parm8 Parm8; + typedef typename Factory::Parm9 Parm9; + typedef typename Factory::Parm10 Parm10; + typedef typename Factory::Parm11 Parm11; + typedef typename Factory::Parm12 Parm12; + typedef typename Factory::Parm13 Parm13; + typedef typename Factory::Parm14 Parm14; + typedef typename Factory::Parm15 Parm15; + public: + // member variables + int count; // should be const, but constness prevent default copy ctor + IdentifierType id; + Parm1 p1; + Parm2 p2; + Parm3 p3; + Parm4 p4; + Parm5 p5; + Parm6 p6; + Parm7 p7; + Parm8 p8; + Parm9 p9; + Parm10 p10; + Parm11 p11; + Parm12 p12; + Parm13 p13; + Parm14 p14; + Parm15 p15; + + // member functions + Key() : count(-1) + { + } + + Key(const IdentifierType& id) : count(0) + { + this->id = id; + } + + Key(const IdentifierType& id, + Parm1 &p1) : count(1) + { + this->id = id; + this->p1 = p1; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2) : count(2) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3) : count(3) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4) : count(4) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5) : count(5) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6) : count(6) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7 ) : count(7) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8) : count(8) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9) : count(9) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9,Parm10 &p10) : count(10) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10, + Parm11 &p11) : count(11) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + this->p11 = p11; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10, + Parm11 &p11, Parm12 &p12) : count(12) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + this->p11 = p11; + this->p12 = p12; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10, + Parm11 &p11, Parm12 &p12, Parm13 &p13) : count(13) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + this->p11 = p11; + this->p12 = p12; + this->p13 = p13; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10, + Parm11 &p11, Parm12 &p12, Parm13 &p13, Parm14 &p14) : count(14) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + this->p11 = p11; + this->p12 = p12; + this->p13 = p13; + this->p14 = p14; + } + + Key(const IdentifierType& id, + Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5, + Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10, + Parm11 &p11, Parm12 &p12, Parm13 &p13, Parm14 &p14, Parm15 &p15) : count(15) + { + this->id = id; + this->p1 = p1; + this->p2 = p2; + this->p3 = p3; + this->p4 = p4; + this->p5 = p5; + this->p6 = p6; + this->p7 = p7; + this->p8 = p8; + this->p9 = p9; + this->p10 = p10; + this->p11 = p11; + this->p12 = p12; + this->p13 = p13; + this->p14 = p14; + this->p15 = p15; + } + + template<class F, typename I> + friend bool operator==(const Key<F, I> &k1, const Key<F, I> &k2); + + template<class F, typename I> + friend bool operator<(const Key<F, I> &k1, const Key<F, I> &k2); + }; + + + template<class F, typename I> + bool operator==(const Key<F, I> &k1, const Key<F, I> &k2) + { + if( k1.count != k2.count ) + return false; + switch(k1.count){ + case -1: + return true; + case 0: + if( k1.id == k2.id ) + return true; + else + return false; + case 1: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) ) + return true; + else + return false; + case 2: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) ) + return true; + else + return false; + case 3: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) ) + return true; + else + return false; + case 4: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) ) + return true; + else + return false; + case 5: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) ) + return true; + else + return false; + case 6: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) ) + return true; + else + return false; + case 7: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) ) + return true; + else + return false; + case 8: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) ) + return true; + else + return false; + case 9: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) ) + return true; + else + return false; + case 10: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) ) + return true; + else + return false; + case 11: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) && + (k1.p11 == k2.p11) ) + return true; + else + return false; + case 12: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) && + (k1.p11 == k2.p11) && + (k1.p12 == k2.p12) ) + return true; + else + return false; + case 13: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) && + (k1.p11 == k2.p11) && + (k1.p12 == k2.p12) && + (k1.p13 == k2.p13) ) + return true; + else + return false; + case 14: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) && + (k1.p11 == k2.p11) && + (k1.p12 == k2.p12) && + (k1.p13 == k2.p13) && + (k1.p14 == k2.p14) ) + return true; + else + return false; + case 15: + if( (k1.id == k2.id) && + (k1.p1 == k2.p1) && + (k1.p2 == k2.p2) && + (k1.p3 == k2.p3) && + (k1.p4 == k2.p4) && + (k1.p5 == k2.p5) && + (k1.p6 == k2.p6) && + (k1.p7 == k2.p7) && + (k1.p8 == k2.p8) && + (k1.p9 == k2.p9) && + (k1.p10 == k2.p10) && + (k1.p11 == k2.p11) && + (k1.p12 == k2.p12) && + (k1.p13 == k2.p13) && + (k1.p14 == k2.p14) && + (k1.p15 == k2.p15) ) + return true; + else + return false; + default: + return false; + } + } + + + + template<class F, typename I> + bool operator<(const Key<F, I> &k1, const Key<F, I> &k2) + { + if( k1.count < k2.count ) + return true; + switch(k1.count){ + case -1: + return false; + case 0: + if( k1.id < k2.id ) + return true; + else + return false; + case 1: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) ) + return true; + else + return false; + case 2: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) ) + return true; + else + return false; + case 3: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) ) + return true; + else + return false; + case 4: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) ) + return true; + else + return false; + case 5: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) ) + return true; + else + return false; + case 6: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) ) + return true; + else + return false; + case 7: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) ) + return true; + else + return false; + case 8: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) ) + return true; + else + return false; + case 9: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) ) + return true; + else + return false; + case 10: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) ) + return true; + else + return false; + case 11: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) || + (k1.p11 < k2.p11) ) + return true; + else + return false; + case 12: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) || + (k1.p11 < k2.p11) || + (k1.p12 < k2.p12) ) + return true; + else + return false; + case 13: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) || + (k1.p11 < k2.p11) || + (k1.p12 < k2.p12) || + (k1.p13 < k2.p13) ) + return true; + else + return false; + case 14: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) || + (k1.p11 < k2.p11) || + (k1.p12 < k2.p12) || + (k1.p13 < k2.p13) || + (k1.p14 < k2.p14) ) + return true; + else + return false; + case 15: + if( (k1.id < k2.id) || + (k1.p1 < k2.p1) || + (k1.p2 < k2.p2) || + (k1.p3 < k2.p3) || + (k1.p4 < k2.p4) || + (k1.p5 < k2.p5) || + (k1.p6 < k2.p6) || + (k1.p7 < k2.p7) || + (k1.p8 < k2.p8) || + (k1.p9 < k2.p9) || + (k1.p10 < k2.p10) || + (k1.p11 < k2.p11) || + (k1.p12 < k2.p12) || + (k1.p13 < k2.p13) || + (k1.p14 < k2.p14) || + (k1.p15 < k2.p15) ) + return true; + else + return false; + default: + return false; + } + } + + + +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/LevelMutex.h b/shared/loki/LevelMutex.h new file mode 100644 index 00000000..c048000f --- /dev/null +++ b/shared/loki/LevelMutex.h @@ -0,0 +1,1211 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// LevelMutex facility for the Loki Library +// Copyright (c) 2008 Richard Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The author makes no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +// +//////////////////////////////////////////////////////////////////////////////// + +// $Id$ + +/// @file LevelMutex.h Defines classes and functions for LevelMutex facility. + +#ifndef LOKI_LEVEL_MUTEX_H_INCLUDED +#define LOKI_LEVEL_MUTEX_H_INCLUDED + + +// ---------------------------------------------------------------------------- + +#include <vector> +#include <assert.h> +#include <time.h> + +#if defined( _MSC_VER ) + #include <Windows.h> +#else + #include <pthread.h> +#endif + +#if !defined(_WIN32) && !defined(_WIN64) + #include <unistd.h> // declares sleep under Linux +#endif + +/** @par thread_local Keyword + The mutexes require compilers to provide thread local storage - meaning each + thread gets its own copy of the data. The next version of C++ will have a + new keyword, thread_local for that purpose. Some existing compilers already + provide thread local storage using different syntax, so these lines use + thread_local to mimic that syntax. If your compiler provides thread local + storage but using different syntax besides "thread_local", you may want to + modify these lines. If your compiler does not support thread local storage, + you can't use LevelMutex. + */ +#ifndef LOKI_THREAD_LOCAL + #if defined( _MSC_VER ) + #if ( _MSC_VER >= 1300 ) + #define LOKI_THREAD_LOCAL __declspec( thread ) + #else + #error "Only Visual Studio versions 7.0 and after supported." + #endif + + #elif ( __GNUC__ ) + #define LOKI_THREAD_LOCAL __thread + + #else + #warning "Check if your compiler provides thread local storage." + #define LOKI_THREAD_LOCAL thread_local + #endif +#endif + +#if defined( DEBUG ) || defined( _DEBUG ) + #define LOKI_MUTEX_DEBUG_CODE( x ) x +#else + #define LOKI_MUTEX_DEBUG_CODE( x ) +#endif + + +namespace Loki +{ + + +// ---------------------------------------------------------------------------- + +class MutexErrors +{ +public: + + /// @enum Type Possible error conditions detected by LevelMutex functions. + enum Type + { + Success = 0, ///< Operation occurred correctly. + NoProblem, ///< Pre-lock and pre-unlock checks passed. + WrongLevel, ///< All mutexes in container must have same level. + LevelTooLow, ///< Trying to unlock a mutex lower than current level. + LevelTooHigh, ///< Trying to lock a mutex higher than current level. + TryFailed, ///< TryLock call failed to lock mutex. + NullMutexPointer, ///< Container has a NULL pointer in it. + DuplicateMutex, ///< Container must have unique pointers - no duplicates. + EmptyContainer, ///< Container must have at least 1 pointer in it. + AlreadyLocked, ///< TryLock call failed because mutex already locked. + WasntLocked, ///< Unlock failed because mutex was not even locked. + NotRecentLock, ///< Mutex in container was not recently locked by this thread. + NotLockedByThread, ///< Can't unlock a mutex not locked by this thread. + MultiUnlockFailed, ///< MultiUnlock can't unlock at least 1 mutex in container. + TimedOut, ///< Wait time elapsed without locking mutex. + TooMuchRecursion, ///< Tried to relock a PThread mutex which is not re-entrant. + NotInitialized, ///< Tried to lock a PThread mutex which did not get setup. + AlreadyInitialized, ///< PThread mutex initialized before ctor called. + InvalidAttribute, ///< PThread mutex improperly initialized. + InvalidAddress, ///< Bad pointer used to initialize a PThread mutex. + ExceptionThrown, ///< Exception caught in mutex operation. + MayDeadlock, ///< Locking this mutex may cause a deadlock. + OtherError ///< Unknown error occurred. + }; +}; + +// ---------------------------------------------------------------------------- + +/** @class LevelMutexInfo + This monolithic base class stores common info for a template class used to + control mutexes. The template class, LevelMutex, is policy-based class. + + @par Implementation + Each thread has a list of mutexes it locked. When a mutex first gets locked, it + gets added to the head of the list. If locked again, LevelMutex merely increments + a count. When unlocked, the count gets decremented until it reaches zero, and + then it gets removed from the list. Each mutex has a pointer to the mutex most + recently locked by the current thread. The current level of a thread is always + the level of the most recently locked mutex, or UnlockedLevel if the thread does + not have any mutexes locked now. A mutex is considered "recently" locked if it is at + the head of the list, or the same level as the current mutex and also locked by the + current thread. + + @par Class Invariants + This class maintains invariants for each LevelMutexInfo so that no function + calls corrupt a mutex. Each function makes a call to IsValid at the start so + that LevelMutex knows it acts on valid internal data. Many functions call + IsValid again when they return to insure the function did not leave any data in + an invalid state. The exit call to IsValid occurs through a tiny helper class + called Checker to insure all data remain valid even when exceptions occur. + Another helper class, MutexUndoer, unlocks mutexes in a container if an + exception occurs during calls to MultiLock. + + @par Error Results + Many functions return an enum value to indicate an error status. Many enum values + indicate errors detected within LevelMutex, but some indicate errors found in policy + classes, SpinLevelMutex and SleepLevelMutex. + */ + +class LevelMutexInfo +{ +public: + + /** Level for thread that has not locked any mutex. Maximum possible level + for a mutex is UnlockedLevel-1; No mutex may have a level of UnlockedLevel. + */ + static const unsigned int UnlockedLevel = 0xFFFFFFFF; + + /// Container for locking multiple mutexes at once. + typedef ::std::vector< volatile LevelMutexInfo * > MutexContainer; + typedef MutexContainer::iterator LevelMutexContainerIter; + typedef MutexContainer::const_iterator LevelMutexContainerCIter; + typedef MutexContainer::reverse_iterator LevelMutexContainerRIter; + typedef MutexContainer::const_reverse_iterator LevelMutexContainerCRIter; + + /** Locks several mutexes at once. Requires O(m + n*n) actions where m is the + number of mutexes currently locked by the thread and n is the number of mutexes + in the container. This provides strong exception safety. If an exception occurs, + any mutexes that were locked during this call will get unlocked. + @param mutexes Container of pointers to mutexes. Container must have at + least 1 mutex, all mutexes must have the same level, no NULL pointers, and all + mutexes must not exceed the thread's current level. This sorts the container + by address order. + @return Enum value indicating success or error. + */ + static MutexErrors::Type MultiLock( MutexContainer & mutexes ); + + /** Locks several mutexes at once. Requires O(m + n*n + n*t) actions where m is + the number of mutexes currently locked by the thread, n is the number of mutexes + in the container, and t is the wait time for each mutex. This provides strong + exception safety. If an exception occurs, any mutexes that were locked during + this call will ge unlocked. + @param mutexes Container of pointers to mutexes. Container must have at + least 1 mutex, all mutexes must have the same level, no NULL pointers, and all + mutexes must not exceed the thread's current level. This sorts the container + by address order. + @param milliSeconds Amount of time to wait for each mutex. + @return Enum value indicating success or error. + */ + static MutexErrors::Type MultiLock( MutexContainer & mutexes, + unsigned int milliSeconds ); + + /** Unlocks several mutexes at once. Requires O(m) actions where m is the number of + mutexes in the container. This provides strong exception safety. If an exception + occurs when unlocking one mutex, other mutexes in the container get unlocked anyway. + @param mutexes Container of pointers to mutexes. Container must have at least 1 + mutex, all mutexes must have the same level, no NULL pointers, and all mutexes must + be locked by the current thread. This sorts the container dby address order. + @return Enum value indicating success or error. + */ + static MutexErrors::Type MultiUnlock( MutexContainer & mutexes ); + + /** Gives pointer to most recently locked mutex, or NULL if nothing locked. + The pointer is for a const mutex so the mutex can't be modified inappropriately. + The pointer is for a volatile mutex so callers can call volatile member + functions to get info about the mutex. + */ + static const volatile LevelMutexInfo * GetCurrentMutex( void ); + + /// Returns the level of this mutex. + inline unsigned int GetLevel( void ) const volatile { return m_level; } + + /// Returns true if this mutex was locked at least once. + inline bool IsLocked( void ) const volatile { return ( 0 < m_count ); } + + /// Returns count of how many times this mutex got locked. + inline unsigned int GetLockCount( void ) const volatile { return m_count; } + + /// Returns pointer to mutex previously locked by the thread which locked this. + inline const volatile LevelMutexInfo * GetPrevious( void ) const volatile + { + return m_previous; + } + + /** Tries to lock mutex, and returns immediately if mutex already locked by + another thread. It will return immediately with a value of AlreadyLocked + if the mutex was locked by a different thread. It may throw an exception + or assert when errors occur if the ErrorPolicy class implements that behavior. + @return An error condition if any occurred, else Success. + */ + virtual MutexErrors::Type TryLock( void ) volatile = 0; + + /** Blocking call will attempt to lock mutex and wait until it can lock. + This may throw an exception if the lock failed or an error occurred - if + that is what the error policy specifies. + @return An error condition if any occurred, else Success. + */ + virtual MutexErrors::Type Lock( void ) volatile = 0; + + /** Attempts to lock mutex, but only waits for a limited amount of time + before it gives up. Will return quickly if an error occurs before any + attempt to lock. This may throw an exception if the lock failed or an + error occurred - if that is what the error policy specifies. + @param milliSeconds How long to wait. + @return An error condition if any occurred, else Success. + */ + virtual MutexErrors::Type Lock( unsigned int milliSeconds ) volatile = 0; + + /** Unlocks the mutex, or returns an error condition. This may throw an + exception if the lock failed or an error occurred - if that is what the + error policy specifies. + @return An error condition if any occurred, else Success. + */ + virtual MutexErrors::Type Unlock( void ) volatile = 0; + + /** Returns true if this mutex was locked by current thread, and level is the same + as the current thread's level. Which means this was the most recently locked + mutex, or it was locked along with several others of the same level recently. + */ + bool IsRecentLock( void ) const volatile; + + /** Returns true if this mutex was locked within the last count mutexes. + @param count How many recent mutexes to look through to find this mutex. + */ + bool IsRecentLock( unsigned int count ) const volatile; + + /// Returns true if this was locked by current thread. + bool IsLockedByCurrentThread( void ) const volatile; + + /// Returns true if this was locked by another thread. + bool IsLockedByAnotherThread( void ) const volatile; + +protected: + + /** @class Checker Performs validity check on mutex to insure no class invariants + were violated inside any member function. This class only gets used in debug + builds, and any instance of it gets optimized away in release builds. A checker + is created inside many of member functions so that it's destructor gets called + when the function exits. It determines if any class invariants were violated + during the function call. + */ + class Checker + { + public: + inline explicit Checker( const volatile LevelMutexInfo * mutex ) : + m_mutex( mutex ) {} + inline ~Checker( void ) { m_mutex->IsValid(); } + private: + Checker( void ); + Checker( const Checker & ); + Checker & operator = ( const Checker & ); + const volatile LevelMutexInfo * m_mutex; + }; + + /** @class MutexUndoer + Undoes actions by MultiLock if an exception occurs. It keeps track of + which mutexes in a container got locked, and if an exception occurs, then + the destructor unlocks them. If MultiLock succeeds, then it cancels the + undoer so nothing gets unlocked inadvertently. + */ + class MutexUndoer + { + public: + + explicit MutexUndoer( MutexContainer & mutexes ); + ~MutexUndoer( void ); + void SetPlace( LevelMutexContainerIter & here ); + void Cancel( void ); + + private: + + MutexUndoer( void ); + MutexUndoer( const MutexUndoer & ); + MutexUndoer & operator = ( const MutexUndoer & ); + + MutexContainer & m_mutexes; + LevelMutexContainerIter m_here; + }; + + /** Returns true if linked-list of locked mutexes in this thread is valid. + Which means the list has no loops, and each previous mutex on the list has a + higher or same level as the current mutex. Called by IsValid. + */ + static bool IsValidList( void ); + + /** This is the only available constructor, and it forces any derived class to set + a level for each mutex. + */ + explicit LevelMutexInfo( unsigned int level ); + + /// The destructor only gets called by the derived class. + virtual ~LevelMutexInfo( void ); + + MutexErrors::Type PreLockCheck( bool forTryLock ) volatile; + + MutexErrors::Type PreUnlockCheck( void ) volatile; + + /** This gets called after each call to DoLock and DoTryLock to make sure the data + members in this object get set correctly. + */ + void PostLock( void ) volatile; + + /// Gets called just before an attempt to unlock a mutex. + void PreUnlock( void ) volatile; + + /// Called to relock a mutex already locked by the current thread. + void IncrementCount( void ) volatile; + + /// Called to unlock a mutex locked multiple times by the current thread. + void DecrementCount( void ) volatile; + + /** Returns true if no class invariant broken, otherwise asserts. This function + only gets called in debug builds. + */ + bool IsValid( void ) const volatile; + +private: + + /// Copy constructor is not implemented. + LevelMutexInfo( const LevelMutexInfo & ); + /// Copy-assignment operator is not implemented. + LevelMutexInfo & operator = ( const LevelMutexInfo & ); + + /** Called only by MultiLock & MultiUnlock to pass a result through an + error checking policy. + @param result What error condition to check. + @return Result or assertion or an exception - depending on error policy. + */ + virtual MutexErrors::Type DoErrorCheck( MutexErrors::Type result ) const volatile = 0; + + /// Called only by MultiLock to Lock each particular mutex within a container. + virtual MutexErrors::Type LockThis( void ) volatile = 0; + + /** Called only by MultiLock to lock each particular mutex within a container. + @param milliSeconds How much time to wait before giving up on locking a mutex. + */ + virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile = 0; + + /// Called only by MultiUnlock to unlock each particular mutex within a container. + virtual MutexErrors::Type UnlockThis( void ) volatile = 0; + + /// Pointer to singly-linked list of mutexes locked by the current thread. + static LOKI_THREAD_LOCAL volatile LevelMutexInfo * s_currentMutex; + + /// Level of this mutex. + const unsigned int m_level; + + /// How many times this mutex got locked. + unsigned int m_count; + + /// Pointer to mutex locked before this one. + volatile LevelMutexInfo * m_previous; + +}; + +// ---------------------------------------------------------------------------- + +/** @class ThrowOnAnyMutexError + Implements the ErrorPolicy for LevelMutex and throws an exception for any + error condition. Only allows MutexErrors::Success and MutexErrors::NoProblem + to get through. Useful for release builds. + */ +class ThrowOnAnyMutexError +{ +public: + static MutexErrors::Type CheckError( MutexErrors::Type error, + unsigned int level ); +}; + +// ---------------------------------------------------------------------------- + +/** @class ThrowOnBadDesignMutexError + Implements the ErrorPolicy for LevelMutex and throws an exception if the error + indicates the programmer did not levelize the calls to mutexes. Otherwise + returns the error result. Useful for release builds. + */ +class ThrowOnBadDesignMutexError +{ +public: + static MutexErrors::Type CheckError( MutexErrors::Type error, + unsigned int level ); +}; + +// ---------------------------------------------------------------------------- + +/** @class AssertAnyMutexError + Implements the ErrorPolicy for LevelMutex and asserts for any error condition. + Only allows MutexErrors::Success and MutexErrors::NoProblem to get through. + Useful for testing mutexes in debug builds. + */ +class AssertAnyMutexError +{ +public: + static inline MutexErrors::Type CheckError( MutexErrors::Type error, + unsigned int level ) + { + (void)level; + assert( ( error == MutexErrors::Success ) + || ( error == MutexErrors::NoProblem ) ); + return error; + } +}; + +// ---------------------------------------------------------------------------- + +/** @class AssertBadDesignMutexError + Implements the ErrorPolicy for LevelMutex and asserts if the error + indicates the programmer did not levelize the calls to mutexes. Otherwise + returns the error result. Useful for testing mutexes in debug builds. + */ +class AssertBadDesignMutexError +{ +public: + static inline MutexErrors::Type CheckError( MutexErrors::Type error, + unsigned int level ) + { + (void)level; + assert( ( error != MutexErrors::LevelTooHigh ) + && ( error != MutexErrors::LevelTooLow ) ); + return error; + } +}; + +// ---------------------------------------------------------------------------- + +/** @class JustReturnMutexError + Implements the ErrorPolicy for LevelMutex and does nothing no matter how bad + the error condition. Only recommended use is for automated unit-testing of + mutex policies. + */ +class JustReturnMutexError +{ +public: + static inline MutexErrors::Type CheckError( MutexErrors::Type error, + unsigned int level ) + { + (void)level; + return error; + } +}; + +// ---------------------------------------------------------------------------- + +/** @class NoMutexWait + Implements the WaitPolicy for LevelMutex. Does nothing at all so it turns + all wait loops into spin loops. Useful for low-level mutexes. + */ +class NoMutexWait +{ +public: + static inline void Wait( void ) {} +}; + +// ---------------------------------------------------------------------------- + +/** @class MutexSleepWaits + Implements the WaitPolicy for LevelMutex. Sleeps for a moment so thread won't + consume idle CPU cycles. Useful for high-level mutexes. + */ +class MutexSleepWaits +{ +public: + static void Wait( void ); + static unsigned int sleepTime; +}; + +// ---------------------------------------------------------------------------- + +/** @class SpinLevelMutex + Implements a spin-loop to wait for the mutex to unlock. Since this class makes + the thread wait in a tight spin-loop, it can cause the thread to remain busy + while waiting and thus consume CPU cycles. For that reason, this mutex is best + used only for very low-level resources - especially resources which do not + require much CPU time to exercise. Rule of thumb: Use this only if all actions + on the resource consume a very small number of CPU cycles. Otherwise, use the + SleepLevelMutex instead. + */ +class SpinLevelMutex +{ +public: + + /// Constructs a spin-level mutex. + explicit SpinLevelMutex( unsigned int level ); + + /// Destructs the mutex. + virtual ~SpinLevelMutex( void ); + + virtual MutexErrors::Type Lock( void ) volatile; + + virtual MutexErrors::Type TryLock( void ) volatile; + + virtual MutexErrors::Type Unlock( void ) volatile; + + inline unsigned int GetLevel( void ) const volatile { return m_level; } + +private: + + /// Copy constructor is not implemented. + SpinLevelMutex( const SpinLevelMutex & ); + /// Copy-assignment operator is not implemented. + SpinLevelMutex & operator = ( const SpinLevelMutex & ); + +#if defined( _MSC_VER ) + #if ( _MSC_VER >= 1300 ) + /// The actual mutex. + CRITICAL_SECTION m_mutex; + #else + #error "Only Visual Studio versions 7.0 and after supported." + #endif + +#elif ( __GNUC__ ) + /// The actual mutex. + pthread_mutex_t m_mutex; + +#else + #error "Check if any mutex libraries are compatible with your compiler." +#endif + + /// Keep a copy of the mutex level around for error reporting. + const unsigned int m_level; + +}; // end class SpinLevelMutex + +// ---------------------------------------------------------------------------- + +/** @class SleepLevelMutex + Implements a sleeping loop to wait for the mutex to unlock. + + @par Purpose + Since this class puts the thread to sleep for short intervals, you can use this + class for most of your mutexes. Especially for locking any high level resources + where any one operation on the resouce consumes many CPU cycles. The purpose of + this mutex is to reduce the number of CPU cycles spent in idle loops. All + SleepLevelMutex's should have higher levels than all your SpinLevelMutex's. + + @par Dependence on SpinLevelMutex + This utilizes SpinLevelMutex so it does not have to re-implement the DoTryLock + and DoUnlock functions the same way. All it really needs is a DoLock function + and the amount of time it should sleep if an attempt to lock a function fails. + */ +class SleepLevelMutex : public SpinLevelMutex +{ +public: + + /** Constructs a levelized mutex that puts threads to sleep while they wait + for another thread to unlock the mutex. + @param level Level of this mutex. + */ + explicit SleepLevelMutex( unsigned int level ); + + SleepLevelMutex( unsigned int level, unsigned int sleepTime ); + + /// Destructs the mutex. + virtual ~SleepLevelMutex( void ); + + inline unsigned int GetSleepTime( void ) const volatile { return m_sleepTime; } + + inline void SetSleepTime( unsigned int sleepTime ) volatile + { + if ( 0 != sleepTime ) + m_sleepTime = sleepTime; + } + +#if defined( _MSC_VER ) + inline bool GetWakable( void ) const volatile { return m_wakable; } + inline void SetWakable( bool wakable ) volatile { m_wakable = wakable; } +#endif + + /** Attempts to lock a mutex, and if it fails, then sleeps for a while + before attempting again. + */ + virtual MutexErrors::Type Lock( void ) volatile; + +private: + + /// Default constructor is not implemented. + SleepLevelMutex( void ); + /// Copy constructor is not implemented. + SleepLevelMutex( const SleepLevelMutex & ); + /// Copy-assignment operator is not implemented. + SleepLevelMutex & operator = ( const SleepLevelMutex & ); + +#if defined( _MSC_VER ) + #if ( _MSC_VER >= 1300 ) + /// True if operating system may wake thread to respond to events. + bool m_wakable; + #else + #error "Only Visual Studio versions 7.0 and after supported." + #endif +#endif + + /// How many milli-seconds to sleep before trying to lock mutex again. + unsigned int m_sleepTime; + +}; // end class SleepLevelMutex + +// ---------------------------------------------------------------------------- + +/** @class LevelMutex + Levelized mutex class prevents deadlocks by requiring programs to lock mutexes in + the same order, and unlock them in reverse order. This is accomplished by forcing + each mutex to have a level and forcing code to lock mutexes with higher levels + before locking mutexes at lower levels. If you want to lock several mutexes, they + must be locked in decreasing order by level, or if they are all of the same level, + then locked by LevelMutex::MultiLock. + + @par Features + - Immune: Very unlikely to deadlock since all mutexes are locked in the same + order and unlocked in reverse order. + - Scalable: Can handle any number of mutexes. + - Efficient: Many operations occur in constant time, and most operations require + no more than O(m) steps. + - Exception safe: All operations provide strong safety or don't throw. + - Extendable: Can work with existing mutexes through policy-based design. + - Easily Extended: Derived classes only need to implement 5 functions and a mutex + to get all the features of this class. + - Re-Entrant: Allows for re-entrancy even if mutexes in policy classes don't. + - Cost-Free: No resource allocations occur in LevelMutex - although user-defined + policy classes may allocate resources. + - Compact: Each LevelMutex object is small. + - Portable: As long as your compiler and libraries can meet the requirements. + - Robust: Maintains data integrity even if exceptions occur in policy classes. + - Affording: Several functions provide information about a mutex which allows + client code to easily choose correct actions. + + @par Requirements + - Your compiler must allow for thread-specific data. + - You must have a threading or mutex library. + + @par Policy-Based Design + This class hosts 3 policies and a default level. The policy-based design allows + users to write their own policies to extend the behaviors of LevelMutex. The + paragraphs below say how to design a class for each policy. + - MutexPolicy The mutex policy class. + - defaultLevel A level for existing client code that calls a default constructor. + - ErrorPolicy How the mutex should handle error conditions. + - WaitPolicy Whether a thread should wait, and how long in some internal loops. + + @par MutexPolicy + A policy class that wraps a low-level mutex. Loki provides two policy classes + for the actual mutex (SpinLevelMutex and SleepLevelMutex), both of which wrap + either pthreads or the Windows CRITICAL_SECTION. If you want to use a mutex + mechanism besides one of those, then all you have to do is provide a class + which wraps the mutex and implements these functions. + explicit SpinLevelMutex( unsigned int level ); + virtual ~SpinLevelMutex( void ); + virtual MutexErrors::Type Lock( void ) volatile; + virtual MutexErrors::Type TryLock( void ) volatile; + virtual MutexErrors::Type Unlock( void ) volatile; + Indeed, since the base class does most of the work, and provides all the interace + and functionality to client classes, a derived class has very few requirements. + It only needs to implement a single constructor, the destructor, some virtual + functions, and whatever data members it requires. You don't actually need to + declare those functions as virtual if the policy class is not a base or child + class. In the parlance of design patterns, LevelMutex is a Template, and the + MutexPolicy is a Strategy. + + @par DefaultLevel + The template class requires a default level to use inside the default constructor. + Some existing code calls instantiates mutexes with a default constructor, so the + mutex must know what level to use there. Please do not use zero or UnlockedLevel + as the default level. + + @par ErrorPolicy + This policy specifies how to handle error conditions. The mutexes can return + errors, assert, or throw exceptions. I recommend that debug code use asserts, + release code use exceptions, and unit-testing code just return errors. The + error policy class only needs to implement one function: + static MutexErrors::Type CheckError( MutexErrors::Type error, unsigned int level ); + + @par WaitPolicy + This states whether the mutex should wait within some tight internal loops, + how the waiting is done, and for how long. A wait policy class could sleep, + do nothing, check if other objects need attention, or check if the program + received events or notices from the operating system. It only needs to + implement one function: + static void Wait( void ); + + @par Per-Function Usage + If you implement a function with a static local mutex, then you have to insure + the function is not called from a lower level via call-backs, virtual functions in + interface classes. If the function does get called from a lower level, you are + setting up a potential deadlock. LevelMutex will detect that by checking the + current level and the local mutex's level, so it will refuse to lock the local mutex. + + @par Per-Object Usage + If you use a mutex as a data member of an object to protect that object, then I + recommend specifying which functions are volatile and which are not, and then only + use the mutex within the volatile functions. You may also want to provide accessor + functions so that client code can lock and unlock the mutex either to allow for + calling multiple operations without having to lock and unlock before and after each + operation, or so they can lock it along with several other objects at the same + level. + + @par Per-Class Usage + If you make a static data member within a class, you can use that to lock any + resources shared by those objects, or to require threads to act on only one object + at a time. You may also want to provide static accessor functions so that client + code can lock several other resources at the same level. + */ + +template +< + class MutexPolicy, + unsigned int DefaultLevel, + class ErrorPolicy = ::Loki::ThrowOnBadDesignMutexError, + class WaitPolicy = ::Loki::NoMutexWait +> +class LevelMutex : public LevelMutexInfo +{ +public: + + typedef ErrorPolicy EP; + typedef WaitPolicy WP; + typedef MutexPolicy MP; + + /** This constructor allows callers to replace the default level with another + value. It also acts as the default constructor for existing code which uses + default construction for mutexes. This is the only time the DefaultLevel + template parameter gets used. + */ + explicit LevelMutex( unsigned int level = DefaultLevel ) : + LevelMutexInfo( level ), + m_mutex( level ) + { + assert( IsValid() ); + } + + /// The destructor. + ~LevelMutex( void ) + { + assert( IsValid() ); + } + + /** These functions allow callers to access the mutex in case they need to + modify specific values in the MutexPolicy (e.g. - sleep time, functors to + call as tasks, etc...) There is one function for every combination of + const and volatile qualifiers so callers get a reference to a MutexPolicy + with the proper qualifiers. + */ + inline const volatile MutexPolicy & GetMutexPolicy( void ) const volatile { return m_mutex; } + inline volatile MutexPolicy & GetMutexPolicy( void ) volatile { return m_mutex; } + inline const MutexPolicy & GetMutexPolicy( void ) const { return m_mutex; } + inline MutexPolicy & GetMutexPolicy( void ) { return m_mutex; } + + virtual MutexErrors::Type TryLock( void ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + MutexErrors::Type result = LevelMutexInfo::PreLockCheck( true ); + if ( MutexErrors::Success == result ) + return MutexErrors::Success; + else if ( MutexErrors::AlreadyLocked == result ) + return result; + else if ( MutexErrors::NoProblem != result ) + return EP::CheckError( result, GetLevel() ); + + assert( 0 == LevelMutexInfo::GetLockCount() ); + result = m_mutex.TryLock(); + if ( MutexErrors::Success != result ) + return EP::CheckError( result, GetLevel() ); + LevelMutexInfo::PostLock(); + + return MutexErrors::Success; + } + + virtual MutexErrors::Type Lock( void ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false ); + if ( MutexErrors::Success == result ) + return MutexErrors::Success; + else if ( MutexErrors::NoProblem != result ) + return EP::CheckError( result, GetLevel() ); + + assert( !LevelMutexInfo::IsLockedByCurrentThread() ); + result = m_mutex.Lock(); + if ( MutexErrors::Success != result ) + return EP::CheckError( result, GetLevel() ); + PostLock(); + + return MutexErrors::Success; + } + + virtual MutexErrors::Type Lock( unsigned int milliSeconds ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false ); + if ( MutexErrors::Success == result ) + return MutexErrors::Success; + else if ( MutexErrors::NoProblem != result ) + return EP::CheckError( result, GetLevel() ); + + assert( !LevelMutexInfo::IsLockedByCurrentThread() ); + clock_t timeOut = clock() + milliSeconds; + while ( clock() < timeOut ) + { + WP::Wait(); + result = m_mutex.TryLock(); + switch ( result ) + { + case MutexErrors::Success: + { + PostLock(); + return MutexErrors::Success; + } + case MutexErrors::AlreadyLocked: + return MutexErrors::AlreadyLocked; + case MutexErrors::TryFailed: + break; + default: + return EP::CheckError( result, GetLevel() ); + } + } + + return MutexErrors::TimedOut; + } + + virtual MutexErrors::Type Unlock( void ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + MutexErrors::Type result = LevelMutexInfo::PreUnlockCheck(); + if ( MutexErrors::Success == result ) + return MutexErrors::Success; + else if ( MutexErrors::NoProblem != result ) + return EP::CheckError( result, GetLevel() ); + + LevelMutexInfo::PreUnlock(); + result = MutexErrors::OtherError; + try + { + result = m_mutex.Unlock(); + if ( MutexErrors::Success != result ) + PostLock(); + } + catch ( ... ) + { + PostLock(); + result = MutexErrors::ExceptionThrown; + } + + return result; + } + +private: + + /// Copy constructor is not implemented since mutexes don't get copied. + LevelMutex( const LevelMutex & ); + /// Copy-assignment operator is not implemented since mutexes don't get copied. + LevelMutex & operator = ( const LevelMutex & ); + + virtual MutexErrors::Type DoErrorCheck( MutexErrors::Type result ) const volatile + { + return EP::CheckError( result, GetLevel() ); + } + + /** Called only by MultiLock to lock each particular mutex within a container. + This does not do pre-lock error checking since MultiLock does that. Since + this skips the error checking, that means that callers of LevelMutex should + not call this function directly, and so this will not be publicly available. + @return Error status indicating success or reason for failure. + */ + virtual MutexErrors::Type LockThis( void ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + assert( this != LevelMutexInfo::GetCurrentMutex() ); + + const MutexErrors::Type result = m_mutex.Lock(); + if ( MutexErrors::Success != result ) + return result; + PostLock(); + + return MutexErrors::Success; + } + + /** Called only by MultiLock to lock each particular mutex within a container. + This does not do pre-lock error checking since MultiLock does that. Since + this skips the error checking, callers of LevelMutex should not call this + function directly, and so this will not be publicly available. + @param milliSeconds How much time to wait before giving up on locking a mutex. + @return Error status indicating success or reason for failure. + */ + virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile + { + assert( IsValid() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + clock_t timeOut = clock() + milliSeconds; + while ( clock() < timeOut ) + { + WP::Wait(); + const bool locked = ( MutexErrors::Success == m_mutex.TryLock() ); + if ( locked ) + { + PostLock(); + return MutexErrors::Success; + } + } + + return MutexErrors::TimedOut; + } + + /** Called only by MultiUnlock to unlock each mutex within a container. + This does not do pre-unlock error checking since MultiLock does that. Since + this skips the error checking, callers of LevelMutex should not call this + function directly, and so this will not be publicly available. + @return Error status indicating success or reason for failure. + */ + virtual MutexErrors::Type UnlockThis( void ) volatile + { + assert( IsValid() ); + assert( NULL != LevelMutexInfo::GetCurrentMutex() ); + LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; ) + + if ( 1 < LevelMutexInfo::GetLockCount() ) + { + LevelMutexInfo::DecrementCount(); + return MutexErrors::Success; + } + + LevelMutexInfo::PreUnlock(); + MutexErrors::Type result = m_mutex.Unlock(); + + return result; + } + + /// An instance of an unleveled mutex wrapped to match LevelMutex's needs. + MutexPolicy m_mutex; + +}; // end class LevelMutex + +// ---------------------------------------------------------------------------- + +/** Returns level of most recently locked mutex by this thread, or UnlockedLevel + if no mutexes are locked. Runs in constant time, and never throws exceptions. + */ +unsigned int GetCurrentThreadsLevel( void ); + +/** Returns count of how mutexes the current thread locked. Requires O(m) + actions where m is the number of mutexes in the thread. Never throws exceptions. + */ +unsigned int CountMutexesInCurrentThread( void ); + +/** Returns count of how mutexes the current thread locked. The lock count + exceeds the number of mutexes locked by current thread if any mutex got locked + more than once. Requires O(m) actions where m is the number of mutexes in the + thread. Never throws exceptions. + */ +unsigned int CountLocksInCurrentThread( void ); + +/** Returns count of mutexes locked by current thread which have the same level + as GetCurrentThreadsLevel. Requires O(m) actions where m is the number of + mutexes in the thread at current level. Never throws exceptions. + */ +unsigned int CountMutexesAtCurrentLevel( void ); + +/** Determines if container of mutexes matches the recently locked mutexes. + If they do match, it returns success, otherwise an error condition. + */ +MutexErrors::Type DoMutexesMatchContainer( const LevelMutexInfo::MutexContainer & mutexes ); + +// ---------------------------------------------------------------------------- + +/** @class MutexException + Exception class used to throw error statuses about LevelMutex's up to code that + can respond to mutex problems. This class exists because it conveys more info + about the error condition than just ::std::exception. + */ +class MutexException : public ::std::exception +{ +public: + + /** Constructs an exception which stores information about a mutex and the + reason an attempt to use a mutex failed. + */ + MutexException( const char * message, unsigned int level, MutexErrors::Type reason ); + + /// Copy constructor performs a member-by-member copy of an exception. + MutexException( const MutexException & that ) throw (); + + /// Copy-assignment operator performs a member-by-member copy of an exception. + MutexException & operator = ( const MutexException & that ) throw (); + + /// Destroys the exception. + virtual ~MutexException( void ) throw(); + + /// Returns a simple message about which operation failed. + virtual const char * what( void ) const throw(); + + /// Returns level of mutex(es) used when problem occurred. + unsigned int GetLevel( void ) const { return m_level; } + + /// Returns an error status for why operation failed. + MutexErrors::Type GetReason( void ) const { return m_reason; } + +private: + + /// Default constructor is not implemented. + MutexException( void ) throw (); + + /// Simple message about operation that failed. + const char * m_message; + /// Level of mutex(es) used when problem occurred. + unsigned int m_level; + /// Error status for why operation failed. + MutexErrors::Type m_reason; + +}; // end class MutexException + +// ---------------------------------------------------------------------------- + +/** @class MutexLocker + You can place an instance of this as a local variable inside a function to lock + a single mutex. It will lock the mutex if no error occurs, or throw if one + does happen. When the function ends, the destructor will determine if it needs + to unlock the mutex. This RAII technique insures the mutex gets unlocked even + when exceptions occur. + */ +class MutexLocker +{ +public: + + /** Creates an object to lock an unlock a mutex for a function. This + will throw if an attempt to lock the mutex fails. + @param mutex Reference to the mutex. + @param lock True if function wants to lock the mutex as this gets + constructed. + */ + explicit MutexLocker( volatile LevelMutexInfo & mutex, bool lock = true ); + + /** Creates an object to lock an unlock a mutex for a function. This waits + a specified amount of time for another thread to unlock the mutex if it is + locked. This will throw if an attempt to lock the mutex fails. + @param mutex Reference to the mutex. + @param milliSeconds Amount of time to wait for another thread to unlock + the mutex. + @param lock True if function wants to lock the mutex as this gets + constructed. + */ + MutexLocker( volatile LevelMutexInfo & mutex, unsigned int milliSeconds, + bool lock = true ); + + /// Destructs the locker, and determines if it needs to unlock the mutex. + ~MutexLocker( void ); + + /** You can call this to lock (or relock) a mutex. In theory, you can lock + and unlock a mutex several times within a function in order to give other + threads access to a resource while this function does not need it. + @return True if mutex is locked by this, else false if not locked. + */ + bool Lock( void ); + + /** You can call this to unlock a mutex before the destructor does it. + By unlocking the mutexes before returning, the function can do other + operations without making other threads wait too long. + @return True if unlocked by this, else false if not unlocked by this. + (Which is not the same as whether the mutex itself is locked or not by + another thread.) + */ + bool Unlock( void ); + + /// Returns true if the mutex is locked by this object. + inline bool IsLocked( void ) const { return m_locked; } + + /// Provides access to mutex controlled by this. + const volatile LevelMutexInfo & GetMutex( void ) const { return m_mutex; } + +private: + + /// Default constructor is not implemented. + MutexLocker( void ); + /// Copy constructor is not implemented. + MutexLocker( const MutexLocker & ); + /// Copy-assignment operator is not implemented. + MutexLocker & operator = ( const MutexLocker & ); + + /// True if mutex got locked. + bool m_locked; + + /// Reference to mutex. + volatile LevelMutexInfo & m_mutex; +}; + +// ---------------------------------------------------------------------------- + +/** @class MultiMutexLocker + You can place an instance of this as a local variable inside a function to lock + a collection of mutexes. It locks them if no error occurs, or throws an + exception if one does happen. When the function ends, the destructor determines + if it needs to unlock the mutexes. This RAII technique insures the mutexes get + unlocked even when exceptions occur. You will also have to construct a + MutexContainer as a local object within the same function. + */ +class MultiMutexLocker +{ +public: + + /** Creates an object to lock and unlock a collection of mutexes for a function. + This will throw if an attempt to lock any mutex fails. If an exception occurs, + it unlocks mutexes it previously locked. + @param mutex Reference to a collection of mutexes. + @param lock True if function wants to lock the mutex as this gets + constructed. + */ + explicit MultiMutexLocker( LevelMutexInfo::MutexContainer & mutexes, + bool lock = true ); + + /** Creates an object to lock and unlock a collection of mutexes for a function. + This waits a specified amount of time for other threads to unlock each mutex + that is locked. This will throw if an attempt to lock any mutex fails. If an + exception occurs, it unlocks mutexes it previously locked. + @param mutexes Reference to a collection of mutexes. + @param milliSeconds Amount of time to wait for another thread to unlock + the mutex. + @param lock True if function wants to lock the mutexes as this gets + constructed. + */ + MultiMutexLocker( LevelMutexInfo::MutexContainer & mutexes, + unsigned int milliSeconds, bool lock = true ); + + /// Destructs the locker, and determines if it needs to unlock the mutexes. + ~MultiMutexLocker( void ); + + /** You can call this to lock (or relock) the mutexes. In theory, you can lock + and unlock mutexes several times within a function in order to give other + threads access to resources while this function does not need them. + @return True if mutex is locked by this, else false if not locked. + */ + bool Lock( void ); + + /** You can call this to unlock the mutexes before the destructor does it. + By unlocking the mutexes before returning, the function can do other + operations without making other threads wait too long. + @return True if unlocked by this, else false if not unlocked by this. + (Which is not the same as whether the mutex itself is locked or not by + another thread.) + */ + bool Unlock( void ); + + /// Returns true if the mutexes are locked by this object. + inline bool IsLocked( void ) const { return m_locked; } + + /// Provides access to the collection of mutexes controlled by this. + const LevelMutexInfo::MutexContainer & GetMutexes( void ) const { return m_mutexes; } + +private: + + /// Default constructor is not implemented. + MultiMutexLocker( void ); + /// Copy constructor is not implemented. + MultiMutexLocker( const MultiMutexLocker & ); + /// Copy-assignment operator is not implemented. + MultiMutexLocker & operator = ( const MultiMutexLocker & ); + + /// True if mutexes got locked. + bool m_locked; + + /// Reference to external container of mutexes; + LevelMutexInfo::MutexContainer & m_mutexes; +}; + +// ---------------------------------------------------------------------------- + +} // end namespace Loki + +#endif // end file guardian diff --git a/shared/loki/LockingPtr.h b/shared/loki/LockingPtr.h new file mode 100644 index 00000000..a50f5d6d --- /dev/null +++ b/shared/loki/LockingPtr.h @@ -0,0 +1,110 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code is from the article: +// "Generic<Programming>: volatile — Multithreaded Programmer’s Best Friend +// Volatile-Correctness or How to Have Your Compiler Detect Race Conditions +// for You" by Alexandrescu, Andrei. +// Published in the February 2001 issue of the C/C++ Users Journal. +// http://www.cuj.com/documents/s=7998/cujcexp1902alexandr/ +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +// Prepared for Loki library by Richard Sposato +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_LOCKING_PTR_INC_ +#define LOKI_LOCKING_PTR_INC_ + +// $Id: LockingPtr.h 840 2008-03-19 19:44:38Z rich_sposato $ + + +#include <loki/ConstPolicy.h> +#include <loki/Threads.h> + + +namespace Loki +{ + /** @class LockingPtr + Locks a volatile object and casts away volatility so that the object + can be safely used in a single-threaded region of code. + Original version of LockingPtr had only one template - for the shared + object, but not the mutex type. This version allows users to specify a + the mutex type as a LockingPolicy class. The only requirements for a + LockingPolicy class are to provide Lock and Unlock methods. + */ + template < typename SharedObject, typename LockingPolicy = LOKI_DEFAULT_MUTEX, + template<class> class ConstPolicy = LOKI_DEFAULT_CONSTNESS > + class LockingPtr + { + public: + + typedef typename ConstPolicy<SharedObject>::Type ConstOrNotType; + + /** Constructor locks mutex associated with an object. + @param object Reference to object. + @param mutex Mutex used to control thread access to object. + */ + LockingPtr( volatile ConstOrNotType & object, LockingPolicy & mutex ) + : pObject_( const_cast< SharedObject * >( &object ) ), + pMutex_( &mutex ) + { + mutex.Lock(); + } + + typedef typename std::pair<volatile ConstOrNotType *, LockingPolicy *> Pair; + + /** Constructor locks mutex associated with an object. + @param lockpair a std::pair of pointers to the object and the mutex + */ + LockingPtr( Pair lockpair ) + : pObject_( const_cast< SharedObject * >( lockpair.first ) ), + pMutex_( lockpair.second ) + { + lockpair.second->Lock(); + } + + /// Destructor unlocks the mutex. + ~LockingPtr() + { + pMutex_->Unlock(); + } + + /// Star-operator dereferences pointer. + ConstOrNotType & operator * () + { + return *pObject_; + } + + /// Point-operator returns pointer to object. + ConstOrNotType * operator -> () + { + return pObject_; + } + + private: + + /// Default constructor is not implemented. + LockingPtr(); + + /// Copy-constructor is not implemented. + LockingPtr( const LockingPtr & ); + + /// Copy-assignment-operator is not implemented. + LockingPtr & operator = ( const LockingPtr & ); + + /// Pointer to the shared object. + ConstOrNotType * pObject_; + + /// Pointer to the mutex. + LockingPolicy * pMutex_; + + }; // end class LockingPtr + +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/LokiExport.h b/shared/loki/LokiExport.h new file mode 100644 index 00000000..625449f2 --- /dev/null +++ b/shared/loki/LokiExport.h @@ -0,0 +1,69 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 by Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_LOKIEXPORT_INC_ +#define LOKI_LOKIEXPORT_INC_ + +// $Id: LokiExport.h 748 2006-10-17 19:49:08Z syntheticpp $ + + +#ifdef __GNUC__ + +#ifdef _HAVE_GCC_VISIBILITY +#define LOKI_EXPORT_SPEC __attribute__ ((visibility("default"))) +#define LOKI_IMPORT_SPEC +#else +#define LOKI_EXPORT_SPEC +#define LOKI_IMPORT_SPEC +#endif + +#else + +#ifdef _WIN32 +#define LOKI_EXPORT_SPEC __declspec(dllexport) +#define LOKI_IMPORT_SPEC __declspec(dllimport) +#else +#define LOKI_EXPORT_SPEC +#define LOKI_IMPORT_SPEC +#endif + +#endif + + +#if (defined(LOKI_MAKE_DLL) && defined(LOKI_DLL)) || \ + (defined(LOKI_MAKE_DLL) && defined(LOKI_STATIC)) || \ + (defined(LOKI_DLL) && defined(LOKI_STATIC)) +#error export macro error: you could not build AND use the library +#endif + +#ifdef LOKI_MAKE_DLL +#define LOKI_EXPORT LOKI_EXPORT_SPEC +#endif + +#ifdef LOKI_DLL +#define LOKI_EXPORT LOKI_IMPORT_SPEC +#endif + +#ifdef LOKI_STATIC +#define LOKI_EXPORT +#endif + +#if !defined(LOKI_EXPORT) && !defined(EXPLICIT_EXPORT) +#define LOKI_EXPORT +#endif + +#ifndef LOKI_EXPORT +#error export macro error: LOKI_EXPORT was not defined, disable EXPLICIT_EXPORT or define a export specification +#endif + + +#endif // end file guardian + diff --git a/shared/loki/LokiTypeInfo.h b/shared/loki/LokiTypeInfo.h new file mode 100644 index 00000000..715dab1a --- /dev/null +++ b/shared/loki/LokiTypeInfo.h @@ -0,0 +1,103 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_LOKITYPEINFO_INC_ +#define LOKI_LOKITYPEINFO_INC_ + +// $Id: LokiTypeInfo.h 748 2006-10-17 19:49:08Z syntheticpp $ + + +#include <typeinfo> +#include <cassert> +#include "Typelist.h" + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class TypeInfo +// Purpose: offer a first-class, comparable wrapper over std::type_info +//////////////////////////////////////////////////////////////////////////////// + + class TypeInfo + { + public: + // Constructors + TypeInfo(); // needed for containers + TypeInfo(const std::type_info&); // non-explicit + + // Access for the wrapped std::type_info + const std::type_info& Get() const; + // Compatibility functions + bool before(const TypeInfo& rhs) const; + const char* name() const; + + private: + const std::type_info* pInfo_; + }; + +// Implementation + + inline TypeInfo::TypeInfo() + { + class Nil {}; + pInfo_ = &typeid(Nil); + assert(pInfo_); + } + + inline TypeInfo::TypeInfo(const std::type_info& ti) + : pInfo_(&ti) + { assert(pInfo_); } + + inline bool TypeInfo::before(const TypeInfo& rhs) const + { + assert(pInfo_); + // type_info::before return type is int in some VC libraries + return pInfo_->before(*rhs.pInfo_) != 0; + } + + inline const std::type_info& TypeInfo::Get() const + { + assert(pInfo_); + return *pInfo_; + } + + inline const char* TypeInfo::name() const + { + assert(pInfo_); + return pInfo_->name(); + } + +// Comparison operators + + inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs) + // type_info::operator== return type is int in some VC libraries + { return (lhs.Get() == rhs.Get()) != 0; } + + inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs) + { return lhs.before(rhs); } + + inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs == rhs); } + + inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs) + { return rhs < lhs; } + + inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs > rhs); } + + inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs < rhs); } +} + +#endif // end file guardian diff --git a/shared/loki/MultiMethods.h b/shared/loki/MultiMethods.h new file mode 100644 index 00000000..d095cfae --- /dev/null +++ b/shared/loki/MultiMethods.h @@ -0,0 +1,415 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_MULTIMETHODS_INC_ +#define LOKI_MULTIMETHODS_INC_ + +// $Id: MultiMethods.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +#include "Typelist.h" +#include "LokiTypeInfo.h" +#include "Functor.h" +#include "AssocVector.h" + +//////////////////////////////////////////////////////////////////////////////// +// IMPORTANT NOTE: +// The double dispatchers implemented below differ from the excerpts shown in +// the book - they are simpler while respecting the same interface. +//////////////////////////////////////////////////////////////////////////////// + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template InvocationTraits (helper) +// Helps implementing optional symmetry +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class SomeLhs, class SomeRhs, + class Executor, typename ResultType> + struct InvocationTraits + { + static ResultType + DoDispatch(SomeLhs& lhs, SomeRhs& rhs, + Executor& exec, Int2Type<false>) + { + return exec.Fire(lhs, rhs); + } + static ResultType + DoDispatch(SomeLhs& lhs, SomeRhs& rhs, + Executor& exec, Int2Type<true>) + { + return exec.Fire(rhs, lhs); + } + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template StaticDispatcher +// Implements an automatic static double dispatcher based on two typelists +//////////////////////////////////////////////////////////////////////////////// + + template + < + class Executor, + class BaseLhs, + class TypesLhs, + bool symmetric = true, + class BaseRhs = BaseLhs, + class TypesRhs = TypesLhs, + typename ResultType = void + > + class StaticDispatcher + { + template <class SomeLhs> + static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, + Executor exec, NullType) + { return exec.OnError(lhs, rhs); } + + template <class Head, class Tail, class SomeLhs> + static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, + Executor exec, Typelist<Head, Tail>) + { + if (Head* p2 = dynamic_cast<Head*>(&rhs)) + { + Int2Type<(symmetric && + int(TL::IndexOf<TypesRhs, Head>::value) < + int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t; + + typedef Private::InvocationTraits< + SomeLhs, Head, Executor, ResultType> CallTraits; + + return CallTraits::DoDispatch(lhs, *p2, exec, i2t); + } + return DispatchRhs(lhs, rhs, exec, Tail()); + } + + static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, + Executor exec, NullType) + { return exec.OnError(lhs, rhs); } + + template <class Head, class Tail> + static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, + Executor exec, Typelist<Head, Tail>) + { + if (Head* p1 = dynamic_cast<Head*>(&lhs)) + { + return DispatchRhs(*p1, rhs, exec, TypesRhs()); + } + return DispatchLhs(lhs, rhs, exec, Tail()); + } + + public: + static ResultType Go(BaseLhs& lhs, BaseRhs& rhs, + Executor exec) + { return DispatchLhs(lhs, rhs, exec, TypesLhs()); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template BasicDispatcher +// Implements a logarithmic double dispatcher for functors (or functions) +// Doesn't offer automated casts or symmetry +//////////////////////////////////////////////////////////////////////////////// + + template + < + class BaseLhs, + class BaseRhs = BaseLhs, + typename ResultType = void, + typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&) + > + class BasicDispatcher + { + typedef std::pair<TypeInfo,TypeInfo> KeyType; + typedef CallbackType MappedType; + typedef AssocVector<KeyType, MappedType> MapType; + MapType callbackMap_; + + void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun); + bool DoRemove(TypeInfo lhs, TypeInfo rhs); + + public: + template <class SomeLhs, class SomeRhs> + void Add(CallbackType fun) + { + DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun); + } + + template <class SomeLhs, class SomeRhs> + bool Remove() + { + return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); + } + + ResultType Go(BaseLhs& lhs, BaseRhs& rhs); + }; + + // Non-inline to reduce compile time overhead... + template <class BaseLhs, class BaseRhs, + typename ResultType, typename CallbackType> + void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType> + ::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun) + { + callbackMap_[KeyType(lhs, rhs)] = fun; + } + + template <class BaseLhs, class BaseRhs, + typename ResultType, typename CallbackType> + bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType> + ::DoRemove(TypeInfo lhs, TypeInfo rhs) + { + return callbackMap_.erase(KeyType(lhs, rhs)) == 1; + } + + template <class BaseLhs, class BaseRhs, + typename ResultType, typename CallbackType> + ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType> + ::Go(BaseLhs& lhs, BaseRhs& rhs) + { + typename MapType::key_type k(typeid(lhs),typeid(rhs)); + typename MapType::iterator i = callbackMap_.find(k); + if (i == callbackMap_.end()) + { + throw std::runtime_error("Function not found"); + } + return (i->second)(lhs, rhs); + } + +//////////////////////////////////////////////////////////////////////////////// +// class template StaticCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template <class To, class From> + struct StaticCaster + { + static To& Cast(From& obj) + { + return static_cast<To&>(obj); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DynamicCaster +// Implementation of the CastingPolicy used by FunctorDispatcher +//////////////////////////////////////////////////////////////////////////////// + + template <class To, class From> + struct DynamicCaster + { + static To& Cast(From& obj) + { + return dynamic_cast<To&>(obj); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Private::FnDispatcherHelper +// Implements trampolines and argument swapping used by FnDispatcher +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class BaseLhs, class BaseRhs, + class SomeLhs, class SomeRhs, + typename ResultType, + class CastLhs, class CastRhs, + ResultType (*Callback)(SomeLhs&, SomeRhs&)> + struct FnDispatcherHelper + { + static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) + { + return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); + } + static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs) + { + return Trampoline(lhs, rhs); + } + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template FnDispatcher +// Implements an automatic logarithmic double dispatcher for functions +// Features automated conversions +//////////////////////////////////////////////////////////////////////////////// + + template <class BaseLhs, class BaseRhs = BaseLhs, + typename ResultType = void, + template <class, class> class CastingPolicy = DynamicCaster, + template <class, class, class, class> + class DispatcherBackend = BasicDispatcher> + class FnDispatcher + { + DispatcherBackend<BaseLhs, BaseRhs, ResultType, + ResultType (*)(BaseLhs&, BaseRhs&)> backEnd_; + + public: + template <class SomeLhs, class SomeRhs> + void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&)) + { + return backEnd_.template Add<SomeLhs, SomeRhs>(pFun); + } + + template <class SomeLhs, class SomeRhs, + ResultType (*callback)(SomeLhs&, SomeRhs&)> + void Add() + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy<SomeLhs,BaseLhs>, + CastingPolicy<SomeRhs,BaseRhs>, + callback> Local; + + Add<SomeLhs, SomeRhs>(&Local::Trampoline); + } + + template <class SomeLhs, class SomeRhs, + ResultType (*callback)(SomeLhs&, SomeRhs&), + bool symmetric> + void Add(bool = true) // [gcc] dummy bool + { + typedef Private::FnDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy<SomeLhs,BaseLhs>, + CastingPolicy<SomeRhs,BaseRhs>, + callback> Local; + + Add<SomeLhs, SomeRhs>(&Local::Trampoline); + if (symmetric) + { + Add<SomeRhs, SomeLhs>(&Local::TrampolineR); + } + } + + template <class SomeLhs, class SomeRhs> + void Remove() + { + backEnd_.template Remove<SomeLhs, SomeRhs>(); + } + + ResultType Go(BaseLhs& lhs, BaseRhs& rhs) + { + return backEnd_.Go(lhs, rhs); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorDispatcherAdaptor +// permits use of FunctorDispatcher under gcc.2.95.2/3 +/////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class BaseLhs, class BaseRhs, + class SomeLhs, class SomeRhs, + typename ResultType, + class CastLhs, class CastRhs, + class Fun, bool SwapArgs> + class FunctorDispatcherHelper + { + Fun fun_; + ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>) + { + return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); + } + ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>) + { + return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); + } + public: + FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {} + + ResultType operator()(BaseLhs& lhs, BaseRhs& rhs) + { + return Fire(lhs,rhs,Int2Type<SwapArgs>()); + } + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template FunctorDispatcher +// Implements a logarithmic double dispatcher for functors +// Features automated casting +//////////////////////////////////////////////////////////////////////////////// + + template <class BaseLhs, class BaseRhs = BaseLhs, + typename ResultType = void, + template <class, class> class CastingPolicy = DynamicCaster, + template <class, class, class, class> + class DispatcherBackend = BasicDispatcher> + class FunctorDispatcher + { + typedef LOKI_TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; + typedef Functor<ResultType, ArgsList, LOKI_DEFAULT_THREADING> FunctorType; + + DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_; + + public: + template <class SomeLhs, class SomeRhs, class Fun> + void Add(const Fun& fun) + { + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy<SomeLhs, BaseLhs>, + CastingPolicy<SomeRhs, BaseRhs>, + Fun, false> Adapter; + + backEnd_.template Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun))); + } + template <class SomeLhs, class SomeRhs, bool symmetric, class Fun> + void Add(const Fun& fun) + { + Add<SomeLhs,SomeRhs>(fun); + + if (symmetric) + { + // Note: symmetry only makes sense where BaseLhs==BaseRhs + typedef Private::FunctorDispatcherHelper< + BaseLhs, BaseLhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy<SomeLhs, BaseLhs>, + CastingPolicy<SomeRhs, BaseLhs>, + Fun, true> AdapterR; + + backEnd_.template Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun))); + } + } + + template <class SomeLhs, class SomeRhs> + void Remove() + { + backEnd_.template Remove<SomeLhs, SomeRhs>(); + } + + ResultType Go(BaseLhs& lhs, BaseRhs& rhs) + { + return backEnd_.Go(lhs, rhs); + } + }; +} // namespace Loki + + + +#endif // end file guardian + diff --git a/shared/loki/NullType.h b/shared/loki/NullType.h new file mode 100644 index 00000000..9403901a --- /dev/null +++ b/shared/loki/NullType.h @@ -0,0 +1,34 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_NULLTYPE_INC_ +#define LOKI_NULLTYPE_INC_ + +// $Id: NullType.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class NullType +// Used as a placeholder for "no type here" +// Useful as an end marker in typelists +//////////////////////////////////////////////////////////////////////////////// + + class NullType {}; + +} // namespace Loki + + +#endif // end file guardian diff --git a/shared/loki/OrderedStatic.h b/shared/loki/OrderedStatic.h new file mode 100644 index 00000000..6eaa20b9 --- /dev/null +++ b/shared/loki/OrderedStatic.h @@ -0,0 +1,225 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2005 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_ORDEREDSTATIC_INC_ +#define LOKI_ORDEREDSTATIC_INC_ + +// $Id: OrderedStatic.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +#include <vector> +#include <iostream> + +#include "LokiExport.h" +#include "Singleton.h" +#include "Typelist.h" +#include "Sequence.h" + +// usage: see test/OrderedStatic + +namespace Loki +{ + namespace Private + { + //////////////////////////////////////////////////////////////////////////////// + // polymorph base class for OrderedStatic template, + // necessary because of the creator + //////////////////////////////////////////////////////////////////////////////// + class LOKI_EXPORT OrderedStaticCreatorFunc + { + public: + virtual void createObject() = 0; + + protected: + OrderedStaticCreatorFunc(); + virtual ~OrderedStaticCreatorFunc(); + + private: + OrderedStaticCreatorFunc(const OrderedStaticCreatorFunc&); + }; + + //////////////////////////////////////////////////////////////////////////////// + // template base clase for OrderedStatic template, + // common for all specializations + //////////////////////////////////////////////////////////////////////////////// + template<class T> + class OrderedStaticBase : public OrderedStaticCreatorFunc + { + public: + T& operator*() + { + return *val_; + } + + T* operator->() + { + return val_; + } + + protected: + + OrderedStaticBase(unsigned int longevity) : val_(0), longevity_(longevity) + { + } + + virtual ~OrderedStaticBase() + { + } + + void SetLongevity(T* ptr) + { + val_=ptr; + Loki::SetLongevity(val_,longevity_); + } + + private: + OrderedStaticBase(); + OrderedStaticBase(const OrderedStaticBase&); + OrderedStaticBase& operator=(const OrderedStaticBase&); + T* val_; + unsigned int longevity_; + + }; + + //////////////////////////////////////////////////////////////////////////////// + // OrderedStaticManagerClass implements details + // OrderedStaticManager is then defined as a Singleton + //////////////////////////////////////////////////////////////////////////////// + class LOKI_EXPORT OrderedStaticManagerClass + { + public: + OrderedStaticManagerClass(); + virtual ~OrderedStaticManagerClass(); + + typedef void (OrderedStaticCreatorFunc::*Creator)(); + + void createObjects(); + void registerObject(unsigned int longevity,OrderedStaticCreatorFunc*,Creator); + + private: + OrderedStaticManagerClass(const OrderedStaticManagerClass&); + OrderedStaticManagerClass& operator=(const OrderedStaticManagerClass&); + + struct Data + { + Data(unsigned int,OrderedStaticCreatorFunc*, Creator); + unsigned int longevity; + OrderedStaticCreatorFunc* object; + Creator creator; + }; + + std::vector<Data> staticObjects_; + unsigned int max_longevity_; + unsigned int min_longevity_; + }; + + }// namespace Private + + //////////////////////////////////////////////////////////////////////////////// + // OrderedStaticManager is only a Singleton typedef + //////////////////////////////////////////////////////////////////////////////// + + typedef Loki::SingletonHolder + < + Loki::Private::OrderedStaticManagerClass, + Loki::CreateUsingNew, + Loki::NoDestroy, + Loki::SingleThreaded + > + OrderedStaticManager; + + //////////////////////////////////////////////////////////////////////////////// + // template OrderedStatic template: + // L : longevity + // T : object type + // TList : creator parameters + //////////////////////////////////////////////////////////////////////////////// + + template<unsigned int L, class T, class TList = Loki::NullType> + class OrderedStatic; + + + //////////////////////////////////////////////////////////////////////////////// + // OrderedStatic specializations + //////////////////////////////////////////////////////////////////////////////// + + template<unsigned int L, class T> + class OrderedStatic<L, T, Loki::NullType> : public Private::OrderedStaticBase<T> + { + public: + OrderedStatic() : Private::OrderedStaticBase<T>(L) + { + OrderedStaticManager::Instance().registerObject + (L,this,&Private::OrderedStaticCreatorFunc::createObject); + } + + void createObject() + { + Private::OrderedStaticBase<T>::SetLongevity(new T); + } + + private: + OrderedStatic(const OrderedStatic&); + OrderedStatic& operator=(const OrderedStatic&); + }; + + template<unsigned int L, class T, typename P1> + class OrderedStatic<L, T, Loki::Seq<P1> > : public Private::OrderedStaticBase<T> + { + public: + OrderedStatic(P1 p) : Private::OrderedStaticBase<T>(L), para_(p) + { + OrderedStaticManager::Instance().registerObject + (L,this,&Private::OrderedStaticCreatorFunc::createObject); + } + + void createObject() + { + Private::OrderedStaticBase<T>::SetLongevity(new T(para_)); + } + + private: + OrderedStatic(); + OrderedStatic(const OrderedStatic&); + OrderedStatic& operator=(const OrderedStatic&); + P1 para_; + }; + + template<unsigned int L, class T, typename P1> + class OrderedStatic<L, T, P1(*)() > : public Private::OrderedStaticBase<T> + { + public: + + typedef P1(*Func)(); + + OrderedStatic(Func p) : Private::OrderedStaticBase<T>(L), para_(p) + { + OrderedStaticManager::Instance().registerObject + (L,this,&Private::OrderedStaticCreatorFunc::createObject); + } + + void createObject() + { + Private::OrderedStaticBase<T>::SetLongevity(new T(para_())); + } + + private: + OrderedStatic(); + OrderedStatic(const OrderedStatic&); + OrderedStatic& operator=(const OrderedStatic&); + Func para_; + }; + +}// namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/Pimpl.h b/shared/loki/Pimpl.h new file mode 100644 index 00000000..ed0d1c7b --- /dev/null +++ b/shared/loki/Pimpl.h @@ -0,0 +1,198 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_PIMPL_INC_ +#define LOKI_PIMPL_INC_ + +// $Id: Pimpl.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +/// \defgroup PimplGroup Pimpl + +#ifndef LOKI_INHERITED_PIMPL_NAME +#define LOKI_INHERITED_PIMPL_NAME d +#endif + +#ifndef LOKI_INHERITED_RIMPL_NAME +#define LOKI_INHERITED_RIMPL_NAME d +#endif + +namespace Loki +{ + + ////////////////////////////////////////// + /// \class ConstPropPtr + /// + /// \ingroup PimplGroup + /// Simple const propagating smart pointer + /// Is the default smart pointer of Pimpl. + ////////////////////////////////////////// + + template<class T> + struct ConstPropPtr + { + explicit ConstPropPtr(T* p) : ptr_(p) {} + ~ConstPropPtr() { delete ptr_; ptr_ = 0; } + T* operator->() { return ptr_; } + T& operator*() { return *ptr_; } + const T* operator->() const { return ptr_; } + const T& operator*() const { return *ptr_; } + + private: + ConstPropPtr(); + ConstPropPtr(const ConstPropPtr&); + ConstPropPtr& operator=(const ConstPropPtr&); + T* ptr_; + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// \class Pimpl + /// + /// \ingroup PimplGroup + /// + /// Implements the Pimpl idiom. It's a wrapper for a smart pointer which + /// automatically creates and deletes the implementation object and adds + /// const propagation to the smart pointer. + /// + /// \par Usage + /// see test/Pimpl + //////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + typename Pointer = ConstPropPtr<T> + > + class Pimpl + { + public: + + typedef T Impl; + + Pimpl() : ptr_(new T) + {} + + ~Pimpl() + { + // Don't compile with incomplete type + // + // If compilation breaks here make sure + // the compiler does not auto-generate the + // destructor of the class hosting the pimpl: + // - implement the destructor of the class + // - don't inline the destructor + typedef char T_must_be_defined[sizeof(T) ? 1 : -1 ]; + } + + + T* operator->() + { + return ptr_.operator->(); + } + + T& operator*() + { + return ptr_.operator*(); + } + + const T* operator->() const + { + return ptr_.operator->(); + } + + const T& operator*() const + { + return ptr_.operator*(); + } + + Pointer& wrapped() + { + return ptr_; + } + + const Pointer& wrapped() const + { + return ptr_; + } + + + private: + Pimpl(const Pimpl&); + Pimpl& operator=(const Pimpl&); + + Pointer ptr_; + }; + + + template<class T, typename Pointer = ConstPropPtr<T> > + struct PimplOwner + { + Pimpl<T,Pointer> LOKI_INHERITED_PIMPL_NAME; + }; + + + ////////////////////////////////////////// + /// \class ImplOf + /// + /// \ingroup PimplGroup + /// Convenience template for the + /// implementations which Pimpl points to. + ////////////////////////////////////////// + + template<class T> + struct ImplOf; + + + ////////////////////////////////////////// + /// \class PImplOf + /// + /// \ingroup PimplGroup + /// Convenience template which uses ImplOf + /// as implementation structure + ////////////////////////////////////////// + + + template<class T, template<class> class Ptr = ConstPropPtr> + struct PimplOf + { + typedef T Impl; + + // declare pimpl + typedef Pimpl<ImplOf<T>, Ptr<ImplOf<T> > > Type; + + // inherit pimpl + typedef PimplOwner<ImplOf<T>, Ptr<ImplOf<T> > > Owner; + }; + + + template<class T, class UsedPimpl = typename PimplOf<T>::Type > + struct RimplOf + { + typedef typename UsedPimpl::Impl & Type; + + class Owner + { + UsedPimpl pimpl; + + public: + Owner() : LOKI_INHERITED_RIMPL_NAME(*pimpl) + {} + + Type LOKI_INHERITED_RIMPL_NAME; + }; + + }; + +} + +#endif // end file guardian + diff --git a/shared/loki/RefToValue.h b/shared/loki/RefToValue.h new file mode 100644 index 00000000..248de792 --- /dev/null +++ b/shared/loki/RefToValue.h @@ -0,0 +1,70 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Richard Sposato +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The authors make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_REFTOVALUE_INC_ +#define LOKI_REFTOVALUE_INC_ + +// $Id: RefToValue.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +namespace Loki +{ + + //////////////////////////////////////////////////////////////////////////////// + /// \class RefToValue + /// + /// \ingroup SmartPointerGroup + /// Transports a reference as a value + /// Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard + //////////////////////////////////////////////////////////////////////////////// + + template <class T> + class RefToValue + { + public: + + RefToValue(T& ref) : ref_(ref) + {} + + RefToValue(const RefToValue& rhs) : ref_(rhs.ref_) + {} + + operator T& () const + { + return ref_; + } + + private: + // Disable - not implemented + RefToValue(); + RefToValue& operator=(const RefToValue&); + + T& ref_; + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// \ingroup ExceptionGroup + /// RefToValue creator. + //////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline RefToValue<T> ByRef(T& t) + { + return RefToValue<T>(t); + } + +} + + +#endif // end file guardian + diff --git a/shared/loki/Register.h b/shared/loki/Register.h new file mode 100644 index 00000000..0ad014ab --- /dev/null +++ b/shared/loki/Register.h @@ -0,0 +1,134 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_REGISTER_INC_ +#define LOKI_REGISTER_INC_ + +// $Id: Register.h 776 2006-11-09 13:12:57Z syntheticpp $ + + +#include "TypeManip.h" +#include "HierarchyGenerators.h" + +/// \defgroup RegisterGroup Register + +namespace Loki +{ + + //////////////////////////////////////////////////////////////////////////////// + // + // Helper classes/functions for RegisterByCreateSet + // + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + /// \ingroup RegisterGroup + /// Must be specialized be the user + //////////////////////////////////////////////////////////////////////////////// + template<class t> bool RegisterFunction(); + + //////////////////////////////////////////////////////////////////////////////// + /// \ingroup RegisterGroup + /// Must be specialized be the user + //////////////////////////////////////////////////////////////////////////////// + template<class t> bool UnRegisterFunction(); + + namespace Private + { + template<class T> + struct RegisterOnCreate + { + RegisterOnCreate() { RegisterFunction<T>(); } + }; + + template<class T> + struct UnRegisterOnDelete + { + ~UnRegisterOnDelete() { UnRegisterFunction<T>(); } + }; + + template<class T> + struct RegisterOnCreateElement + { + RegisterOnCreate<T> registerObj; + }; + + template<class T> + struct UnRegisterOnDeleteElement + { + UnRegisterOnDelete<T> unregisterObj; + }; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \class RegisterOnCreateSet + /// + /// \ingroup RegisterGroup + /// Implements a generic register class which registers classes of a typelist + /// + /// \par Usage + /// see test/Register + //////////////////////////////////////////////////////////////////////////////// + + template<typename ElementList> + struct RegisterOnCreateSet + : GenScatterHierarchy<ElementList, Private::RegisterOnCreateElement> + {}; + + //////////////////////////////////////////////////////////////////////////////// + /// \class UnRegisterOnDeleteSet + /// + /// \ingroup RegisterGroup + /// Implements a generic register class which unregisters classes of a typelist + /// + /// \par Usage + /// see test/Register + //////////////////////////////////////////////////////////////////////////////// + template<typename ElementList> + struct UnRegisterOnDeleteSet + : GenScatterHierarchy<ElementList, Private::UnRegisterOnDeleteElement> + {}; + + + //////////////////////////////////////////////////////////////////////////////// + /// \def LOKI_CHECK_CLASS_IN_LIST( CLASS , LIST ) + /// + /// \ingroup RegisterGroup + /// Check if CLASS is in the typelist LIST. + /// + /// \par Usage + /// see test/Register + //////////////////////////////////////////////////////////////////////////////// + + +#define LOKI_CONCATE(a,b,c,d) a ## b ## c ## d +#define LOKI_CONCAT(a,b,c,d) LOKI_CONCATE(a,b,c,d) + +#define LOKI_CHECK_CLASS_IN_LIST( CLASS , LIST ) \ + \ + struct LOKI_CONCAT(check_,CLASS,_isInList_,LIST) \ + { \ + typedef int LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList_,LIST); \ + }; \ + typedef Loki::Select<Loki::TL::IndexOf<LIST, CLASS>::value == -1, \ + CLASS, \ + LOKI_CONCAT(check_,CLASS,_isInList_,LIST)> \ + ::Result LOKI_CONCAT(CLASS,isInList,LIST,result); \ + typedef LOKI_CONCAT(CLASS,isInList,LIST,result):: \ + LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList_,LIST) \ + LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList__,LIST); + + +} // namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/SPCachedFactory.h b/shared/loki/SPCachedFactory.h new file mode 100644 index 00000000..71c72644 --- /dev/null +++ b/shared/loki/SPCachedFactory.h @@ -0,0 +1,204 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 by Guillaume Chatelet +// +// Code covered by the MIT License +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The authors make no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied warranty. +// +// This code DOES NOT accompany the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// +//////////////////////////////////////////////////////////////////////////////// + +// $Id: SPCachedFactory.h 896 2008-08-08 22:20:05Z syntheticpp $ + +#ifndef SPCACHEDFACTORY_H_ +#define SPCACHEDFACTORY_H_ + +/** + * This file is intented to be used if you want a CachedFactory with + * a SmartPointer encapsulation policy. + * It as been defined in a separate file because of the many introduced + * dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h + * would depend on SmartPtr.h). By defining another header you pay for those + * extra dependencies only if you need it. + * + * This file defines FunctionStorage a new SmartPointer storage policy and + * SmartPointer a new CachedFactory encapsulation policy. + */ + +#include <loki/Functor.h> +#include <loki/SmartPtr.h> +#include <loki/CachedFactory.h> + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +/// \class FunctionStorage +/// +/// \ingroup SmartPointerStorageGroup +/// \brief Implementation of the StoragePolicy used by SmartPtr. +/// +/// This storage policy is used by SmartPointer CachedFactory's encapsulation +/// policy. It's purpose is to call a Functor instead of deleting the +/// underlying pointee object. You have to set the callback functor by calling +/// SetCallBackFunction(const FunctorType &functor). +/// +/// Unfortunately, the functor argument is not a reference to the SmartPtr but +/// a void *. Making functor argument a reference to the pointer would require +/// the FunctionStorage template to know the full definition of the SmartPtr. +//////////////////////////////////////////////////////////////////////////////// + + template <class T> + class FunctionStorage + { + public: + /// the type of the pointee_ object + typedef T* StoredType; + /// type used to declare OwnershipPolicy type. + typedef T* InitPointerType; + /// type returned by operator-> + typedef T* PointerType; + /// type returned by operator* + typedef T& ReferenceType; + /// type of the Functor to set + typedef Functor< void , Seq< void* > > FunctorType; + + FunctionStorage() : pointee_(Default()), functor_() + {} + + // The storage policy doesn't initialize the stored pointer + // which will be initialized by the OwnershipPolicy's Clone fn + FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_) + {} + + template <class U> + FunctionStorage(const FunctionStorage<U>& rsh) : pointee_(0), functor_(rsh.functor_) + {} + + FunctionStorage(const StoredType& p) : pointee_(p), functor_() {} + + PointerType operator->() const { return pointee_; } + + ReferenceType operator*() const { return *pointee_; } + + void Swap(FunctionStorage& rhs) + { + std::swap(pointee_, rhs.pointee_); + std::swap(functor_, rhs.functor_); + } + + /// Sets the callback function to call. You have to specify it or + /// the smartPtr will throw a bad_function_call exception. + void SetCallBackFunction(const FunctorType &functor) + { + functor_ = functor; + } + + // Accessors + template <class F> + friend typename FunctionStorage<F>::PointerType GetImpl(const FunctionStorage<F>& sp); + + template <class F> + friend const typename FunctionStorage<F>::StoredType& GetImplRef(const FunctionStorage<F>& sp); + + template <class F> + friend typename FunctionStorage<F>::StoredType& GetImplRef(FunctionStorage<F>& sp); + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + void Destroy() + { + functor_(this); + } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + // Data + StoredType pointee_; + FunctorType functor_; + }; + + template <class T> + inline typename FunctionStorage<T>::PointerType GetImpl(const FunctionStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline const typename FunctionStorage<T>::StoredType& GetImplRef(const FunctionStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline typename FunctionStorage<T>::StoredType& GetImplRef(FunctionStorage<T>& sp) + { return sp.pointee_; } + + /** + * \class SmartPointer + * \ingroup EncapsulationPolicyCachedFactoryGroup + * \brief Encapsulate the object in a SmartPtr with FunctionStorage policy. + * + * The object will come back to the Cache as soon as no more SmartPtr are + * referencing this object. You can customize the SmartPointer with the standard + * SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy, + * ConstnessPolicy) but StoragePolicy is forced to FunctionStorage. + */ + template + < + class AbstractProduct, + template <class> class OwnershipPolicy = RefCounted, + class ConversionPolicy = DisallowConversion, + template <class> class CheckingPolicy = AssertCheck, + template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS + > + class SmartPointer + { + private: + typedef SmartPtr< AbstractProduct,OwnershipPolicy, + ConversionPolicy, CheckingPolicy, + FunctionStorage, ConstnessPolicy > CallBackSP; + protected: + typedef CallBackSP ProductReturn; + SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {} + virtual ~SmartPointer(){} + + ProductReturn encapsulate(AbstractProduct* pProduct) + { + CallBackSP SP(pProduct); + SP.SetCallBackFunction(fun); + return SP; + } + + AbstractProduct* release(ProductReturn &pProduct) + { + return GetImpl(pProduct); + } + + const char* name(){return "smart pointer";} + + private: + SmartPointer& operator=(const SmartPointer&); + SmartPointer(const SmartPointer&); + void smartPointerCallbackFunction(void* pSP) + { + CallBackSP &SP(*reinterpret_cast<CallBackSP*>(pSP)); + ReleaseObject(SP); + } + virtual void ReleaseObject(ProductReturn &object)=0; + const typename CallBackSP::FunctorType fun; + }; + +} // namespace Loki + +#endif /*SPCACHEDFACTORY_H_*/ diff --git a/shared/loki/SafeBits.h b/shared/loki/SafeBits.h new file mode 100644 index 00000000..f45065ed --- /dev/null +++ b/shared/loki/SafeBits.h @@ -0,0 +1,514 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2009 by Fedor Pikus & Rich Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// +// The author makes no claims about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// $Id$ + + +#ifndef LOKI_INCLUDED_SAFE_BIT_FIELDS_H +#define LOKI_INCLUDED_SAFE_BIT_FIELDS_H + +#include <cstdlib> +#include <assert.h> +#include <loki/static_check.h> + + +namespace Loki +{ + +/* + ========================================================================================================================================== + SafeBitField - type-safe class for bit fields. + SafeBitConst - type-safe class for bit constants. + SafeBitField is designed to be a [almost] drop-in replacement for integer flags and bit fields where individual bits are set and checked + using symbolic names for flags: + + typedef unsigned long Labels_t; + Labels_t labels; + const Labels_t Label_A = 0x00000001; + const Labels_t Label_B = 0x00000002; + ... + labels |= Label_B; + if ( labels & Label_A ) { ... } + + Such code offers no protection against mismatching bit constants and bit fields: + + typedef unsigned long Kinds_t; + Kinds_t kinds; + const Kinds_t Kind_A = 0x00000004; + ... + if ( kinds & Label_A ) { ... } // Error but compiles + + SafeBitField is a drop-in replacement which generates a unique type for each bit field. Bit fields of different types cannot be applied + to each other: + + LOKI_BIT_FIELD( unsigned long ) Labels_t; + Labels_t labels; + LOKI_BIT_CONST( Labels_t, Label_A, 1 ); // 0x0001 - 1st bit is set + LOKI_BIT_CONST( Labels_t, Label_B, 2 ); // 0x0002 - 1st bit is set + ... + LOKI_BIT_FIELD( unsigned long ) Kinds_t; + Kinds_t kinds; + LOKI_BIT_CONST( Kinds_t, Kind_A, 3 ); // 0x0004 - 1st bit is set + ... + if ( kinds & Label_A ) { ... } // Does not compile + + Several other kinds of bit field misuse are caught by safe bit fields: + + if ( kinds & Kind_A == 0 ) { ... } + if ( kinds && Kind_A ) { ... } + + There are few cases where drop-in replacement does not work: + + 1. Operations involving bit fields and unnamed integers. Usually the integer in question is 0: + + Labels_t labels = 0; // No longer compiles + if ( ( labels & Label_A ) == 0 ) { ... } // Also does not compile + + The solution is to use named bit constants, including the one for 0: + + LOKI_BIT_CONST( Labels_t, Label_None, 0 ); // 0x0000 - No bit is set + Labels_t labels = Label_None; // Or just Labels_t labels; - constructor initializes to 0 + if ( ( labels & Label_A ) == Label_None ) { ... } // // Or just if ( labels & Label_A ) { ... } + + 2. I/O and other operations which require integer variables and cannot be modified: + + void write_to_db( unsigned int word ); + Labels_t labels; + write_to_db( labels ); // No longer compiles + + This problem is solved by reinterpreting the bit fields as an integer, the user is responsible for using the right + type of integer: + + write_to_db( *((Labels_t::bit_word_t*)(&labels)) ); + + ========================================================================================================================================== +*/ + +/// @par Non-Templated Initialization. +/// Not all compilers support template member functions where the template +/// arguments are not deduced but explicitly specified. For these broken +/// compilers, a non-template make_bit_const() function is provided instead of +/// the template one. The only downside is that instead of compile-time checking +/// of the index argument, it does runtime checking. +#if defined(__SUNPRO_CC) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + #define LOKI_BIT_FIELD_NONTEMPLATE_INIT +#endif + +/// @par Forbidding Conversions. +/// This incomplete type prevents compilers from instantiating templates for +/// type conversions which should not happen. This incomplete type must be a +/// template: if the type is incomplete at the point of template definition, +/// the template is illegal (although the standard allows compilers to accept +/// or reject such code, §14.6/, so some compilers will not issue diagnostics +/// unless template is instantiated). The standard-compliant way is to defer +/// binding to the point of instantiation by making the incomplete type itself +/// a template. +template < typename > struct Forbidden_conversion; // This struct must not be defined! + +/// Forward declaration of the field type. +template < + unsigned int unique_index, + typename word_t = unsigned long +> class SafeBitField; + +//////////////////////////////////////////////////////////////////////////////// +/// \class SafeBitConst Bit constants. +/// This class defines a bit-field constant - a collection of unchanging bits +/// used to compare to bit-fields. Instances of this class are intended to act +/// as labels for bit-fields. +/// +/// \par Safety +/// - This class provides operations used for comparisons and conversions, but +/// no operations which may modify the value. +/// - As a templated class, it provides type-safety so bit values and constants +/// used for different reasons may not be unknowingly compared to each other. +/// - The unique_index template parameter insures the unique type of each bit +/// bit-field. It shares the unique_index with a similar SafeBitField. +/// - Its operations only allow comparisons to other bit-constants and +/// bit-fields of the same type. +//////////////////////////////////////////////////////////////////////////////// + +template +< + unsigned int unique_index, + typename word_t = unsigned long +> +class SafeBitConst +{ +public: + + /// Type of the bit field is available if needed. + typedef word_t bit_word_t; + /// Corresponding field type. + typedef SafeBitField< unique_index, word_t > field_t; + /// Typedef is not allowed in friendship declaration. + friend class SafeBitField< unique_index, word_t >; + + // Static factory constructor, creates a bit constant with one bit set. The position of the bit is given by the template parameter, + // bit 1 is the junior bit, i.e. make_bit_const<1>() returns 1. Bit index 0 is a special case and returns 0. + // This function should be used only to initialize the static bit constant objects. + // This function will not compile if the bit index is outside the vaild range. + // There is also a compile-time assert to make sure the size of the class is the same as the size of the underlaying integer type. + // This assert could go into the constructor, but aCC does not seem to understand sizeof(SafeBitConst) in the constructor. + // +#ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT + template < unsigned int i > static SafeBitConst make_bit_const() + { + LOKI_STATIC_CHECK( i <= ( 8 * sizeof(word_t) ), Index_is_beyond_size_of_data ); + LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size ); + // Why check for ( i > 0 ) again inside the shift if the shift + // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 ) + // and complain that for i == 0 the number is invalid, without + // checking that shift needs evaluating. + return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 ); + } +#else + static SafeBitConst make_bit_const( unsigned int i ) + { + LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size ); + assert( i <= ( 8 * sizeof(word_t) ) ); // Index is beyond size of data. + // Why check for ( i > 0 ) again inside the shift if the shift + // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 ) + // and complain that for i == 0 the number is invalid, without + // checking that shift needs evaluating. + return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 ); + } +#endif + + /// Default constructor allows client code to construct bit fields on the stack. + SafeBitConst() : word( 0 ) {} + + /// Copy constructor. + SafeBitConst( const SafeBitConst& rhs ) : word( rhs.word ) {} + + /// Comparison operators which take a constant bit value. + bool operator == ( const SafeBitConst & rhs ) const { return word == rhs.word; } + bool operator != ( const SafeBitConst & rhs ) const { return word != rhs.word; } + bool operator < ( const SafeBitConst & rhs ) const { return word < rhs.word; } + bool operator > ( const SafeBitConst & rhs ) const { return word > rhs.word; } + bool operator <= ( const SafeBitConst & rhs ) const { return word <= rhs.word; } + bool operator >= ( const SafeBitConst & rhs ) const { return word >= rhs.word; } + + /// Comparision operators for mutable bit fields. + bool operator == ( const field_t & rhs ) const { return word == rhs.word; } + bool operator != ( const field_t & rhs ) const { return word != rhs.word; } + bool operator < ( const field_t & rhs ) const { return word < rhs.word; } + bool operator > ( const field_t & rhs ) const { return word > rhs.word; } + bool operator <= ( const field_t & rhs ) const { return word <= rhs.word; } + bool operator >= ( const field_t & rhs ) const { return word >= rhs.word; } + + /// Bitwise operations. Operation-assignment operators are not needed, + /// since bit constants cannot be changed after they are initialized. + const SafeBitConst operator | ( const SafeBitConst & rhs ) const { return SafeBitConst( word | rhs.word ); } + const SafeBitConst operator & ( const SafeBitConst & rhs ) const { return SafeBitConst( word & rhs.word ); } + const SafeBitConst operator ^ ( const SafeBitConst & rhs ) const { return SafeBitConst( word ^ rhs.word ); } + const SafeBitConst operator ~ ( void ) const { return SafeBitConst( ~word ); } + + /// These bitwise operators return a bit-field instead of a bit-const. + field_t operator | ( const field_t & rhs ) const { return field_t( word | rhs.word ); } + field_t operator & ( const field_t & rhs ) const { return field_t( word & rhs.word ); } + field_t operator ^ ( const field_t & rhs ) const { return field_t( word ^ rhs.word ); } + + /// The shift operators move bits inside the bit field. These are useful in + /// loops which act over bit fields and increment them. + const SafeBitConst operator << ( unsigned int s ) const { return SafeBitConst( word << s ); } + const SafeBitConst operator >> ( unsigned int s ) const { return SafeBitConst( word >> s ); } + + /// Word size is also the maximum number of different bit fields for a given word type. + static size_t size() { return ( 8 * sizeof( word_t ) ); } + +private: + + /// Copy-assignment operator is not implemented since it does not make sense + /// for a constant object. + SafeBitConst operator = ( const SafeBitConst & rhs ); + + // Private constructor from an integer type. + explicit SafeBitConst( word_t init ) : word( init ) {} + + /// This data stores a single bit value. It is declared const to enforce + // constness for all functions of this class. + const word_t word; + + // Here comes the interesting stuff: all the operators designed to + // trap unintended conversions and make them not compile. + // Operators below handle code like this: + // SafeBitField<1> label1; + // SafeBitField<2> label2; + // if ( label1 & label2 ) { ... } + + // These operators are private, and will not instantiate in any + // event because of the incomplete Forbidden_conversion struct. + template < typename T > SafeBitConst operator|( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitConst operator&( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitConst operator^( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitConst operator|=( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitConst operator&=( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitConst operator^=( T ) const { Forbidden_conversion< T > wrong; return *this; } + + // And the same thing for comparisons: private and unusable. + // if ( label1 == label2 ) { ... } + template < typename T > bool operator==( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator!=( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator<( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator>( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator<=( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator>=( const T ) const { Forbidden_conversion< T > wrong; return true; } +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// \class SafeBitConst Bit constants. +/// This class defines a bit-field constant - a collection of unchanging bits +/// used to compare to bit-fields. Instances of this class are intended to +/// store bit values. +/// +/// \par Safety +/// - This class provides operations used for comparisons and conversions, and +/// also operations which may safely modify the value. +/// - As a templated class, it provides type-safety so bit values and constants +/// used for different reasons may not be unknowingly compared to each other. +/// - The unique_index template parameter insures the unique type of each bit +/// bit-field. It shares the unique_index with a similar SafeBitConst. +/// - Its operations only allow comparisons to other bit-constants and +/// bit-fields of the same type. +//////////////////////////////////////////////////////////////////////////////// + +template +< + unsigned int unique_index, + typename word_t +> +class SafeBitField +{ +public: + + /// Type of the bit field is available if needed. + typedef word_t bit_word_t; + /// Corresponding field type. + typedef SafeBitConst< unique_index, word_t > const_t; + /// Typedef is not allowed in friendship declaration. + friend class SafeBitConst<unique_index, word_t>; + + /// Default constructor allows client code to construct bit fields on the stack. + SafeBitField() : word( 0 ) {} + + /// Copy constructor and assignment operators. + SafeBitField( const SafeBitField & rhs ) : word( rhs.word ) {} + SafeBitField & operator = ( const SafeBitField & rhs ) { word = rhs.word; return *this; } + + /// Copy constructor and assignment operators from constant bit fields. + SafeBitField( const const_t & rhs ) : word( rhs.word ) {} + SafeBitField & operator = ( const const_t & rhs ) { word = rhs.word; return *this; } + + /// These comparison operators act on bit-fields of the same type. + bool operator == ( const SafeBitField & rhs ) const { return word == rhs.word; } + bool operator != ( const SafeBitField & rhs ) const { return word != rhs.word; } + bool operator < ( const SafeBitField & rhs ) const { return word < rhs.word; } + bool operator > ( const SafeBitField & rhs ) const { return word > rhs.word; } + bool operator <= ( const SafeBitField & rhs ) const { return word <= rhs.word; } + bool operator >= ( const SafeBitField & rhs ) const { return word >= rhs.word; } + + /// These comparison operators act on bit-constants of a similar type. + bool operator == ( const const_t & rhs ) const { return word == rhs.word; } + bool operator != ( const const_t & rhs ) const { return word != rhs.word; } + bool operator < ( const const_t & rhs ) const { return word < rhs.word; } + bool operator > ( const const_t & rhs ) const { return word > rhs.word; } + bool operator <= ( const const_t & rhs ) const { return word <= rhs.word; } + bool operator >= ( const const_t & rhs ) const { return word >= rhs.word; } + + /// Bitwise operations that use bit-fields. + SafeBitField operator | ( const SafeBitField & rhs ) const { return SafeBitField( word | rhs.word ); } + SafeBitField operator & ( const SafeBitField & rhs ) const { return SafeBitField( word & rhs.word ); } + SafeBitField operator ^ ( const SafeBitField & rhs ) const { return SafeBitField( word ^ rhs.word ); } + SafeBitField operator ~ ( void ) const { return SafeBitField( ~word ); } + SafeBitField operator |= ( const SafeBitField & rhs ) { word |= rhs.word; return SafeBitField( *this ); } + SafeBitField operator &= ( const SafeBitField & rhs ) { word &= rhs.word; return SafeBitField( *this ); } + SafeBitField operator ^= ( const SafeBitField & rhs ) { word ^= rhs.word; return SafeBitField( *this ); } + + /// Bitwise operators that use bit-constants. + SafeBitField operator | ( const_t rhs ) const { return SafeBitField( word | rhs.word ); } + SafeBitField operator & ( const_t rhs ) const { return SafeBitField( word & rhs.word ); } + SafeBitField operator ^ ( const_t rhs ) const { return SafeBitField( word ^ rhs.word ); } + SafeBitField operator |= ( const_t rhs ) { word |= rhs.word; return SafeBitField( *this ); } + SafeBitField operator &= ( const_t rhs ) { word &= rhs.word; return SafeBitField( *this ); } + SafeBitField operator ^= ( const_t rhs ) { word ^= rhs.word; return SafeBitField( *this ); } + + // Conversion to bool. + // This is a major source of headaches, but it's required to support code like this: + // const static SafeBitConst<1> Label_value = SafeBitConst<1>::make_bit_const<1>(); + // SafeBitField<1> label; + // if ( label & Label_value ) { ... } // Nice... + // + // The downside is that this allows all sorts of nasty conversions. Without additional precautions, bit fields of different types + // can be converted to bool and then compared or operated on: + // SafeBitField<1> label1; + // SafeBitField<2> label2; + // if ( label1 == label2 ) { ... } // Yuck! + // if ( label1 & label2 ) { ... } // Blech! + // + // It is somewhat safer to convert to a pointer, at least pointers to different types cannot be readilly compared, and there are no + // bitwise operations on pointers, but the conversion from word_t to a pointer can have run-time cost if they are of different size. + // + operator const bool() const { return ( 0 != word ); } + + // Shift operators shift bits inside the bit field. Does not make + // sense, most of the time, except perhaps to loop over labels and + // increment them. + SafeBitField operator << ( unsigned int s ) { return SafeBitField( word << s ); } + SafeBitField operator >> ( unsigned int s ) { return SafeBitField( word >> s ); } + SafeBitField operator <<= ( unsigned int s ) { word <<= s; return *this; } + SafeBitField operator >>= ( unsigned int s ) { word >>= s; return *this; } + + // Word size is also the maximum number of different bit fields for + // a given word type. + static size_t size( void ) { return ( 8 * sizeof( word_t ) ); } + +private: + + /// Private constructor from an integer type. Don't put too much stock into + /// explicit declaration, it's better than nothing but does not solve all + /// problems with undesired conversions because SafeBitField coverts to bool. + explicit SafeBitField( word_t init ) : word( init ) {} + + /// This stores the bits. + word_t word; + + // Here comes the interesting stuff: all the operators designed to + // trap unintended conversions and make them not compile. + // Operators below handle code like this: + // SafeBitField<1> label1; + // SafeBitField<2> label2; + // if ( label1 & label2 ) { ... } + + // These operators are private, and will not instantiate in any + // event because of the incomplete Forbidden_conversion struct. + template < typename T > SafeBitField operator | ( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitField operator & ( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitField operator ^ ( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitField operator |= ( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitField operator &= ( T ) const { Forbidden_conversion< T > wrong; return *this; } + template < typename T > SafeBitField operator ^= ( T ) const { Forbidden_conversion< T > wrong; return *this; } + + // And the same thing for comparisons: + // if ( label1 == label2 ) { ... } + template < typename T > bool operator == ( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator != ( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator < ( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator > ( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator <= ( const T ) const { Forbidden_conversion< T > wrong; return true; } + template < typename T > bool operator >= ( const T ) const { Forbidden_conversion< T > wrong; return true; } +}; + +// The above template member operators catch errors when the first +// argument to a binary operator is a label, but they don't work when +// the first argument is an integer and the second one is a label: the +// label converts to bool and the operator is performed on two integers. +// These operators catch errors like this: +// SafeBitField<1> label1; +// SafeBitField<2> label2; +// if ( !label1 & label2 ) { ... } +// where the first label is converted to bool (these errors cannot be +// caught by member operators of SafeBitField class because the first +// argument is not SafeBitField but bool. +// +// If used, these operators will not instantiate because of the +// incomplete Forbidden_conversion struct. + +template < unsigned int unique_index, typename word_t > +inline SafeBitField< unique_index, word_t > operator & ( bool, SafeBitField< unique_index, word_t > rhs ) +{ + Forbidden_conversion<word_t> wrong; + return rhs; +} + +template < unsigned int unique_index, typename word_t > +inline SafeBitField< unique_index, word_t > operator | ( bool, SafeBitField< unique_index, word_t > rhs ) +{ + Forbidden_conversion< word_t > wrong; + return rhs; +} + +template < unsigned int unique_index, typename word_t > +inline SafeBitField< unique_index, word_t > operator ^ ( bool, SafeBitField< unique_index, word_t > rhs ) +{ + Forbidden_conversion< word_t > wrong; + return rhs; +} + +template < unsigned int unique_index, typename word_t > +inline SafeBitField< unique_index, word_t > operator == ( bool, SafeBitField< unique_index, word_t > rhs ) +{ + Forbidden_conversion< word_t > wrong; + return rhs; +} + +template < unsigned int unique_index, typename word_t > +inline SafeBitField< unique_index, word_t > operator != ( bool, SafeBitField< unique_index, word_t > rhs ) +{ + Forbidden_conversion< word_t > wrong; + return rhs; +} + +// Finally, few macros. All macros are conditionally defined to use the SafeBitField classes if LOKI_SAFE_BIT_FIELD is defined. Otherwise, +// the macros fall back on the use of typedefs and integer constants. This provides no addititonal safety but allows the code to support the +// mixture of compilers which are broken to different degrees. +#define LOKI_SAFE_BIT_FIELD + +// The first macro helps to declare new bit field types: +// LOKI_BIT_FIELD( ulong ) field_t; +// This creates a typedef field_t for SafeBitField<unique_index, ulong> where index is the current line number. Since line numbers __LINE__ are counted +// separately for all header files, this ends up being the same type in all files using the header which defines field_t. +#ifdef LOKI_SAFE_BIT_FIELD + #define LOKI_BIT_FIELD( word_t ) typedef SafeBitField<__LINE__, word_t> +#else + #define LOKI_BIT_FIELD( word_t ) typedef word_t +#endif // LOKI_SAFE_BIT_FIELD + +// The second macro helps to declare static bit constants: +// LOKI_BIT_CONST( field_t, Label_1, 1 ); +// creates new bit field object named Label_1 of type field_t which represents the field with the 1st (junior) bit set. +#ifdef LOKI_SAFE_BIT_FIELD + #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT + #define LOKI_BIT_CONST( field_t, label, bit_index ) \ + static const field_t::const_t label = field_t::const_t::make_bit_const<bit_index>() + #else + #define LOKI_BIT_CONST( field_t, label, bit_index ) \ + static const field_t::const_t label = field_t::const_t::make_bit_const( bit_index ) + #endif // LOKI_BIT_FIELD_NONTEMPLATE_INIT +#else + inline size_t make_bit_const( size_t i ) { return ( i > 0 ) ? ( size_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0; } + #define LOKI_BIT_CONST( field_t, label, bit_index ) static const field_t label = make_bit_const( bit_index ) +#endif // LOKI_SAFE_BIT_FIELD + +// The third macro helps to declare complex bit constants which are combination of several bits: +// LOKI_BIT_CONSTS( field_t, Label12 ) = Label_1 | Label_2; +#ifdef LOKI_SAFE_BIT_FIELD + #define LOKI_BIT_CONSTS( field_t, label ) static const field_t::const_t label +#else + #define LOKI_BIT_CONSTS( field_t, label ) static const field_t label +#endif // LOKI_SAFE_BIT_FIELD + +// The fourth macro helps to declare the maximum number of bit constants for a given type: +// static const size_t count = LOKI_BIT_FIELD_COUNT( field_t ); +// declared a variable "count" initialized to field_t::size() +#ifdef LOKI_SAFE_BIT_FIELD + #define LOKI_BIT_FIELD_COUNT( field_t ) field_t::size() +#else + #define LOKI_BIT_FIELD_COUNT( field_t ) ( 8 * sizeof(field_t) ) +#endif // LOKI_SAFE_BIT_FIELD + +} // namespace Loki + +#endif // LOKI_INCLUDED_SAFE_BIT_FIELDS_H diff --git a/shared/loki/SafeFormat.h b/shared/loki/SafeFormat.h new file mode 100644 index 00000000..9d948581 --- /dev/null +++ b/shared/loki/SafeFormat.h @@ -0,0 +1,590 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2005 by Andrei Alexandrescu +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute, and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the suitability of this software +// for any purpose. It is provided "as is" without express or implied +// warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SAFEFORMAT_INC_ +#define LOKI_SAFEFORMAT_INC_ + +// $Id: SafeFormat.h 911 2008-12-15 20:55:24Z syntheticpp $ + + +//////////////////////////////////////////////////////////////////////////////// +// This file contains definitions for SafePrintf. SafeScanf coming soon (the +// design is similar). +// See Alexandrescu, Andrei: Type-safe Formatting, C/C++ Users Journal, Aug 2005 +//////////////////////////////////////////////////////////////////////////////// + +#include <cstdio> +#include <climits> +#include <string> +#include <cstring> +#include <stdexcept> +#include <utility> +#include <cassert> +#include <locale> +#include <iostream> + +#include <loki/LokiExport.h> + + +// long is 32 bit on 64-bit Windows! +// intptr_t used to get 64 bit on Win64 +#if defined(_WIN32) || defined(_WIN64) +# define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t +# define LOKI_SAFEFORMAT_UNSIGNED_LONG uintptr_t +#else +# define LOKI_SAFEFORMAT_SIGNED_LONG signed long +# define LOKI_SAFEFORMAT_UNSIGNED_LONG unsigned long +#endif + +// Windows headers could have min/max defined +#ifdef max +# undef max +#endif +#ifdef min +# undef min +#endif + +namespace Loki +{ + + // Crude writing method: writes straight to the file, unbuffered + // Must be combined with a buffer to work properly (and efficiently) + LOKI_EXPORT + void write(std::FILE* f, const char* from, const char* to); + + // Write to an ostream + LOKI_EXPORT + void write(std::ostream& f, const char* from, const char* to); + + // Write to a string + LOKI_EXPORT + void write(std::string& s, const char* from, const char* to); + + // Write to a fixed-size buffer + template <class Char> + void write(std::pair<Char*, std::size_t>& s, const Char* from, const Char* to) { + assert(from <= to); + if(from + s.second < to) + throw std::overflow_error(""); + // s.first: position one past the final copied element + s.first = std::copy(from, to, s.first); + // remaining buffer size + s.second -= to - from; + } + + //////////////////////////////////////////////////////////////////////////////// + // PrintfState class template + // Holds the formatting state, and implements operator() to format stuff + // Todo: make sure errors are handled properly + //////////////////////////////////////////////////////////////////////////////// + + template <class Device, class Char> + struct PrintfState { + PrintfState(Device dev, const Char * format) + : device_(dev) + , format_(format) + , width_(0) + , prec_(0) + , flags_(0) + , result_(0) { + Advance(); + } + + ~PrintfState() { + } + + #define LOKI_PRINTF_STATE_FORWARD(type) \ + PrintfState& operator()(type par) {\ + return (*this)(static_cast< LOKI_SAFEFORMAT_UNSIGNED_LONG >(par)); \ + } + + LOKI_PRINTF_STATE_FORWARD(bool) + LOKI_PRINTF_STATE_FORWARD(char) + LOKI_PRINTF_STATE_FORWARD(signed char) + LOKI_PRINTF_STATE_FORWARD(unsigned char) + LOKI_PRINTF_STATE_FORWARD(signed short) + LOKI_PRINTF_STATE_FORWARD(unsigned short) + LOKI_PRINTF_STATE_FORWARD(signed int) + LOKI_PRINTF_STATE_FORWARD(signed long) +#if (defined(_WIN32) || defined(_WIN64)) + LOKI_PRINTF_STATE_FORWARD(unsigned long) +#else + // on Windows already defined by uintptr_t + LOKI_PRINTF_STATE_FORWARD(unsigned int) +#endif + + // Print (or gobble in case of the "*" specifier) an int + PrintfState& operator()(LOKI_SAFEFORMAT_UNSIGNED_LONG i) { + if (result_ == -1) return *this; // don't even bother + // % [flags] [width] [.prec] [modifier] type_char + // Fetch the flags + ReadFlags(); + if (*format_ == '*') { + // read the width and get out + SetWidth(static_cast<size_t>(i)); + ++format_; + return *this; + } + ReadWidth(); + // precision + if (*format_ == '.') { + // deal with precision + if (format_[1] == '*') { + // read the precision and get out + SetPrec(static_cast<size_t>(i)); + format_ += 2; + return *this; + } + ReadPrecision(); + } + ReadModifiers(); + // input size modifier + if (ForceShort()) { + // short int + const Char c = *format_; + if (c == 'x' || c == 'X' || c == 'u' || c == 'o') { + i = static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(static_cast<unsigned short>(i)); + } + } + FormatWithCurrentFlags(i); + return *this; + } + + PrintfState& operator()(void* n) { + if (result_ == -1) return *this; // don't even bother + PrintUsing_snprintf(n,"p"); + return *this; + } + + PrintfState& operator()(double n) { + if (result_ == -1) return *this; // don't even bother + PrintUsing_snprintf(n,"eEfgG"); + return *this; + } + + PrintfState& operator()(long double n) { + if (result_ == -1) return *this; // don't even bother + PrintUsing_snprintf(n,"eEfgG"); + return *this; + } + + // Store the number of characters printed so far + PrintfState& operator()(int * pi) { + return StoreCountHelper(pi); + } + + // Store the number of characters printed so far + PrintfState& operator()(short * pi) { + return StoreCountHelper(pi); + } + + // Store the number of characters printed so far + PrintfState& operator()(long * pi) { + return StoreCountHelper(pi); + } + + PrintfState& operator()(const std::string& stdstr) { + return operator()(stdstr.c_str()); + } + + PrintfState& operator()(const char *const s) { + if (result_ == -1) return *this; + ReadLeaders(); + const char fmt = *format_; + if (fmt == 'p') { + FormatWithCurrentFlags(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(s)); + return *this; + } + if (fmt != 's') { + result_ = -1; + return *this; + } + const size_t len = std::min(std::strlen(s), prec_); + if (width_ > len) { + if (LeftJustify()) { + Write(s, s + len); + Fill(' ', width_ - len); + } else { + Fill(' ', width_ - len); + Write(s, s + len); + } + } else { + Write(s, s + len); + } + Next(); + return *this; + } + + PrintfState& operator()(const void *const p) { + return (*this)(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(p)); + } + + // read the result + operator int() const { + return static_cast<int>(result_); + } + + private: + PrintfState& operator=(const PrintfState&); + template <typename T> + PrintfState& StoreCountHelper(T *const pi) { + if (result_ == -1) return *this; // don't even bother + ReadLeaders(); + const char fmt = *format_; + if (fmt == 'p') { // pointer + FormatWithCurrentFlags(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(pi)); + return *this; + } + if (fmt != 'n') { + result_ = -1; + return *this; + } + assert(pi != 0); + *pi = result_; + Next(); + return *this; + } + + void FormatWithCurrentFlags(const LOKI_SAFEFORMAT_UNSIGNED_LONG i) { + // look at the format character + Char formatChar = *format_; + bool isSigned = formatChar == 'd' || formatChar == 'i'; + if (formatChar == 'p') { + formatChar = 'x'; // pointers go to hex + SetAlternateForm(); // printed with '0x' in front + isSigned = true; // that's what gcc does + } + if (!strchr("cdiuoxX", formatChar)) { + result_ = -1; + return; + } + Char buf[ + sizeof(LOKI_SAFEFORMAT_UNSIGNED_LONG) * 3 // digits + + 1 // sign or ' ' + + 2 // 0x or 0X + + 1]; // terminating zero + const Char *const bufEnd = buf + (sizeof(buf) / sizeof(Char)); + Char * bufLast = buf + (sizeof(buf) / sizeof(Char) - 1); + Char signChar = 0; + unsigned int base = 10; + + if (formatChar == 'c') { + // Format only one character + // The 'fill with zeros' flag is ignored + ResetFillZeros(); + *bufLast = static_cast<char>(i); + } else { + // TODO: inefficient code, refactor + const bool negative = isSigned && static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(i) < 0; + if (formatChar == 'o') base = 8; + else if (formatChar == 'x' || formatChar == 'X') base = 16; + bufLast = isSigned + ? RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(i), bufLast, base, + formatChar == 'X') + : RenderWithoutSign(i, bufLast, base, + formatChar == 'X'); + // Add the sign + if (isSigned) { + negative ? signChar = '-' + : ShowSignAlways() ? signChar = '+' + : Blank() ? signChar = ' ' + : 0; + } + } + // precision + size_t + countDigits = bufEnd - bufLast, + countZeros = prec_ != size_t(-1) && countDigits < prec_ && + formatChar != 'c' + ? prec_ - countDigits + : 0, + countBase = base != 10 && AlternateForm() && i != 0 + ? (base == 16 ? 2 : countZeros > 0 ? 0 : 1) + : 0, + countSign = (signChar != 0), + totalPrintable = countDigits + countZeros + countBase + countSign; + size_t countPadLeft = 0, countPadRight = 0; + if (width_ > totalPrintable) { + if (LeftJustify()) { + countPadRight = width_ - totalPrintable; + countPadLeft = 0; + } else { + countPadLeft = width_ - totalPrintable; + countPadRight = 0; + } + } + if (FillZeros() && prec_ == size_t(-1)) { + // pad with zeros and no precision - transfer padding to precision + countZeros = countPadLeft; + countPadLeft = 0; + } + // ok, all computed, ready to print to device + Fill(' ', countPadLeft); + if (signChar != 0) Write(&signChar, &signChar + 1); + if (countBase > 0) Fill('0', 1); + if (countBase == 2) Fill(formatChar, 1); + Fill('0', countZeros); + Write(bufLast, bufEnd); + Fill(' ', countPadRight); + // done, advance + Next(); + } + + void Write(const Char* b, const Char* e) { + if (result_ < 0) return; + const LOKI_SAFEFORMAT_SIGNED_LONG x = e - b; + write(device_, b, e); + result_ += x; + } + + template <class Value> + void PrintUsing_snprintf(Value n, const char* check_fmt_char) { + const Char *const fmt = format_ - 1; + assert(*fmt == '%'); + // enforce format string validity + ReadLeaders(); + // enforce format spec + if (!strchr(check_fmt_char, *format_)) { + result_ = -1; + return; + } + // format char validated, copy it to a temp and use legacy sprintf + ++format_; + Char fmtBuf[128], resultBuf[1024]; + if (format_ >= fmt + sizeof(fmtBuf) / sizeof(Char)) { + result_ = -1; + return; + } + memcpy(fmtBuf, fmt, (format_ - fmt) * sizeof(Char)); + fmtBuf[format_ - fmt] = 0; + + const int stored = +#ifdef _MSC_VER +#if _MSC_VER < 1400 + _snprintf +#else + _snprintf_s +#endif +#else + snprintf +#endif + (resultBuf, sizeof(resultBuf) / sizeof(Char), fmtBuf, n); + + if (stored < 0) { + result_ = -1; + return; + } + Write(resultBuf, resultBuf + strlen(resultBuf)); + Advance(); // output stuff to the next format directive + } + + void Fill(const Char c, size_t n) { + for (; n > 0; --n) { + Write(&c, &c + 1); + } + } + + Char* RenderWithoutSign(LOKI_SAFEFORMAT_UNSIGNED_LONG n, char* bufLast, + unsigned int base, bool uppercase) { + const Char hex1st = uppercase ? 'A' : 'a'; + for (;;) { + const LOKI_SAFEFORMAT_UNSIGNED_LONG next = n / base; + Char c = static_cast<Char>(n - next * base); + c = static_cast<Char>(c + (c <= 9 ? '0' : static_cast<Char>(hex1st - 10))); + *bufLast = c; + n = next; + if (n == 0) break; + --bufLast; + } + return bufLast; + } + + char* RenderWithoutSign(LOKI_SAFEFORMAT_SIGNED_LONG n, char* bufLast, unsigned int base, + bool uppercase) { + if (n != LONG_MIN) { + return RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(n < 0 ? -n : n), + bufLast, base, uppercase); + } + // annoying corner case + char* save = bufLast; + ++n; + bufLast = RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(n), + bufLast, base, uppercase); + --(*save); + return bufLast; + } + + void Next() { + ++format_; + Advance(); + } + + void Advance() { + ResetAll(); + const Char* begin = format_; + for (;;) { + if (*format_ == '%') { + if (format_[1] != '%') { // It's a format specifier + Write(begin, format_); + ++format_; + break; + } + // It's a "%%" + Write(begin, ++format_); + begin = ++format_; + continue; + } + if (*format_ == 0) { + Write(begin, format_); + break; + } + ++format_; + } + } + + void ReadFlags() { + for (;; ++format_) { + switch (*format_) { + case '-': SetLeftJustify(); break; + case '+': SetShowSignAlways(); break; + case ' ': SetBlank(); break; + case '#': SetAlternateForm(); break; + case '0': SetFillZeros(); break; + default: return; + } + } + } + + void ParseDecimalSizeT(size_t& dest) { + if (!std::isdigit(*format_, std::locale())) return; + size_t r = 0; + do { + // TODO: inefficient - rewrite + r *= 10; + r += *format_ - '0'; + ++format_; + } while (std::isdigit(*format_, std::locale())); + dest = r; + } + + void ReadWidth() { + ParseDecimalSizeT(width_); + } + + void ReadPrecision() { + assert(*format_ == '.'); + ++format_; + ParseDecimalSizeT(prec_); + } + + void ReadModifiers() { + switch (*format_) { + case 'h': SetForceShort(); ++format_; break; + case 'l': ++format_; break; + // more (C99 and platform-specific modifiers) to come + } + } + + void ReadLeaders() { + ReadFlags(); + ReadWidth(); + if (*format_ == '.') ReadPrecision(); + ReadModifiers(); + } + + enum { + leftJustify = 1, + showSignAlways = 2, + blank = 4, + alternateForm = 8, + fillZeros = 16, + forceShort = 32 + }; + + bool LeftJustify() const { return (flags_ & leftJustify) != 0; } + bool ShowSignAlways() const { return (flags_ & showSignAlways) != 0; } + void SetWidth(size_t w) { width_ = w; } + void SetLeftJustify() { flags_ |= leftJustify; } + void SetShowSignAlways() { flags_ |= showSignAlways; } + bool Blank() const { return (flags_ & blank) != 0; } + bool AlternateForm() const { return (flags_ & alternateForm) != 0; } + bool FillZeros() const { return (flags_ & fillZeros) != 0; } + bool ForceShort() const { return (flags_ & forceShort) != 0; } + + void SetPrec(size_t p) { prec_ = p; } + void SetBlank() { flags_ |= blank; } + void SetAlternateForm() { flags_ |= alternateForm; } + void SetFillZeros() { flags_ |= fillZeros; } + void ResetFillZeros() { flags_ &= ~fillZeros; } + void SetForceShort() { flags_ |= forceShort; } + + void ResetAll() { + assert(result_ != EOF); + width_ = 0; + prec_ = size_t(-1); + flags_ = 0; + } + + // state + Device device_; + const Char* format_; + size_t width_; + size_t prec_; + unsigned int flags_; + LOKI_SAFEFORMAT_SIGNED_LONG result_; + }; + + LOKI_EXPORT + PrintfState<std::FILE*, char> Printf(const char* format); + + LOKI_EXPORT + PrintfState<std::FILE*, char> Printf(const std::string& format); + + LOKI_EXPORT + PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const char* format); + + LOKI_EXPORT + PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const std::string& format); + + LOKI_EXPORT + PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const char* format); + + LOKI_EXPORT + PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const std::string& format); + + LOKI_EXPORT + PrintfState<std::string&, char> SPrintf(std::string& s, const char* format); + + LOKI_EXPORT + PrintfState<std::string&, char> SPrintf(std::string& s, const std::string& format); + + template <class T, class Char> + PrintfState<T&, Char> XPrintf(T& device, const Char* format) { + return PrintfState<T&, Char>(device, format); + } + + template <class T> + PrintfState<T&, char> XPrintf(T& device, const std::string& format) { + return PrintfState<T&, char>(device, format.c_str()); + } + + template <class Char, std::size_t N> + PrintfState<std::pair<Char*, std::size_t>, Char> + BufPrintf(Char (&buf)[N], const Char* format) { + std::pair<Char*, std::size_t> temp(buf, N); + return PrintfState<std::pair<Char*, std::size_t>, Char>(temp, format); + } + +}// namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/ScopeGuard.h b/shared/loki/ScopeGuard.h new file mode 100644 index 00000000..a7e61ddd --- /dev/null +++ b/shared/loki/ScopeGuard.h @@ -0,0 +1,666 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2000 Andrei Alexandrescu +// Copyright (c) 2000 Petru Marginean +// Copyright (c) 2005 Joshua Lehrer +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SCOPEGUARD_INC_ +#define LOKI_SCOPEGUARD_INC_ + +// $Id: ScopeGuard.h 799 2006-12-20 00:37:13Z rich_sposato $ + + +#include <loki/RefToValue.h> + +/// \defgroup ExceptionGroup Exception-safe code + +namespace Loki +{ + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImplBase + /// \ingroup ExceptionGroup + /// + /// Base class used by all ScopeGuard implementations. All commonly used + /// functions are in this class (e.g. - Dismiss and SafeExecute). + /// + /// See Andrei's and Petru Marginean's CUJ article + /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm + /// + /// Changes to the original code by Joshua Lehrer: + /// http://www.lehrerfamily.com/scopeguard.html + //////////////////////////////////////////////////////////////// + + class ScopeGuardImplBase + { + /// Copy-assignment operator is not implemented and private. + ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); + + protected: + + ~ScopeGuardImplBase() + {} + + /// Copy-constructor takes over responsibility from other ScopeGuard. + ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() + : dismissed_(other.dismissed_) + { + other.Dismiss(); + } + + template <typename J> + static void SafeExecute(J& j) throw() + { + if (!j.dismissed_) + try + { + j.Execute(); + } + catch(...) + {} + } + + mutable bool dismissed_; + + public: + ScopeGuardImplBase() throw() : dismissed_(false) + {} + + void Dismiss() const throw() + { + dismissed_ = true; + } + }; + + //////////////////////////////////////////////////////////////// + /// + /// \typedef typedef const ScopeGuardImplBase& ScopeGuard + /// \ingroup ExceptionGroup + /// + //////////////////////////////////////////////////////////////// + + typedef const ScopeGuardImplBase& ScopeGuard; + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl0 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with no parameters. ScopeGuard ignores any value returned from the + /// call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template <typename F> + class ScopeGuardImpl0 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl0<F> MakeGuard(F fun) + { + return ScopeGuardImpl0<F>(fun); + } + + ~ScopeGuardImpl0() throw() + { + SafeExecute(*this); + } + + void Execute() + { + fun_(); + } + + protected: + ScopeGuardImpl0(F fun) : fun_(fun) + {} + + F fun_; + }; + + template <typename F> + inline ScopeGuardImpl0<F> MakeGuard(F fun) + { + return ScopeGuardImpl0<F>::MakeGuard(fun); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl1 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with one parameter. Each parameter is copied by value - use + /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores + /// any value returned from the call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template <typename F, typename P1> + class ScopeGuardImpl1 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) + { + return ScopeGuardImpl1<F, P1>(fun, p1); + } + + ~ScopeGuardImpl1() throw() + { + SafeExecute(*this); + } + + void Execute() + { + fun_(p1_); + } + + protected: + ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) + {} + + F fun_; + const P1 p1_; + }; + + template <typename F, typename P1> + inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) + { + return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl2 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with two parameters. Each parameter is copied by value - use + /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores + /// any value returned from the call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template <typename F, typename P1, typename P2> + class ScopeGuardImpl2: public ScopeGuardImplBase + { + public: + static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) + { + return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2); + } + + ~ScopeGuardImpl2() throw() + { + SafeExecute(*this); + } + + void Execute() + { + fun_(p1_, p2_); + } + + protected: + ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) + {} + + F fun_; + const P1 p1_; + const P2 p2_; + }; + + template <typename F, typename P1, typename P2> + inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) + { + return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl3 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with three parameters. Each parameter is copied by value - use + /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores + /// any value returned from the call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template <typename F, typename P1, typename P2, typename P3> + class ScopeGuardImpl3 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) + { + return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3); + } + + ~ScopeGuardImpl3() throw() + { + SafeExecute(*this); + } + + void Execute() + { + fun_(p1_, p2_, p3_); + } + + protected: + ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) + {} + + F fun_; + const P1 p1_; + const P2 p2_; + const P3 p3_; + }; + + template <typename F, typename P1, typename P2, typename P3> + inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) + { + return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl4 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with four parameters. Each parameter is copied by value - use + /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores + /// any value returned from the call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template < typename F, typename P1, typename P2, typename P3, typename P4 > + class ScopeGuardImpl4 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( + F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) + { + return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 ); + } + + ~ScopeGuardImpl4() throw() + { + SafeExecute( *this ); + } + + void Execute() + { + fun_( p1_, p2_, p3_, p4_ ); + } + + protected: + ScopeGuardImpl4( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) : + fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ) + {} + + F fun_; + const P1 p1_; + const P2 p2_; + const P3 p3_; + const P4 p4_; + }; + + template < typename F, typename P1, typename P2, typename P3, typename P4 > + inline ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) + { + return ScopeGuardImpl4< F, P1, P2, P3, P4 >::MakeGuard( fun, p1, p2, p3, p4 ); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ScopeGuardImpl5 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a standalone function or class static function + /// with five parameters. Each parameter is copied by value - use + /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores + /// any value returned from the call within the Execute function. + /// + /// This class has a single standalone helper function, MakeGuard which + /// creates and returns a ScopeGuard. + /// + //////////////////////////////////////////////////////////////// + + template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 > + class ScopeGuardImpl5 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( + F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) + { + return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 ); + } + + ~ScopeGuardImpl5() throw() + { + SafeExecute( *this ); + } + + void Execute() + { + fun_( p1_, p2_, p3_, p4_, p5_ ); + } + + protected: + ScopeGuardImpl5( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) : + fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ), p5_( p5 ) + {} + + F fun_; + const P1 p1_; + const P2 p2_; + const P3 p3_; + const P4 p4_; + const P5 p5_; + }; + + template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 > + inline ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) + { + return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >::MakeGuard( fun, p1, p2, p3, p4, p5 ); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ObjScopeGuardImpl0 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a class per-instance member function with no + /// parameters. ScopeGuard ignores any value returned from the call within + /// the Execute function. + /// + /// This class has 3 standalone helper functions which create a ScopeGuard. + /// One is MakeObjGuard, which is deprecated but provided for older code. + /// The other two are MakeGuard overloads, one which takes a pointer to an + /// object, and the other which takes a reference. + /// + //////////////////////////////////////////////////////////////// + + template <class Obj, typename MemFun> + class ObjScopeGuardImpl0 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) + { + return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); + } + + ~ObjScopeGuardImpl0() throw() + { + SafeExecute(*this); + } + + void Execute() + { + (obj_.*memFun_)(); + } + + protected: + ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) + {} + + Obj& obj_; + MemFun memFun_; + }; + + template <class Obj, typename MemFun> + inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) + { + return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun); + } + + template <typename Ret, class Obj1, class Obj2> + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) + { + return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun); + } + + template <typename Ret, class Obj1, class Obj2> + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) + { + return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ObjScopeGuardImpl1 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a class per-instance member function with one + /// parameter. The parameter is copied by value - use ::Loki::ByRef if you + /// must use a reference instead. ScopeGuard ignores any value returned + /// from the call within the Execute function. + /// + /// This class has 3 standalone helper functions which create a ScopeGuard. + /// One is MakeObjGuard, which is deprecated but provided for older code. + /// The other two are MakeGuard overloads, one which takes a pointer to an + /// object, and the other which takes a reference. + /// + //////////////////////////////////////////////////////////////// + + template <class Obj, typename MemFun, typename P1> + class ObjScopeGuardImpl1 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) + { + return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1); + } + + ~ObjScopeGuardImpl1() throw() + { + SafeExecute(*this); + } + + void Execute() + { + (obj_.*memFun_)(p1_); + } + + protected: + ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) + {} + + Obj& obj_; + MemFun memFun_; + const P1 p1_; + }; + + template <class Obj, typename MemFun, typename P1> + inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) + { + return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) + { + return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) + { + return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ObjScopeGuardImpl2 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a class per-instance member function with two + /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you + /// must use a reference instead. ScopeGuard ignores any value returned + /// from the call within the Execute function. + /// + /// This class has 3 standalone helper functions which create a ScopeGuard. + /// One is MakeObjGuard, which is deprecated but provided for older code. + /// The other two are MakeGuard overloads, one which takes a pointer to an + /// object, and the other which takes a reference. + /// + //////////////////////////////////////////////////////////////// + + template <class Obj, typename MemFun, typename P1, typename P2> + class ObjScopeGuardImpl2 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) + { + return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); + } + + ~ObjScopeGuardImpl2() throw() + { + SafeExecute(*this); + } + + void Execute() + { + (obj_.*memFun_)(p1_, p2_); + } + + protected: + ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) + {} + + Obj& obj_; + MemFun memFun_; + const P1 p1_; + const P2 p2_; + }; + + template <class Obj, typename MemFun, typename P1, typename P2> + inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) + { + return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) + { + return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) + { + return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2); + } + + //////////////////////////////////////////////////////////////// + /// + /// \class ObjScopeGuardImpl3 + /// \ingroup ExceptionGroup + /// + /// Implementation class for a class per-instance member function with three + /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you + /// must use a reference instead. ScopeGuard ignores any value returned + /// from the call within the Execute function. + /// + /// This class has 3 standalone helper functions which create a ScopeGuard. + /// One is MakeObjGuard, which is deprecated but provided for older code. + /// The other two are MakeGuard overloads, one which takes a pointer to an + /// object, and the other which takes a reference. + /// + //////////////////////////////////////////////////////////////// + + template < class Obj, typename MemFun, typename P1, typename P2, typename P3 > + class ObjScopeGuardImpl3 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard( + Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) + { + return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 ); + } + + ~ObjScopeGuardImpl3() throw() + { + SafeExecute( *this ); + } + + void Execute() + { + ( obj_.*memFun_ )( p1_, p2_, p3_ ); + } + + protected: + ObjScopeGuardImpl3( Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) : + obj_( obj ), memFun_( memFun ), p1_( p1 ), p2_( p2 ), p3_( p3 ) + {} + + Obj& obj_; + MemFun memFun_; + const P1 p1_; + const P2 p2_; + const P3 p3_; + }; + + template < class Obj, typename MemFun, typename P1, typename P2, typename P3 > + inline ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard( + Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) + { + return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >::MakeObjGuard( + obj, memFun, p1, p2, p3 ); + } + + template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, + typename P2a, typename P2b, typename P3a, typename P3b > + inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b > + MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 & obj, P1b p1, P2b p2, P3b p3 ) + { + return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b > + ::MakeObjGuard( obj, memFun, p1, p2, p3 ); + } + + template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, + typename P2a, typename P2b, typename P3a, typename P3b > + inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b > + MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 * obj, P1b p1, P2b p2, P3b p3 ) + { + return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b > + ::MakeObjGuard( *obj, memFun, p1, p2, p3 ); + } + +} // namespace Loki + +#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 +#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) +#define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__) + +#define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard +#define LOKI_ON_BLOCK_EXIT_OBJ ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeObjGuard + +#endif // end file guardian + diff --git a/shared/loki/Sequence.h b/shared/loki/Sequence.h new file mode 100644 index 00000000..4e5bd235 --- /dev/null +++ b/shared/loki/Sequence.h @@ -0,0 +1,49 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2005 by Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SEQUENCE_INC_ +#define LOKI_SEQUENCE_INC_ + +// $Id: Sequence.h 768 2006-10-25 20:40:40Z syntheticpp $ + + +#include "Typelist.h" + +namespace Loki +{ + + template + < + class T01=NullType,class T02=NullType,class T03=NullType,class T04=NullType,class T05=NullType, + class T06=NullType,class T07=NullType,class T08=NullType,class T09=NullType,class T10=NullType, + class T11=NullType,class T12=NullType,class T13=NullType,class T14=NullType,class T15=NullType, + class T16=NullType,class T17=NullType,class T18=NullType,class T19=NullType,class T20=NullType + > + struct Seq + { + private: + typedef typename Seq< T02, T03, T04, T05, T06, T07, T08, T09, T10, + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>::Type + TailResult; + public: + typedef Typelist<T01, TailResult> Type; + }; + + template<> + struct Seq<> + { + typedef NullType Type; + }; + +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/Singleton.h b/shared/loki/Singleton.h new file mode 100644 index 00000000..42d6eb0d --- /dev/null +++ b/shared/loki/Singleton.h @@ -0,0 +1,889 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SINGLETON_INC_ +#define LOKI_SINGLETON_INC_ + +// $Id: Singleton.h 834 2007-08-02 19:36:10Z syntheticpp $ + + +#include "LokiExport.h" +#include "Threads.h" +#include <algorithm> +#include <stdexcept> +#include <cassert> +#include <cstdlib> +#include <new> +#include <vector> +#include <list> +#include <memory> + +#ifdef _MSC_VER +#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl +#else +#define LOKI_C_CALLING_CONVENTION_QUALIFIER +#endif + +/// \defgroup SingletonGroup Singleton +/// \defgroup CreationGroup Creation policies +/// \ingroup SingletonGroup +/// \defgroup LifetimeGroup Lifetime policies +/// \ingroup SingletonGroup +/// The lifetimes of the singleton. +/// \par Special lifetime for SmallObjects +/// When the holded object is a Small(Value)Object or the holded object +/// uses objects which are or inherit from Small(Value)Object +/// then you can't use the default lifetime: you must use the lifetime +/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode +/// Be aware of this when you use Loki::Factory, Loki::Functor, or Loki::Function. + + + +namespace Loki +{ + typedef void (LOKI_C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)(); + + namespace Private + { + +#ifndef LOKI_MAKE_DLL + void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below +#else + void LOKI_EXPORT AtExitFn(); +#endif + + class LifetimeTracker; + +#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL +#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL + + // Helper data + // std::list because of the inserts + typedef std::list<LifetimeTracker*> TrackerArray; + extern LOKI_EXPORT TrackerArray* pTrackerArray; +#else + // Helper data + typedef LifetimeTracker** TrackerArray; + extern TrackerArray pTrackerArray; + extern unsigned int elements; +#endif + + //////////////////////////////////////////////////////////////////////////////// + // class LifetimeTracker + // Helper class for SetLongevity + //////////////////////////////////////////////////////////////////////////////// + + class LifetimeTracker + { + public: + LifetimeTracker(unsigned int x) : longevity_(x) + {} + + virtual ~LifetimeTracker() = 0; + + static bool Compare(const LifetimeTracker* lhs, + const LifetimeTracker* rhs) + { + return lhs->longevity_ > rhs->longevity_; + } + + private: + unsigned int longevity_; + }; + + // Definition required + inline LifetimeTracker::~LifetimeTracker() {} + + // Helper destroyer function + template <typename T> + struct Deleter + { + typedef void (*Type)(T*); + static void Delete(T* pObj) + { delete pObj; } + }; + + // Concrete lifetime tracker for objects of type T + template <typename T, typename Destroyer> + class ConcreteLifetimeTracker : public LifetimeTracker + { + public: + ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d) + : LifetimeTracker(longevity) + , pTracked_(p) + , destroyer_(d) + {} + + ~ConcreteLifetimeTracker() + { destroyer_(pTracked_); } + + private: + T* pTracked_; + Destroyer destroyer_; + }; + + } // namespace Private + + //////////////////////////////////////////////////////////////////////////////// + /// \ingroup LifetimeGroup + /// + /// Assigns an object a longevity; ensures ordered destructions of objects + /// registered thusly during the exit sequence of the application + //////////////////////////////////////////////////////////////////////////////// + +#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL + + template <typename T, typename Destroyer> + void SetLongevity(T* pDynObject, unsigned int longevity, + Destroyer d) + { + using namespace Private; + + // manage lifetime of stack manually + if(pTrackerArray==0) + pTrackerArray = new TrackerArray; + + // automatically delete the ConcreteLifetimeTracker object when a exception is thrown + std::auto_ptr<LifetimeTracker> + p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) ); + + // Find correct position + TrackerArray::iterator pos = std::upper_bound( + pTrackerArray->begin(), + pTrackerArray->end(), + p.get(), + LifetimeTracker::Compare); + + // Insert the pointer to the ConcreteLifetimeTracker object into the queue + pTrackerArray->insert(pos, p.get()); + + // nothing has thrown: don't delete the ConcreteLifetimeTracker object + p.release(); + + // Register a call to AtExitFn + std::atexit(Private::AtExitFn); + } + +#else + + template <typename T, typename Destroyer> + void SetLongevity(T* pDynObject, unsigned int longevity, + Destroyer d) + { + using namespace Private; + + TrackerArray pNewArray = static_cast<TrackerArray>( + std::realloc(pTrackerArray, + sizeof(*pTrackerArray) * (elements + 1))); + if (!pNewArray) throw std::bad_alloc(); + + // Delayed assignment for exception safety + pTrackerArray = pNewArray; + + LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>( + pDynObject, longevity, d); + + // Insert a pointer to the object into the queue + TrackerArray pos = std::upper_bound( + pTrackerArray, + pTrackerArray + elements, + p, + LifetimeTracker::Compare); + std::copy_backward( + pos, + pTrackerArray + elements, + pTrackerArray + elements + 1); + *pos = p; + ++elements; + + // Register a call to AtExitFn + std::atexit(Private::AtExitFn); + } + +#endif + + template <typename T> + void SetLongevity(T* pDynObject, unsigned int longevity, + typename Private::Deleter<T>::Type d = Private::Deleter<T>::Delete) + { + SetLongevity<T, typename Private::Deleter<T>::Type>(pDynObject, longevity, d); + } + + //////////////////////////////////////////////////////////////////////////////// + /// \struct CreateUsingNew + /// + /// \ingroup CreationGroup + /// Implementation of the CreationPolicy used by SingletonHolder + /// Creates objects using a straight call to the new operator + //////////////////////////////////////////////////////////////////////////////// + template <class T> struct CreateUsingNew + { + static T* Create() + { return new T; } + + static void Destroy(T* p) + { delete p; } + }; + + //////////////////////////////////////////////////////////////////////////////// + /// \struct CreateUsing + /// + /// \ingroup CreationGroup + /// Implementation of the CreationPolicy used by SingletonHolder + /// Creates objects using a custom allocater. + /// Usage: e.g. CreateUsing<std::allocator>::Allocator + //////////////////////////////////////////////////////////////////////////////// + template<template<class> class Alloc> + struct CreateUsing + { + template <class T> + struct Allocator + { + static Alloc<T> allocator; + + static T* Create() + { + return new (allocator.allocate(1)) T; + } + + static void Destroy(T* p) + { + //allocator.destroy(p); + p->~T(); + allocator.deallocate(p,1); + } + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + /// \struct CreateUsingMalloc + /// + /// \ingroup CreationGroup + /// Implementation of the CreationPolicy used by SingletonHolder + /// Creates objects using a call to std::malloc, followed by a call to the + /// placement new operator + //////////////////////////////////////////////////////////////////////////////// + template <class T> struct CreateUsingMalloc + { + static T* Create() + { + void* p = std::malloc(sizeof(T)); + if (!p) return 0; + return new(p) T; + } + + static void Destroy(T* p) + { + p->~T(); + std::free(p); + } + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// \struct CreateStatic + /// + /// \ingroup CreationGroup + /// Implementation of the CreationPolicy used by SingletonHolder + /// Creates an object in static memory + /// Implementation is slightly nonportable because it uses the MaxAlign trick + /// (an union of all types to ensure proper memory alignment). This trick is + /// nonportable in theory but highly portable in practice. + //////////////////////////////////////////////////////////////////////////////// + template <class T> struct CreateStatic + { + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4121 ) +// alignment of a member was sensitive to packing +#endif // _MSC_VER + + union MaxAlign + { + char t_[sizeof(T)]; + short int shortInt_; + int int_; + long int longInt_; + float float_; + double double_; + long double longDouble_; + struct Test; + int Test::* pMember_; + int (Test::*pMemberFn_)(int); + }; + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif // _MSC_VER + + static T* Create() + { + static MaxAlign staticMemory_; + return new(&staticMemory_) T; + } + + static void Destroy(T* p) + { + p->~T(); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + /// \struct DefaultLifetime + /// + /// \ingroup LifetimeGroup + /// Implementation of the LifetimePolicy used by SingletonHolder + /// Schedules an object's destruction as per C++ rules + /// Forwards to std::atexit + //////////////////////////////////////////////////////////////////////////////// + template <class T> + struct DefaultLifetime + { + static void ScheduleDestruction(T*, atexit_pfn_t pFun) + { std::atexit(pFun); } + + static void OnDeadReference() + { throw std::logic_error("Dead Reference Detected"); } + }; + + //////////////////////////////////////////////////////////////////////////////// + /// \struct PhoenixSingleton + /// + /// \ingroup LifetimeGroup + /// Implementation of the LifetimePolicy used by SingletonHolder + /// Schedules an object's destruction as per C++ rules, and it allows object + /// recreation by not throwing an exception from OnDeadReference + //////////////////////////////////////////////////////////////////////////////// + template <class T> + class PhoenixSingleton + { + public: + static void ScheduleDestruction(T*, atexit_pfn_t pFun) + { +#ifndef ATEXIT_FIXED + if (!destroyedOnce_) +#endif + std::atexit(pFun); + } + + static void OnDeadReference() + { +#ifndef ATEXIT_FIXED + destroyedOnce_ = true; +#endif + } + + private: +#ifndef ATEXIT_FIXED + static bool destroyedOnce_; +#endif + }; + +#ifndef ATEXIT_FIXED + template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false; +#endif + + //////////////////////////////////////////////////////////////////////////////// + // Copyright (c) 2004 by Curtis Krauskopf - curtis@decompile.com + /// + /// \struct DeletableSingleton + /// + /// \ingroup LifetimeGroup + /// + /// A DeletableSingleton allows the instantiated singleton to be + /// destroyed at any time. The singleton can be reinstantiated at + /// any time, even during program termination. + /// If the singleton exists when the program terminates, it will + /// be automatically deleted. + /// + /// \par Usage: + /// The singleton can be deleted manually: + /// + /// DeletableSingleton<MyClass>::GracefulDelete(); + //////////////////////////////////////////////////////////////////////////////// + template <class T> + class DeletableSingleton + { + public: + + static void ScheduleDestruction(T*, atexit_pfn_t pFun) + { + static bool firstPass = true; + isDead = false; + deleter = pFun; + if (firstPass || needCallback) + { + std::atexit(atexitCallback); + firstPass = false; + needCallback = false; + } + } + + static void OnDeadReference() + { + } + /// delete singleton object manually + static void GracefulDelete() + { + if (isDead) + return; + isDead = true; + deleter(); + } + + protected: + static atexit_pfn_t deleter; + static bool isDead; + static bool needCallback; + + static void atexitCallback() + { +#ifdef ATEXIT_FIXED + needCallback = true; +#else + needCallback = false; +#endif + GracefulDelete(); + } + }; + + template <class T> + atexit_pfn_t DeletableSingleton<T>::deleter = 0; + + template <class T> + bool DeletableSingleton<T>::isDead = true; + + template <class T> + bool DeletableSingleton<T>::needCallback = true; + + //////////////////////////////////////////////////////////////////////////////// + // class template Adapter + // Helper for SingletonWithLongevity below + //////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class T> + struct Adapter + { + void operator()(T*) { return pFun_(); } + atexit_pfn_t pFun_; + }; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \struct SingletonWithLongevity + /// + /// \ingroup LifetimeGroup + /// Implementation of the LifetimePolicy used by SingletonHolder + /// Schedules an object's destruction in order of their longevities + /// Assumes a visible function GetLongevity(T*) that returns the longevity of the + /// object. + //////////////////////////////////////////////////////////////////////////////// + template <class T> + class SingletonWithLongevity + { + public: + static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun) + { + Private::Adapter<T> adapter = { pFun }; + SetLongevity(pObj, GetLongevity(pObj), adapter); + } + + static void OnDeadReference() + { throw std::logic_error("Dead Reference Detected"); } + }; + + //////////////////////////////////////////////////////////////////////////////// + /// \struct NoDestroy + /// + /// \ingroup LifetimeGroup + /// Implementation of the LifetimePolicy used by SingletonHolder + /// Never destroys the object + //////////////////////////////////////////////////////////////////////////////// + template <class T> + struct NoDestroy + { + static void ScheduleDestruction(T*, atexit_pfn_t) + {} + + static void OnDeadReference() + {} + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// \defgroup LongevityLifetimeGroup LongevityLifetime + /// \ingroup LifetimeGroup + /// + /// \namespace LongevityLifetime + /// + /// \ingroup LongevityLifetimeGroup + /// \brief In this namespace are special lifetime policies to manage lifetime + /// dependencies. + //////////////////////////////////////////////////////////////////////////////// + namespace LongevityLifetime + { + //////////////////////////////////////////////////////////////////////////////// + /// \struct SingletonFixedLongevity + /// + /// \ingroup LongevityLifetimeGroup + /// Add your own lifetimes into the namespace 'LongevityLifetime' + /// with your prefered lifetime by adding a struct like this: + /// + /// template<class T> + /// struct MyLifetime : SingletonFixedLongevity< MyLifetimeNumber ,T> {} + //////////////////////////////////////////////////////////////////////////////// + template <unsigned int Longevity, class T> + class SingletonFixedLongevity + { + public: + virtual ~SingletonFixedLongevity() {} + + static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun) + { + Private::Adapter<T> adapter = { pFun }; + SetLongevity(pObj, Longevity , adapter); + } + + static void OnDeadReference() + { throw std::logic_error("Dead Reference Detected"); } + }; + + /// \struct DieLast + /// \ingroup LongevityLifetimeGroup + /// \brief Longest possible SingletonWithLongevity lifetime: 0xFFFFFFFF + template <class T> + struct DieLast : SingletonFixedLongevity<0xFFFFFFFF ,T> + {}; + + /// \struct DieDirectlyBeforeLast + /// \ingroup LongevityLifetimeGroup + /// \brief Lifetime is a one less than DieLast: 0xFFFFFFFF-1 + template <class T> + struct DieDirectlyBeforeLast : SingletonFixedLongevity<0xFFFFFFFF-1 ,T> + {}; + + /// \struct DieFirst + /// \ingroup LongevityLifetimeGroup + /// \brief Shortest possible SingletonWithLongevity lifetime: 0 + template <class T> + struct DieFirst : SingletonFixedLongevity<0,T> + {}; + + }//namespace LongevityLifetime + + //////////////////////////////////////////////////////////////////////////////// + /// \class FollowIntoDeath + /// + /// \ingroup LifetimeGroup + /// + /// Lifetime policyfor the SingletonHolder tempalte. + /// Followers will die after the master dies Followers will not die, if + /// - master never dies (NoDestroy policy) + /// - master never created + /// - master dies not in the function registered with atexit + /// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete) + /// + /// \par Usage: + /// + /// Lifetimes of the master and the follower singletons, e.g. with a M and a F class: + /// \code SingletonHolder< M , FollowIntoDeath::With<DefaultLifetime>::AsMasterLifetime > MasterSingleton; \endcode + /// \code SingletonHolder< F , CreateUsingNew, FollowIntoDeath::AfterMaster< MasterSingleton >::IsDestroyed > FollowerSingleton \endcode + //////////////////////////////////////////////////////////////////////////////// + class FollowIntoDeath + { + template<class T> + class Followers + { + typedef std::vector<atexit_pfn_t> Container; + typedef typename Container::iterator iterator; + static Container* followers_; + + public: + static void Init() + { + static bool done = false; + if(!done) + { + followers_ = new Container; + done = true; + } + } + + static void AddFollower(atexit_pfn_t ae) + { + Init(); + followers_->push_back(ae); + } + + static void DestroyFollowers() + { + Init(); + for(iterator it = followers_->begin();it != followers_->end();++it) + (*it)(); + delete followers_; + } + }; + + public: + + /// \struct With + /// Template for the master + /// \param Lifetime Lifetime policy for the master + template<template <class> class Lifetime> + struct With + { + /// \struct AsMasterLifetime + /// Policy for master + template<class Master> + struct AsMasterLifetime + { + static void ScheduleDestruction(Master* pObj, atexit_pfn_t pFun) + { + Followers<Master>::Init(); + Lifetime<Master>::ScheduleDestruction(pObj, pFun); + + // use same policy for the followers and force a new + // template instantiation, this adds a additional atexit entry + // does not work with SetLonlevity, but there you can control + // the lifetime with the GetLongevity function. + Lifetime<Followers<Master> >::ScheduleDestruction(0,Followers<Master>::DestroyFollowers); + } + + static void OnDeadReference() + { + throw std::logic_error("Dead Reference Detected"); + } + }; + }; + + /// \struct AfterMaster + /// Template for the follower + /// \param Master Master to follow into death + template<class Master> + struct AfterMaster + { + /// \struct IsDestroyed + /// Policy for followers + template<class F> + struct IsDestroyed + { + static void ScheduleDestruction(F*, atexit_pfn_t pFun) + { + Followers<Master>::AddFollower(pFun); + } + + static void OnDeadReference() + { + throw std::logic_error("Dead Reference Detected"); + } + }; + }; + }; + + template<class T> + typename FollowIntoDeath::Followers<T>::Container* + FollowIntoDeath::Followers<T>::followers_ = 0; + + + + //////////////////////////////////////////////////////////////////////////////// + /// \class SingletonHolder + /// + /// \ingroup SingletonGroup + /// + /// Provides Singleton amenities for a type T + /// To protect that type from spurious instantiations, + /// you have to protect it yourself. + /// + /// \param CreationPolicy Creation policy, default: CreateUsingNew + /// \param LifetimePolicy Lifetime policy, default: DefaultLifetime, + /// \param ThreadingModel Threading policy, + /// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL + //////////////////////////////////////////////////////////////////////////////// + template + < + typename T, + template <class> class CreationPolicy = CreateUsingNew, + template <class> class LifetimePolicy = DefaultLifetime, + template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, + class MutexPolicy = LOKI_DEFAULT_MUTEX + > + class SingletonHolder + { + public: + + /// Type of the singleton object + typedef T ObjectType; + + /// Returns a reference to singleton object + static T& Instance(); + + private: + // Helpers + static void MakeInstance(); + static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton(); + + // Protection + SingletonHolder(); + + // Data + typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType; + static PtrInstanceType pInstance_; + static bool destroyed_; + }; + + //////////////////////////////////////////////////////////////////////////////// + // SingletonHolder's data + //////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + template <class> class C, + template <class> class L, + template <class, class> class M, + class X + > + typename SingletonHolder<T, C, L, M, X>::PtrInstanceType + SingletonHolder<T, C, L, M, X>::pInstance_ = 0; + + template + < + class T, + template <class> class C, + template <class> class L, + template <class, class> class M, + class X + > + bool SingletonHolder<T, C, L, M, X>::destroyed_ = false; + + //////////////////////////////////////////////////////////////////////////////// + // SingletonHolder::Instance + //////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + template <class> class CreationPolicy, + template <class> class LifetimePolicy, + template <class, class> class ThreadingModel, + class MutexPolicy + > + inline T& SingletonHolder<T, CreationPolicy, + LifetimePolicy, ThreadingModel, MutexPolicy>::Instance() + { + if (!pInstance_) + { + MakeInstance(); + } + return *pInstance_; + } + + //////////////////////////////////////////////////////////////////////////////// + // SingletonHolder::MakeInstance (helper for Instance) + //////////////////////////////////////////////////////////////////////////////// + + template + < + class T, + template <class> class CreationPolicy, + template <class> class LifetimePolicy, + template <class, class> class ThreadingModel, + class MutexPolicy + > + void SingletonHolder<T, CreationPolicy, + LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance() + { + typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard; + (void)guard; + + if (!pInstance_) + { + if (destroyed_) + { + destroyed_ = false; + LifetimePolicy<T>::OnDeadReference(); + } + pInstance_ = CreationPolicy<T>::Create(); + LifetimePolicy<T>::ScheduleDestruction(pInstance_, + &DestroySingleton); + } + } + + template + < + class T, + template <class> class CreationPolicy, + template <class> class L, + template <class, class> class M, + class X + > + void LOKI_C_CALLING_CONVENTION_QUALIFIER + SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton() + { + assert(!destroyed_); + CreationPolicy<T>::Destroy(pInstance_); + pInstance_ = 0; + destroyed_ = true; + } + + + //////////////////////////////////////////////////////////////////////////////// + /// \class Singleton + /// + /// \ingroup SingletonGroup + /// + /// Convenience template to implement a getter function for a singleton object. + /// Often needed in a shared library which hosts singletons. + /// + /// \par Usage + /// + /// see test/SingletonDll + /// + //////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_SINGLETON_EXPORT +#define LOKI_SINGLETON_EXPORT +#endif + + template<class T> + class LOKI_SINGLETON_EXPORT Singleton + { + public: + static T& Instance(); + }; + +} // namespace Loki + + +/// \def LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) +/// Convenience macro for the definition of the static Instance member function +/// Put this macro called with a SingletonHolder typedef into your cpp file. + +#define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) \ +namespace Loki \ +{ \ + template<> \ + SHOLDER::ObjectType& Singleton<SHOLDER::ObjectType>::Instance() \ + { \ + return SHOLDER::Instance(); \ + } \ +} + + +#endif // end file guardian + diff --git a/shared/loki/SmallObj.cpp b/shared/loki/SmallObj.cpp new file mode 100644 index 00000000..a2911bb1 --- /dev/null +++ b/shared/loki/SmallObj.cpp @@ -0,0 +1,1226 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// $Id: SmallObj.cpp 823 2007-05-08 10:48:40Z lfittl $ + + +#include <loki/SmallObj.h> + +#include <cassert> +#include <climits> +#include <vector> +#include <bitset> + +//#define DO_EXTRA_LOKI_TESTS +//#define USE_NEW_TO_ALLOCATE +//#define LOKI_CHECK_FOR_CORRUPTION + +#ifdef DO_EXTRA_LOKI_TESTS + #include <iostream> +#endif + +namespace Loki +{ + + /** @struct Chunk + @ingroup SmallObjectGroupInternal + Contains info about each allocated Chunk - which is a collection of + contiguous blocks. Each block is the same size, as specified by the + FixedAllocator. The number of blocks in a Chunk depends upon page size. + This is a POD-style struct with value-semantics. All functions and data + are private so that they can not be changed by anything other than the + FixedAllocator which owns the Chunk. + + @par Minimal Interface + For the sake of runtime efficiency, no constructor, destructor, or + copy-assignment operator is defined. The inline functions made by the + compiler should be sufficient, and perhaps faster than hand-crafted + functions. The lack of these functions allows vector to create and copy + Chunks as needed without overhead. The Init and Release functions do + what the default constructor and destructor would do. A Chunk is not in + a usable state after it is constructed and before calling Init. Nor is + a Chunk usable after Release is called, but before the destructor. + + @par Efficiency + Down near the lowest level of the allocator, runtime efficiencies trump + almost all other considerations. Each function does the minimum required + of it. All functions should execute in constant time to prevent higher- + level code from unwittingly using a version of Shlemiel the Painter's + Algorithm. + + @par Stealth Indexes + The first char of each empty block contains the index of the next empty + block. These stealth indexes form a singly-linked list within the blocks. + A Chunk is corrupt if this singly-linked list has a loop or is shorter + than blocksAvailable_. Much of the allocator's time and space efficiency + comes from how these stealth indexes are implemented. + */ + class Chunk + { + private: + friend class FixedAllocator; + + /** Initializes a just-constructed Chunk. + @param blockSize Number of bytes per block. + @param blocks Number of blocks per Chunk. + @return True for success, false for failure. + */ + bool Init( std::size_t blockSize, unsigned char blocks ); + + /** Allocate a block within the Chunk. Complexity is always O(1), and + this will never throw. Does not actually "allocate" by calling + malloc, new, or any other function, but merely adjusts some internal + indexes to indicate an already allocated block is no longer available. + @return Pointer to block within Chunk. + */ + void * Allocate( std::size_t blockSize ); + + /** Deallocate a block within the Chunk. Complexity is always O(1), and + this will never throw. For efficiency, this assumes the address is + within the block and aligned along the correct byte boundary. An + assertion checks the alignment, and a call to HasBlock is done from + within VicinityFind. Does not actually "deallocate" by calling free, + delete, or other function, but merely adjusts some internal indexes to + indicate a block is now available. + */ + void Deallocate( void * p, std::size_t blockSize ); + + /** Resets the Chunk back to pristine values. The available count is + set back to zero, and the first available index is set to the zeroth + block. The stealth indexes inside each block are set to point to the + next block. This assumes the Chunk's data was already using Init. + */ + void Reset( std::size_t blockSize, unsigned char blocks ); + + /// Releases the allocated block of memory. + void Release(); + + /** Determines if the Chunk has been corrupted. + @param numBlocks Total # of blocks in the Chunk. + @param blockSize # of bytes in each block. + @param checkIndexes True if caller wants to check indexes of available + blocks for corruption. If false, then caller wants to skip some + tests tests just to run faster. (Debug version does more checks, but + release version runs faster.) + @return True if Chunk is corrupt. + */ + bool IsCorrupt( unsigned char numBlocks, std::size_t blockSize, + bool checkIndexes ) const; + + /** Determines if block is available. + @param p Address of block managed by Chunk. + @param numBlocks Total # of blocks in the Chunk. + @param blockSize # of bytes in each block. + @return True if block is available, else false if allocated. + */ + bool IsBlockAvailable( void * p, unsigned char numBlocks, + std::size_t blockSize ) const; + + /// Returns true if block at address P is inside this Chunk. + inline bool HasBlock( void * p, std::size_t chunkLength ) const + { + unsigned char * pc = static_cast< unsigned char * >( p ); + return ( pData_ <= pc ) && ( pc < pData_ + chunkLength ); + } + + inline bool HasAvailable( unsigned char numBlocks ) const + { return ( blocksAvailable_ == numBlocks ); } + + inline bool IsFilled( void ) const + { return ( 0 == blocksAvailable_ ); } + + /// Pointer to array of allocated blocks. + unsigned char * pData_; + /// Index of first empty block. + unsigned char firstAvailableBlock_; + /// Count of empty blocks. + unsigned char blocksAvailable_; + }; + + /** @class FixedAllocator + @ingroup SmallObjectGroupInternal + Offers services for allocating fixed-sized objects. It has a container + of "containers" of fixed-size blocks. The outer container has all the + Chunks. The inner container is a Chunk which owns some blocks. + + @par Class Level Invariants + - There is always either zero or one Chunk which is empty. + - If this has no empty Chunk, then emptyChunk_ is NULL. + - If this has an empty Chunk, then emptyChunk_ points to it. + - If the Chunk container is empty, then deallocChunk_ and allocChunk_ + are NULL. + - If the Chunk container is not-empty, then deallocChunk_ and allocChunk_ + are either NULL or point to Chunks within the container. + - allocChunk_ will often point to the last Chunk in the container since + it was likely allocated most recently, and therefore likely to have an + available block. + */ + class FixedAllocator + { + private: + + /** Deallocates the block at address p, and then handles the internal + bookkeeping needed to maintain class invariants. This assumes that + deallocChunk_ points to the correct chunk. + */ + void DoDeallocate( void * p ); + + /** Creates an empty Chunk and adds it to the end of the ChunkList. + All calls to the lower-level memory allocation functions occur inside + this function, and so the only try-catch block is inside here. + @return true for success, false for failure. + */ + bool MakeNewChunk( void ); + + /** Finds the Chunk which owns the block at address p. It starts at + deallocChunk_ and searches in both forwards and backwards directions + from there until it finds the Chunk which owns p. This algorithm + should find the Chunk quickly if it is deallocChunk_ or is close to it + in the Chunks container. This goes both forwards and backwards since + that works well for both same-order and opposite-order deallocations. + (Same-order = objects are deallocated in the same order in which they + were allocated. Opposite order = objects are deallocated in a last to + first order. Complexity is O(C) where C is count of all Chunks. This + never throws. + @return Pointer to Chunk that owns p, or NULL if no owner found. + */ + Chunk * VicinityFind( void * p ) const; + + /// Not implemented. + FixedAllocator(const FixedAllocator&); + /// Not implemented. + FixedAllocator& operator=(const FixedAllocator&); + + /// Type of container used to hold Chunks. + typedef std::vector< Chunk > Chunks; + /// Iterator through container of Chunks. + typedef Chunks::iterator ChunkIter; + /// Iterator through const container of Chunks. + typedef Chunks::const_iterator ChunkCIter; + + /// Fewest # of objects managed by a Chunk. + static unsigned char MinObjectsPerChunk_; + + /// Most # of objects managed by a Chunk - never exceeds UCHAR_MAX. + static unsigned char MaxObjectsPerChunk_; + + /// Number of bytes in a single block within a Chunk. + std::size_t blockSize_; + /// Number of blocks managed by each Chunk. + unsigned char numBlocks_; + + /// Container of Chunks. + Chunks chunks_; + /// Pointer to Chunk used for last or next allocation. + Chunk * allocChunk_; + /// Pointer to Chunk used for last or next deallocation. + Chunk * deallocChunk_; + /// Pointer to the only empty Chunk if there is one, else NULL. + Chunk * emptyChunk_; + + public: + /// Create a FixedAllocator which manages blocks of 'blockSize' size. + FixedAllocator(); + + /// Destroy the FixedAllocator and release all its Chunks. + ~FixedAllocator(); + + /// Initializes a FixedAllocator by calculating # of blocks per Chunk. + void Initialize( std::size_t blockSize, std::size_t pageSize ); + + /** Returns pointer to allocated memory block of fixed size - or NULL + if it failed to allocate. + */ + void * Allocate( void ); + + /** Deallocate a memory block previously allocated with Allocate. If + the block is not owned by this FixedAllocator, it returns false so + that SmallObjAllocator can call the default deallocator. If the + block was found, this returns true. + */ + bool Deallocate( void * p, Chunk * hint ); + + /// Returns block size with which the FixedAllocator was initialized. + inline std::size_t BlockSize() const { return blockSize_; } + + /** Releases the memory used by the empty Chunk. This will take + constant time under any situation. + @return True if empty chunk found and released, false if none empty. + */ + bool TrimEmptyChunk( void ); + + /** Releases unused spots from ChunkList. This takes constant time + with respect to # of Chunks, but actual time depends on underlying + memory allocator. + @return False if no unused spots, true if some found and released. + */ + bool TrimChunkList( void ); + + /** Returns count of empty Chunks held by this allocator. Complexity + is O(C) where C is the total number of Chunks - empty or used. + */ + std::size_t CountEmptyChunks( void ) const; + + /** Determines if FixedAllocator is corrupt. Checks data members to + see if any have erroneous values, or violate class invariants. It + also checks if any Chunk is corrupt. Complexity is O(C) where C is + the number of Chunks. If any data is corrupt, this will return true + in release mode, or assert in debug mode. + */ + bool IsCorrupt( void ) const; + + /** Returns true if the block at address p is within a Chunk owned by + this FixedAllocator. Complexity is O(C) where C is the total number + of Chunks - empty or used. + */ + const Chunk * HasBlock( void * p ) const; + inline Chunk * HasBlock( void * p ) + { + return const_cast< Chunk * >( + const_cast< const FixedAllocator * >( this )->HasBlock( p ) ); + } + + }; + + unsigned char FixedAllocator::MinObjectsPerChunk_ = 8; + unsigned char FixedAllocator::MaxObjectsPerChunk_ = UCHAR_MAX; + +// Chunk::Init ---------------------------------------------------------------- + +bool Chunk::Init( std::size_t blockSize, unsigned char blocks ) +{ + assert(blockSize > 0); + assert(blocks > 0); + // Overflow check + const std::size_t allocSize = blockSize * blocks; + assert( allocSize / blockSize == blocks); + +#ifdef USE_NEW_TO_ALLOCATE + // If this new operator fails, it will throw, and the exception will get + // caught one layer up. + pData_ = static_cast< unsigned char * >( ::operator new ( allocSize ) ); +#else + // malloc can't throw, so its only way to indicate an error is to return + // a NULL pointer, so we have to check for that. + pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) ); + if ( NULL == pData_ ) return false; +#endif + + Reset( blockSize, blocks ); + return true; +} + +// Chunk::Reset --------------------------------------------------------------- + +void Chunk::Reset(std::size_t blockSize, unsigned char blocks) +{ + assert(blockSize > 0); + assert(blocks > 0); + // Overflow check + assert((blockSize * blocks) / blockSize == blocks); + + firstAvailableBlock_ = 0; + blocksAvailable_ = blocks; + + unsigned char i = 0; + for ( unsigned char * p = pData_; i != blocks; p += blockSize ) + { + *p = ++i; + } +} + +// Chunk::Release ------------------------------------------------------------- + +void Chunk::Release() +{ + assert( NULL != pData_ ); +#ifdef USE_NEW_TO_ALLOCATE + ::operator delete ( pData_ ); +#else + ::std::free( static_cast< void * >( pData_ ) ); +#endif +} + +// Chunk::Allocate ------------------------------------------------------------ + +void* Chunk::Allocate(std::size_t blockSize) +{ + if ( IsFilled() ) return NULL; + + assert((firstAvailableBlock_ * blockSize) / blockSize == + firstAvailableBlock_); + unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize); + firstAvailableBlock_ = *pResult; + --blocksAvailable_; + + return pResult; +} + +// Chunk::Deallocate ---------------------------------------------------------- + +void Chunk::Deallocate(void* p, std::size_t blockSize) +{ + assert(p >= pData_); + + unsigned char* toRelease = static_cast<unsigned char*>(p); + // Alignment check + assert((toRelease - pData_) % blockSize == 0); + unsigned char index = static_cast< unsigned char >( + ( toRelease - pData_ ) / blockSize); + +#if defined(DEBUG) || defined(_DEBUG) + // Check if block was already deleted. Attempting to delete the same + // block more than once causes Chunk's linked-list of stealth indexes to + // become corrupt. And causes count of blocksAvailable_ to be wrong. + if ( 0 < blocksAvailable_ ) + assert( firstAvailableBlock_ != index ); +#endif + + *toRelease = firstAvailableBlock_; + firstAvailableBlock_ = index; + // Truncation check + assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize); + + ++blocksAvailable_; +} + +// Chunk::IsCorrupt ----------------------------------------------------------- + +bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize, + bool checkIndexes ) const +{ + + if ( numBlocks < blocksAvailable_ ) + { + // Contents at this Chunk corrupted. This might mean something has + // overwritten memory owned by the Chunks container. + assert( false ); + return true; + } + if ( IsFilled() ) + // Useless to do further corruption checks if all blocks allocated. + return false; + unsigned char index = firstAvailableBlock_; + if ( numBlocks <= index ) + { + // Contents at this Chunk corrupted. This might mean something has + // overwritten memory owned by the Chunks container. + assert( false ); + return true; + } + if ( !checkIndexes ) + // Caller chose to skip more complex corruption tests. + return false; + + /* If the bit at index was set in foundBlocks, then the stealth index was + found on the linked-list. + */ + std::bitset< UCHAR_MAX > foundBlocks; + unsigned char * nextBlock = NULL; + + /* The loop goes along singly linked-list of stealth indexes and makes sure + that each index is within bounds (0 <= index < numBlocks) and that the + index was not already found while traversing the linked-list. The linked- + list should have exactly blocksAvailable_ nodes, so the for loop will not + check more than blocksAvailable_. This loop can't check inside allocated + blocks for corruption since such blocks are not within the linked-list. + Contents of allocated blocks are not changed by Chunk. + + Here are the types of corrupted link-lists which can be verified. The + corrupt index is shown with asterisks in each example. + + Type 1: Index is too big. + numBlocks == 64 + blocksAvailable_ == 7 + firstAvailableBlock_ -> 17 -> 29 -> *101* + There should be no indexes which are equal to or larger than the total + number of blocks. Such an index would refer to a block beyond the + Chunk's allocated domain. + + Type 2: Index is repeated. + numBlocks == 64 + blocksAvailable_ == 5 + firstAvailableBlock_ -> 17 -> 29 -> 53 -> *17* -> 29 -> 53 ... + No index should be repeated within the linked-list since that would + indicate the presence of a loop in the linked-list. + */ + for ( unsigned char cc = 0; ; ) + { + nextBlock = pData_ + ( index * blockSize ); + foundBlocks.set( index, true ); + ++cc; + if ( cc >= blocksAvailable_ ) + // Successfully counted off number of nodes in linked-list. + break; + index = *nextBlock; + if ( numBlocks <= index ) + { + /* This catches Type 1 corruptions as shown in above comments. + This implies that a block was corrupted due to a stray pointer + or an operation on a nearby block overran the size of the block. + */ + assert( false ); + return true; + } + if ( foundBlocks.test( index ) ) + { + /* This catches Type 2 corruptions as shown in above comments. + This implies that a block was corrupted due to a stray pointer + or an operation on a nearby block overran the size of the block. + Or perhaps the program tried to delete a block more than once. + */ + assert( false ); + return true; + } + } + if ( foundBlocks.count() != blocksAvailable_ ) + { + /* This implies that the singly-linked-list of stealth indexes was + corrupted. Ideally, this should have been detected within the loop. + */ + assert( false ); + return true; + } + + return false; +} + +// Chunk::IsBlockAvailable ---------------------------------------------------- + +bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks, + std::size_t blockSize ) const +{ + (void) numBlocks; + + if ( IsFilled() ) + return false; + + unsigned char * place = static_cast< unsigned char * >( p ); + // Alignment check + assert( ( place - pData_ ) % blockSize == 0 ); + unsigned char blockIndex = static_cast< unsigned char >( + ( place - pData_ ) / blockSize ); + + unsigned char index = firstAvailableBlock_; + assert( numBlocks > index ); + if ( index == blockIndex ) + return true; + + /* If the bit at index was set in foundBlocks, then the stealth index was + found on the linked-list. + */ + std::bitset< UCHAR_MAX > foundBlocks; + unsigned char * nextBlock = NULL; + for ( unsigned char cc = 0; ; ) + { + nextBlock = pData_ + ( index * blockSize ); + foundBlocks.set( index, true ); + ++cc; + if ( cc >= blocksAvailable_ ) + // Successfully counted off number of nodes in linked-list. + break; + index = *nextBlock; + if ( index == blockIndex ) + return true; + assert( numBlocks > index ); + assert( !foundBlocks.test( index ) ); + } + + return false; +} + +// FixedAllocator::FixedAllocator --------------------------------------------- + +FixedAllocator::FixedAllocator() + : blockSize_( 0 ) + , numBlocks_( 0 ) + , chunks_( 0 ) + , allocChunk_( NULL ) + , deallocChunk_( NULL ) + , emptyChunk_( NULL ) +{ +} + +// FixedAllocator::~FixedAllocator -------------------------------------------- + +FixedAllocator::~FixedAllocator() +{ +#ifdef DO_EXTRA_LOKI_TESTS + TrimEmptyChunk(); + assert( chunks_.empty() && "Memory leak detected!" ); +#endif + for ( ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i ) + i->Release(); +} + +// FixedAllocator::Initialize ------------------------------------------------- + +void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize ) +{ + assert( blockSize > 0 ); + assert( pageSize >= blockSize ); + blockSize_ = blockSize; + + std::size_t numBlocks = pageSize / blockSize; + if ( numBlocks > MaxObjectsPerChunk_ ) numBlocks = MaxObjectsPerChunk_; + else if ( numBlocks < MinObjectsPerChunk_ ) numBlocks = MinObjectsPerChunk_; + + numBlocks_ = static_cast<unsigned char>(numBlocks); + assert(numBlocks_ == numBlocks); +} + +// FixedAllocator::CountEmptyChunks ------------------------------------------- + +std::size_t FixedAllocator::CountEmptyChunks( void ) const +{ +#ifdef DO_EXTRA_LOKI_TESTS + // This code is only used for specialized tests of the allocator. + // It is #ifdef-ed so that its O(C) complexity does not overwhelm the + // functions which call it. + std::size_t count = 0; + for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it ) + { + const Chunk & chunk = *it; + if ( chunk.HasAvailable( numBlocks_ ) ) + ++count; + } + return count; +#else + return ( NULL == emptyChunk_ ) ? 0 : 1; +#endif +} + +// FixedAllocator::IsCorrupt -------------------------------------------------- + +bool FixedAllocator::IsCorrupt( void ) const +{ + const bool isEmpty = chunks_.empty(); + ChunkCIter start( chunks_.begin() ); + ChunkCIter last( chunks_.end() ); + const size_t emptyChunkCount = CountEmptyChunks(); + + if ( isEmpty ) + { + if ( start != last ) + { + assert( false ); + return true; + } + if ( 0 < emptyChunkCount ) + { + assert( false ); + return true; + } + if ( NULL != deallocChunk_ ) + { + assert( false ); + return true; + } + if ( NULL != allocChunk_ ) + { + assert( false ); + return true; + } + if ( NULL != emptyChunk_ ) + { + assert( false ); + return true; + } + } + + else + { + const Chunk * front = &chunks_.front(); + const Chunk * back = &chunks_.back(); + if ( start >= last ) + { + assert( false ); + return true; + } + if ( back < deallocChunk_ ) + { + assert( false ); + return true; + } + if ( back < allocChunk_ ) + { + assert( false ); + return true; + } + if ( front > deallocChunk_ ) + { + assert( false ); + return true; + } + if ( front > allocChunk_ ) + { + assert( false ); + return true; + } + + switch ( emptyChunkCount ) + { + case 0: + if ( emptyChunk_ != NULL ) + { + assert( false ); + return true; + } + break; + case 1: + if ( emptyChunk_ == NULL ) + { + assert( false ); + return true; + } + if ( back < emptyChunk_ ) + { + assert( false ); + return true; + } + if ( front > emptyChunk_ ) + { + assert( false ); + return true; + } + if ( !emptyChunk_->HasAvailable( numBlocks_ ) ) + { + // This may imply somebody tried to delete a block twice. + assert( false ); + return true; + } + break; + default: + assert( false ); + return true; + } + for ( ChunkCIter it( start ); it != last; ++it ) + { + const Chunk & chunk = *it; + if ( chunk.IsCorrupt( numBlocks_, blockSize_, true ) ) + return true; + } + } + + return false; +} + +// FixedAllocator::HasBlock --------------------------------------------------- + +const Chunk * FixedAllocator::HasBlock( void * p ) const +{ + const std::size_t chunkLength = numBlocks_ * blockSize_; + for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it ) + { + const Chunk & chunk = *it; + if ( chunk.HasBlock( p, chunkLength ) ) + return &chunk; + } + return NULL; +} + +// FixedAllocator::TrimEmptyChunk --------------------------------------------- + +bool FixedAllocator::TrimEmptyChunk( void ) +{ + // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. + assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + if ( NULL == emptyChunk_ ) return false; + + // If emptyChunk_ points to valid Chunk, then chunk list is not empty. + assert( !chunks_.empty() ); + // And there should be exactly 1 empty Chunk. + assert( 1 == CountEmptyChunks() ); + + Chunk * lastChunk = &chunks_.back(); + if ( lastChunk != emptyChunk_ ) + std::swap( *emptyChunk_, *lastChunk ); + assert( lastChunk->HasAvailable( numBlocks_ ) ); + lastChunk->Release(); + chunks_.pop_back(); + + if ( chunks_.empty() ) + { + allocChunk_ = NULL; + deallocChunk_ = NULL; + } + else + { + if ( deallocChunk_ == emptyChunk_ ) + { + deallocChunk_ = &chunks_.front(); + assert( deallocChunk_->blocksAvailable_ < numBlocks_ ); + } + if ( allocChunk_ == emptyChunk_ ) + { + allocChunk_ = &chunks_.back(); + assert( allocChunk_->blocksAvailable_ < numBlocks_ ); + } + } + + emptyChunk_ = NULL; + assert( 0 == CountEmptyChunks() ); + + return true; +} + +// FixedAllocator::TrimChunkList ---------------------------------------------- + +bool FixedAllocator::TrimChunkList( void ) +{ + if ( chunks_.empty() ) + { + assert( NULL == allocChunk_ ); + assert( NULL == deallocChunk_ ); + } + + if ( chunks_.size() == chunks_.capacity() ) + return false; + // Use the "make-a-temp-and-swap" trick to remove excess capacity. + Chunks( chunks_ ).swap( chunks_ ); + + return true; +} + +// FixedAllocator::MakeNewChunk ----------------------------------------------- + +bool FixedAllocator::MakeNewChunk( void ) +{ + bool allocated = false; + try + { + std::size_t size = chunks_.size(); + // Calling chunks_.reserve *before* creating and initializing the new + // Chunk means that nothing is leaked by this function in case an + // exception is thrown from reserve. + if ( chunks_.capacity() == size ) + { + if ( 0 == size ) size = 4; + chunks_.reserve( size * 2 ); + } + Chunk newChunk; + allocated = newChunk.Init( blockSize_, numBlocks_ ); + if ( allocated ) + chunks_.push_back( newChunk ); + } + catch ( ... ) + { + allocated = false; + } + if ( !allocated ) return false; + + allocChunk_ = &chunks_.back(); + deallocChunk_ = &chunks_.front(); + return true; +} + +// FixedAllocator::Allocate --------------------------------------------------- + +void * FixedAllocator::Allocate( void ) +{ + // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. + assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( CountEmptyChunks() < 2 ); + + if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() ) + { + if ( NULL != emptyChunk_ ) + { + allocChunk_ = emptyChunk_; + emptyChunk_ = NULL; + } + else + { + for ( ChunkIter i( chunks_.begin() ); ; ++i ) + { + if ( chunks_.end() == i ) + { + if ( !MakeNewChunk() ) + return NULL; + break; + } + if ( !i->IsFilled() ) + { + allocChunk_ = &*i; + break; + } + } + } + } + else if ( allocChunk_ == emptyChunk_) + // detach emptyChunk_ from allocChunk_, because after + // calling allocChunk_->Allocate(blockSize_); the chunk + // is no longer empty. + emptyChunk_ = NULL; + + assert( allocChunk_ != NULL ); + assert( !allocChunk_->IsFilled() ); + void * place = allocChunk_->Allocate( blockSize_ ); + + // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. + assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + assert( CountEmptyChunks() < 2 ); +#ifdef LOKI_CHECK_FOR_CORRUPTION + if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_, true ) ) + { + assert( false ); + return NULL; + } +#endif + + return place; +} + +// FixedAllocator::Deallocate ------------------------------------------------- + +bool FixedAllocator::Deallocate( void * p, Chunk * hint ) +{ + assert(!chunks_.empty()); + assert(&chunks_.front() <= deallocChunk_); + assert(&chunks_.back() >= deallocChunk_); + assert( &chunks_.front() <= allocChunk_ ); + assert( &chunks_.back() >= allocChunk_ ); + assert( CountEmptyChunks() < 2 ); + + Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint; + if ( NULL == foundChunk ) + return false; + + assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) ); +#ifdef LOKI_CHECK_FOR_CORRUPTION + if ( foundChunk->IsCorrupt( numBlocks_, blockSize_, true ) ) + { + assert( false ); + return false; + } + if ( foundChunk->IsBlockAvailable( p, numBlocks_, blockSize_ ) ) + { + assert( false ); + return false; + } +#endif + deallocChunk_ = foundChunk; + DoDeallocate(p); + assert( CountEmptyChunks() < 2 ); + + return true; +} + +// FixedAllocator::VicinityFind ----------------------------------------------- + +Chunk * FixedAllocator::VicinityFind( void * p ) const +{ + if ( chunks_.empty() ) return NULL; + assert(deallocChunk_); + + const std::size_t chunkLength = numBlocks_ * blockSize_; + Chunk * lo = deallocChunk_; + Chunk * hi = deallocChunk_ + 1; + const Chunk * loBound = &chunks_.front(); + const Chunk * hiBound = &chunks_.back() + 1; + + // Special case: deallocChunk_ is the last in the array + if (hi == hiBound) hi = NULL; + + for (;;) + { + if (lo) + { + if ( lo->HasBlock( p, chunkLength ) ) return lo; + if ( lo == loBound ) + { + lo = NULL; + if ( NULL == hi ) break; + } + else --lo; + } + + if (hi) + { + if ( hi->HasBlock( p, chunkLength ) ) return hi; + if ( ++hi == hiBound ) + { + hi = NULL; + if ( NULL == lo ) break; + } + } + } + + return NULL; +} + +// FixedAllocator::DoDeallocate ----------------------------------------------- + +void FixedAllocator::DoDeallocate(void* p) +{ + // Show that deallocChunk_ really owns the block at address p. + assert( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) ); + // Either of the next two assertions may fail if somebody tries to + // delete the same block twice. + assert( emptyChunk_ != deallocChunk_ ); + assert( !deallocChunk_->HasAvailable( numBlocks_ ) ); + // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. + assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); + + // call into the chunk, will adjust the inner list but won't release memory + deallocChunk_->Deallocate(p, blockSize_); + + if ( deallocChunk_->HasAvailable( numBlocks_ ) ) + { + assert( emptyChunk_ != deallocChunk_ ); + // deallocChunk_ is empty, but a Chunk is only released if there are 2 + // empty chunks. Since emptyChunk_ may only point to a previously + // cleared Chunk, if it points to something else besides deallocChunk_, + // then FixedAllocator currently has 2 empty Chunks. + if ( NULL != emptyChunk_ ) + { + // If last Chunk is empty, just change what deallocChunk_ + // points to, and release the last. Otherwise, swap an empty + // Chunk with the last, and then release it. + Chunk * lastChunk = &chunks_.back(); + if ( lastChunk == deallocChunk_ ) + deallocChunk_ = emptyChunk_; + else if ( lastChunk != emptyChunk_ ) + std::swap( *emptyChunk_, *lastChunk ); + assert( lastChunk->HasAvailable( numBlocks_ ) ); + lastChunk->Release(); + chunks_.pop_back(); + if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() ) + allocChunk_ = deallocChunk_; + } + emptyChunk_ = deallocChunk_; + } + + // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk. + assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) ); +} + +// GetOffset ------------------------------------------------------------------ +/// @ingroup SmallObjectGroupInternal +/// Calculates index into array where a FixedAllocator of numBytes is located. +inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment ) +{ + const std::size_t alignExtra = alignment-1; + return ( numBytes + alignExtra ) / alignment; +} + +// DefaultAllocator ----------------------------------------------------------- +/** @ingroup SmallObjectGroupInternal + Calls the default allocator when SmallObjAllocator decides not to handle a + request. SmallObjAllocator calls this if the number of bytes is bigger than + the size which can be handled by any FixedAllocator. + @param numBytes number of bytes + @param doThrow True if this function should throw an exception, or false if it + should indicate failure by returning a NULL pointer. +*/ +void * DefaultAllocator( std::size_t numBytes, bool doThrow ) +{ +#ifdef USE_NEW_TO_ALLOCATE + return doThrow ? ::operator new( numBytes ) : + ::operator new( numBytes, std::nothrow_t() ); +#else + void * p = ::std::malloc( numBytes ); + if ( doThrow && ( NULL == p ) ) + throw std::bad_alloc(); + return p; +#endif +} + +// DefaultDeallocator --------------------------------------------------------- +/** @ingroup SmallObjectGroupInternal + Calls default deallocator when SmallObjAllocator decides not to handle a + request. The default deallocator could be the global delete operator or the + free function. The free function is the preferred default deallocator since + it matches malloc which is the preferred default allocator. SmallObjAllocator + will call this if an address was not found among any of its own blocks. + */ +void DefaultDeallocator( void * p ) +{ +#ifdef USE_NEW_TO_ALLOCATE + ::operator delete( p ); +#else + ::std::free( p ); +#endif +} + +// SmallObjAllocator::SmallObjAllocator --------------------------------------- + +SmallObjAllocator::SmallObjAllocator( std::size_t pageSize, + std::size_t maxObjectSize, std::size_t objectAlignSize ) : + pool_( NULL ), + maxSmallObjectSize_( maxObjectSize ), + objectAlignSize_( objectAlignSize ) +{ +#ifdef DO_EXTRA_LOKI_TESTS + std::cout << "SmallObjAllocator " << this << std::endl; +#endif + assert( 0 != objectAlignSize ); + const std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize ); + pool_ = new FixedAllocator[ allocCount ]; + for ( std::size_t i = 0; i < allocCount; ++i ) + pool_[ i ].Initialize( ( i+1 ) * objectAlignSize, pageSize ); +} + +// SmallObjAllocator::~SmallObjAllocator -------------------------------------- + +SmallObjAllocator::~SmallObjAllocator( void ) +{ +#ifdef DO_EXTRA_LOKI_TESTS + std::cout << "~SmallObjAllocator " << this << std::endl; +#endif + delete [] pool_; +} + +// SmallObjAllocator::TrimExcessMemory ---------------------------------------- + +bool SmallObjAllocator::TrimExcessMemory( void ) +{ + bool found = false; + const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + std::size_t i = 0; + for ( ; i < allocCount; ++i ) + { + if ( pool_[ i ].TrimEmptyChunk() ) + found = true; + } + for ( i = 0; i < allocCount; ++i ) + { + if ( pool_[ i ].TrimChunkList() ) + found = true; + } + + return found; +} + +// SmallObjAllocator::Allocate ------------------------------------------------ + +void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow ) +{ + if ( numBytes > GetMaxObjectSize() ) + return DefaultAllocator( numBytes, doThrow ); + + assert( NULL != pool_ ); + if ( 0 == numBytes ) numBytes = 1; + const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; + const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + (void) allocCount; + assert( index < allocCount ); + + FixedAllocator & allocator = pool_[ index ]; + assert( allocator.BlockSize() >= numBytes ); + assert( allocator.BlockSize() < numBytes + GetAlignment() ); + void * place = allocator.Allocate(); + + if ( ( NULL == place ) && TrimExcessMemory() ) + place = allocator.Allocate(); + + if ( ( NULL == place ) && doThrow ) + { +#ifdef _MSC_VER + throw std::bad_alloc( "could not allocate small object" ); +#else + // GCC did not like a literal string passed to std::bad_alloc. + // so just throw the default-constructed exception. + throw std::bad_alloc(); +#endif + } + return place; +} + +// SmallObjAllocator::Deallocate ---------------------------------------------- + +void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes ) +{ + if ( NULL == p ) return; + if ( numBytes > GetMaxObjectSize() ) + { + DefaultDeallocator( p ); + return; + } + assert( NULL != pool_ ); + if ( 0 == numBytes ) numBytes = 1; + const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1; + const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + (void) allocCount; + assert( index < allocCount ); + FixedAllocator & allocator = pool_[ index ]; + assert( allocator.BlockSize() >= numBytes ); + assert( allocator.BlockSize() < numBytes + GetAlignment() ); + const bool found = allocator.Deallocate( p, NULL ); + (void) found; + assert( found ); +} + +// SmallObjAllocator::Deallocate ---------------------------------------------- + +void SmallObjAllocator::Deallocate( void * p ) +{ + if ( NULL == p ) return; + assert( NULL != pool_ ); + FixedAllocator * pAllocator = NULL; + const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + Chunk * chunk = NULL; + + for ( std::size_t ii = 0; ii < allocCount; ++ii ) + { + chunk = pool_[ ii ].HasBlock( p ); + if ( NULL != chunk ) + { + pAllocator = &pool_[ ii ]; + break; + } + } + if ( NULL == pAllocator ) + { + DefaultDeallocator( p ); + return; + } + + assert( NULL != chunk ); + const bool found = pAllocator->Deallocate( p, chunk ); + (void) found; + assert( found ); +} + +// SmallObjAllocator::IsCorrupt ----------------------------------------------- + +bool SmallObjAllocator::IsCorrupt( void ) const +{ + if ( NULL == pool_ ) + { + assert( false ); + return true; + } + if ( 0 == GetAlignment() ) + { + assert( false ); + return true; + } + if ( 0 == GetMaxObjectSize() ) + { + assert( false ); + return true; + } + const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() ); + for ( std::size_t ii = 0; ii < allocCount; ++ii ) + { + if ( pool_[ ii ].IsCorrupt() ) + return true; + } + return false; +} + +} // end namespace Loki + diff --git a/shared/loki/SmallObj.h b/shared/loki/SmallObj.h new file mode 100644 index 00000000..65828bf2 --- /dev/null +++ b/shared/loki/SmallObj.h @@ -0,0 +1,644 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SMALLOBJ_INC_ +#define LOKI_SMALLOBJ_INC_ + +// $Id: SmallObj.h 806 2007-02-03 00:01:52Z rich_sposato $ + + +#include "LokiExport.h" +#include "Threads.h" +#include "Singleton.h" +#include <cstddef> +#include <new> // needed for std::nothrow_t parameter. + +#ifndef LOKI_DEFAULT_CHUNK_SIZE +#define LOKI_DEFAULT_CHUNK_SIZE 4096 +#endif + +#ifndef LOKI_MAX_SMALL_OBJECT_SIZE +#define LOKI_MAX_SMALL_OBJECT_SIZE 256 +#endif + +#ifndef LOKI_DEFAULT_OBJECT_ALIGNMENT +#define LOKI_DEFAULT_OBJECT_ALIGNMENT 4 +#endif + +#ifndef LOKI_DEFAULT_SMALLOBJ_LIFETIME +#define LOKI_DEFAULT_SMALLOBJ_LIFETIME ::Loki::LongevityLifetime::DieAsSmallObjectParent +#endif + +#if defined(LOKI_SMALL_OBJECT_USE_NEW_ARRAY) && defined(_MSC_VER) +#pragma message("Don't define LOKI_SMALL_OBJECT_USE_NEW_ARRAY when using a Microsoft compiler to prevent memory leaks.") +#pragma message("now calling '#undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY'") +#undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY +#endif + +/// \defgroup SmallObjectGroup Small objects +/// +/// \defgroup SmallObjectGroupInternal Internals +/// \ingroup SmallObjectGroup + +namespace Loki +{ + namespace LongevityLifetime + { + /** @struct DieAsSmallObjectParent + @ingroup SmallObjectGroup + Lifetime policy to manage lifetime dependencies of + SmallObject base and child classes. + The Base class should have this lifetime + */ + template <class T> + struct DieAsSmallObjectParent : DieLast<T> {}; + + /** @struct DieAsSmallObjectChild + @ingroup SmallObjectGroup + Lifetime policy to manage lifetime dependencies of + SmallObject base and child classes. + The Child class should have this lifetime + */ + template <class T> + struct DieAsSmallObjectChild : DieDirectlyBeforeLast<T> {}; + + } + + class FixedAllocator; + + /** @class SmallObjAllocator + @ingroup SmallObjectGroupInternal + Manages pool of fixed-size allocators. + Designed to be a non-templated base class of AllocatorSingleton so that + implementation details can be safely hidden in the source code file. + */ + class LOKI_EXPORT SmallObjAllocator + { + protected: + /** The only available constructor needs certain parameters in order to + initialize all the FixedAllocator's. This throws only if + @param pageSize # of bytes in a page of memory. + @param maxObjectSize Max # of bytes which this may allocate. + @param objectAlignSize # of bytes between alignment boundaries. + */ + SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize, + std::size_t objectAlignSize ); + + /** Destructor releases all blocks, all Chunks, and FixedAllocator's. + Any outstanding blocks are unavailable, and should not be used after + this destructor is called. The destructor is deliberately non-virtual + because it is protected, not public. + */ + ~SmallObjAllocator( void ); + + public: + /** Allocates a block of memory of requested size. Complexity is often + constant-time, but might be O(C) where C is the number of Chunks in a + FixedAllocator. + + @par Exception Safety Level + Provides either strong-exception safety, or no-throw exception-safety + level depending upon doThrow parameter. The reason it provides two + levels of exception safety is because it is used by both the nothrow + and throwing new operators. The underlying implementation will never + throw of its own accord, but this can decide to throw if it does not + allocate. The only exception it should emit is std::bad_alloc. + + @par Allocation Failure + If it does not allocate, it will call TrimExcessMemory and attempt to + allocate again, before it decides to throw or return NULL. Many + allocators loop through several new_handler functions, and terminate + if they can not allocate, but not this one. It only makes one attempt + using its own implementation of the new_handler, and then returns NULL + or throws so that the program can decide what to do at a higher level. + (Side note: Even though the C++ Standard allows allocators and + new_handlers to terminate if they fail, the Loki allocator does not do + that since that policy is not polite to a host program.) + + @param size # of bytes needed for allocation. + @param doThrow True if this should throw if unable to allocate, false + if it should provide no-throw exception safety level. + @return NULL if nothing allocated and doThrow is false. Else the + pointer to an available block of memory. + */ + void * Allocate( std::size_t size, bool doThrow ); + + /** Deallocates a block of memory at a given place and of a specific + size. Complexity is almost always constant-time, and is O(C) only if + it has to search for which Chunk deallocates. This never throws. + */ + void Deallocate( void * p, std::size_t size ); + + /** Deallocates a block of memory at a given place but of unknown size + size. Complexity is O(F + C) where F is the count of FixedAllocator's + in the pool, and C is the number of Chunks in all FixedAllocator's. This + does not throw exceptions. This overloaded version of Deallocate is + called by the nothow delete operator - which is called when the nothrow + new operator is used, but a constructor throws an exception. + */ + void Deallocate( void * p ); + + /// Returns max # of bytes which this can allocate. + inline std::size_t GetMaxObjectSize() const + { return maxSmallObjectSize_; } + + /// Returns # of bytes between allocation boundaries. + inline std::size_t GetAlignment() const { return objectAlignSize_; } + + /** Releases empty Chunks from memory. Complexity is O(F + C) where F + is the count of FixedAllocator's in the pool, and C is the number of + Chunks in all FixedAllocator's. This will never throw. This is called + by AllocatorSingleto::ClearExtraMemory, the new_handler function for + Loki's allocator, and is called internally when an allocation fails. + @return True if any memory released, or false if none released. + */ + bool TrimExcessMemory( void ); + + /** Returns true if anything in implementation is corrupt. Complexity + is O(F + C + B) where F is the count of FixedAllocator's in the pool, + C is the number of Chunks in all FixedAllocator's, and B is the number + of blocks in all Chunks. If it determines any data is corrupted, this + will return true in release version, but assert in debug version at + the line where it detects the corrupted data. If it does not detect + any corrupted data, it returns false. + */ + bool IsCorrupt( void ) const; + + private: + /// Default-constructor is not implemented. + SmallObjAllocator( void ); + /// Copy-constructor is not implemented. + SmallObjAllocator( const SmallObjAllocator & ); + /// Copy-assignment operator is not implemented. + SmallObjAllocator & operator = ( const SmallObjAllocator & ); + + /// Pointer to array of fixed-size allocators. + Loki::FixedAllocator * pool_; + + /// Largest object size supported by allocators. + const std::size_t maxSmallObjectSize_; + + /// Size of alignment boundaries. + const std::size_t objectAlignSize_; + }; + + + /** @class AllocatorSingleton + @ingroup SmallObjectGroupInternal + This template class is derived from + SmallObjAllocator in order to pass template arguments into it, and still + have a default constructor for the singleton. Each instance is a unique + combination of all the template parameters, and hence is singleton only + with respect to those parameters. The template parameters have default + values and the class has typedefs identical to both SmallObject and + SmallValueObject so that this class can be used directly instead of going + through SmallObject or SmallValueObject. That design feature allows + clients to use the new_handler without having the name of the new_handler + function show up in classes derived from SmallObject or SmallValueObject. + Thus, the only functions in the allocator which show up in SmallObject or + SmallValueObject inheritance hierarchies are the new and delete + operators. + */ + template + < + template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, + std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE, + std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE, + std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT, + template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME, + class MutexPolicy = LOKI_DEFAULT_MUTEX + > + class AllocatorSingleton : public SmallObjAllocator + { + public: + + /// Defines type of allocator. + typedef AllocatorSingleton< ThreadingModel, chunkSize, + maxSmallObjectSize, objectAlignSize, LifetimePolicy > MyAllocator; + + /// Defines type for thread-safety locking mechanism. + typedef ThreadingModel< MyAllocator, MutexPolicy > MyThreadingModel; + + /// Defines singleton made from allocator. + typedef Loki::SingletonHolder< MyAllocator, Loki::CreateStatic, + LifetimePolicy, ThreadingModel > MyAllocatorSingleton; + + /// Returns reference to the singleton. + inline static AllocatorSingleton & Instance( void ) + { + return MyAllocatorSingleton::Instance(); + } + + /// The default constructor is not meant to be called directly. + inline AllocatorSingleton() : + SmallObjAllocator( chunkSize, maxSmallObjectSize, objectAlignSize ) + {} + + /// The destructor is not meant to be called directly. + inline ~AllocatorSingleton( void ) {} + + /** Clears any excess memory used by the allocator. Complexity is + O(F + C) where F is the count of FixedAllocator's in the pool, and C + is the number of Chunks in all FixedAllocator's. This never throws. + @note This function can be used as a new_handler when Loki and other + memory allocators can no longer allocate. Although the C++ Standard + allows new_handler functions to terminate the program when they can + not release any memory, this will not do so. + */ + static void ClearExtraMemory( void ); + + /** Returns true if anything in implementation is corrupt. Complexity + is O(F + C + B) where F is the count of FixedAllocator's in the pool, + C is the number of Chunks in all FixedAllocator's, and B is the number + of blocks in all Chunks. If it determines any data is corrupted, this + will return true in release version, but assert in debug version at + the line where it detects the corrupted data. If it does not detect + any corrupted data, it returns false. + */ + static bool IsCorrupted( void ); + + private: + /// Copy-constructor is not implemented. + AllocatorSingleton( const AllocatorSingleton & ); + /// Copy-assignment operator is not implemented. + AllocatorSingleton & operator = ( const AllocatorSingleton & ); + }; + + template + < + template <class, class> class T, + std::size_t C, + std::size_t M, + std::size_t O, + template <class> class L, + class X + > + void AllocatorSingleton< T, C, M, O, L, X >::ClearExtraMemory( void ) + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + Instance().TrimExcessMemory(); + } + + template + < + template <class, class> class T, + std::size_t C, + std::size_t M, + std::size_t O, + template <class> class L, + class X + > + bool AllocatorSingleton< T, C, M, O, L, X >::IsCorrupted( void ) + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + return Instance().IsCorrupt(); + } + + /** This standalone function provides the longevity level for Small-Object + Allocators which use the Loki::SingletonWithLongevity policy. The + SingletonWithLongevity class can find this function through argument- + dependent lookup. + + @par Longevity Levels + No Small-Object Allocator depends on any other Small-Object allocator, so + this does not need to calculate dependency levels among allocators, and + it returns just a constant. All allocators must live longer than the + objects which use the allocators, it must return a longevity level higher + than any such object. + */ + template + < + template <class, class> class T, + std::size_t C, + std::size_t M, + std::size_t O, + template <class> class L, + class X + > + inline unsigned int GetLongevity( + AllocatorSingleton< T, C, M, O, L, X > * ) + { + // Returns highest possible value. + return 0xFFFFFFFF; + } + + + /** @class SmallObjectBase + @ingroup SmallObjectGroup + Base class for small object allocation classes. + The shared implementation of the new and delete operators are here instead + of being duplicated in both SmallObject or SmallValueObject, later just + called Small-Objects. This class is not meant to be used directly by clients, + or derived from by clients. Class has no data members so compilers can + use Empty-Base-Optimization. + + @par ThreadingModel + This class doesn't support ObjectLevelLockable policy for ThreadingModel. + The allocator is a singleton, so a per-instance mutex is not necessary. + Nor is using ObjectLevelLockable recommended with SingletonHolder since + the SingletonHolder::MakeInstance function requires a mutex that exists + prior to when the object is created - which is not possible if the mutex + is inside the object, such as required for ObjectLevelLockable. If you + attempt to use ObjectLevelLockable, the compiler will emit errors because + it can't use the default constructor in ObjectLevelLockable. If you need + a thread-safe allocator, use the ClassLevelLockable policy. + + @par Lifetime Policy + + The SmallObjectBase template needs a lifetime policy because it owns + a singleton of SmallObjAllocator which does all the low level functions. + When using a Small-Object in combination with the SingletonHolder template + you have to choose two lifetimes, that of the Small-Object and that of + the singleton. The rule is: The Small-Object lifetime must be greater than + the lifetime of the singleton hosting the Small-Object. Violating this rule + results in a crash on exit, because the hosting singleton tries to delete + the Small-Object which is then already destroyed. + + The lifetime policies recommended for use with Small-Objects hosted + by a SingletonHolder template are + - LongevityLifetime::DieAsSmallObjectParent / LongevityLifetime::DieAsSmallObjectChild + - SingletonWithLongevity + - FollowIntoDeath (not supported by MSVC 7.1) + - NoDestroy + + The default lifetime of Small-Objects is + LongevityLifetime::DieAsSmallObjectParent to + insure that memory is not released before a object with the lifetime + LongevityLifetime::DieAsSmallObjectChild using that + memory is destroyed. The LongevityLifetime::DieAsSmallObjectParent + lifetime has the highest possible value of a SetLongevity lifetime, so + you can use it in combination with your own lifetime not having also + the highest possible value. + + The DefaultLifetime and PhoenixSingleton policies are *not* recommended + since they can cause the allocator to be destroyed and release memory + for singletons hosting a object which inherit from either SmallObject + or SmallValueObject. + + @par Lifetime usage + + - LongevityLifetime: The Small-Object has + LongevityLifetime::DieAsSmallObjectParent policy and the Singleton + hosting the Small-Object has LongevityLifetime::DieAsSmallObjectChild. + The child lifetime has a hard coded SetLongevity lifetime which is + shorter than the lifetime of the parent, thus the child dies + before the parent. + + - Both Small-Object and Singleton use SingletonWithLongevity policy. + The longevity level for the singleton must be lower than that for the + Small-Object. This is why the AllocatorSingleton's GetLongevity function + returns the highest value. + + - FollowIntoDeath lifetime: The Small-Object has + FollowIntoDeath::With<LIFETIME>::AsMasterLiftime + policy and the Singleton has + FollowIntoDeath::AfterMaster<MASTERSINGLETON>::IsDestroyed policy, + where you could choose the LIFETIME. + + - Both Small-Object and Singleton use NoDestroy policy. + Since neither is ever destroyed, the destruction order does not matter. + Note: you will get memory leaks! + + - The Small-Object has NoDestroy policy but the Singleton has + SingletonWithLongevity policy. Note: you will get memory leaks! + + + You should *not* use NoDestroy for the singleton, and then use + SingletonWithLongevity for the Small-Object. + + @par Examples: + + - test/SmallObj/SmallSingleton.cpp + - test/Singleton/Dependencies.cpp + */ + template + < + template <class, class> class ThreadingModel, + std::size_t chunkSize, + std::size_t maxSmallObjectSize, + std::size_t objectAlignSize, + template <class> class LifetimePolicy, + class MutexPolicy + > + class SmallObjectBase + { + +#if (LOKI_MAX_SMALL_OBJECT_SIZE != 0) && (LOKI_DEFAULT_CHUNK_SIZE != 0) && (LOKI_DEFAULT_OBJECT_ALIGNMENT != 0) + + public: + /// Defines type of allocator singleton, must be public + /// to handle singleton lifetime dependencies. + typedef AllocatorSingleton< ThreadingModel, chunkSize, + maxSmallObjectSize, objectAlignSize, LifetimePolicy > ObjAllocatorSingleton; + + private: + + /// Defines type for thread-safety locking mechanism. + typedef ThreadingModel< ObjAllocatorSingleton, MutexPolicy > MyThreadingModel; + + /// Use singleton defined in AllocatorSingleton. + typedef typename ObjAllocatorSingleton::MyAllocatorSingleton MyAllocatorSingleton; + + public: + + /// Throwing single-object new throws bad_alloc when allocation fails. +#ifdef _MSC_VER + /// @note MSVC complains about non-empty exception specification lists. + static void * operator new ( std::size_t size ) +#else + static void * operator new ( std::size_t size ) throw ( std::bad_alloc ) +#endif + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + return MyAllocatorSingleton::Instance().Allocate( size, true ); + } + + /// Non-throwing single-object new returns NULL if allocation fails. + static void * operator new ( std::size_t size, const std::nothrow_t & ) throw () + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + return MyAllocatorSingleton::Instance().Allocate( size, false ); + } + + /// Placement single-object new merely calls global placement new. + inline static void * operator new ( std::size_t size, void * place ) + { + return ::operator new( size, place ); + } + + /// Single-object delete. + static void operator delete ( void * p, std::size_t size ) throw () + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + MyAllocatorSingleton::Instance().Deallocate( p, size ); + } + + /** Non-throwing single-object delete is only called when nothrow + new operator is used, and the constructor throws an exception. + */ + static void operator delete ( void * p, const std::nothrow_t & ) throw() + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + MyAllocatorSingleton::Instance().Deallocate( p ); + } + + /// Placement single-object delete merely calls global placement delete. + inline static void operator delete ( void * p, void * place ) + { + ::operator delete ( p, place ); + } + +#ifdef LOKI_SMALL_OBJECT_USE_NEW_ARRAY + + /// Throwing array-object new throws bad_alloc when allocation fails. +#ifdef _MSC_VER + /// @note MSVC complains about non-empty exception specification lists. + static void * operator new [] ( std::size_t size ) +#else + static void * operator new [] ( std::size_t size ) + throw ( std::bad_alloc ) +#endif + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + return MyAllocatorSingleton::Instance().Allocate( size, true ); + } + + /// Non-throwing array-object new returns NULL if allocation fails. + static void * operator new [] ( std::size_t size, + const std::nothrow_t & ) throw () + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + return MyAllocatorSingleton::Instance().Allocate( size, false ); + } + + /// Placement array-object new merely calls global placement new. + inline static void * operator new [] ( std::size_t size, void * place ) + { + return ::operator new( size, place ); + } + + /// Array-object delete. + static void operator delete [] ( void * p, std::size_t size ) throw () + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + MyAllocatorSingleton::Instance().Deallocate( p, size ); + } + + /** Non-throwing array-object delete is only called when nothrow + new operator is used, and the constructor throws an exception. + */ + static void operator delete [] ( void * p, + const std::nothrow_t & ) throw() + { + typename MyThreadingModel::Lock lock; + (void)lock; // get rid of warning + MyAllocatorSingleton::Instance().Deallocate( p ); + } + + /// Placement array-object delete merely calls global placement delete. + inline static void operator delete [] ( void * p, void * place ) + { + ::operator delete ( p, place ); + } +#endif // #if use new array functions. + +#endif // #if default template parameters are not zero + + protected: + inline SmallObjectBase( void ) {} + inline SmallObjectBase( const SmallObjectBase & ) {} + inline SmallObjectBase & operator = ( const SmallObjectBase & ) + { return *this; } + inline ~SmallObjectBase() {} + }; // end class SmallObjectBase + + + /** @class SmallObject + @ingroup SmallObjectGroup + SmallObject Base class for polymorphic small objects, offers fast + allocations & deallocations. Destructor is virtual and public. Default + constructor is trivial. Copy-constructor and copy-assignment operator are + not implemented since polymorphic classes almost always disable those + operations. Class has no data members so compilers can use + Empty-Base-Optimization. + */ + template + < + template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, + std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE, + std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE, + std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT, + template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME, + class MutexPolicy = LOKI_DEFAULT_MUTEX + > + class SmallObject : public SmallObjectBase< ThreadingModel, chunkSize, + maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy > + { + + public: + virtual ~SmallObject() {} + protected: + inline SmallObject( void ) {} + + private: + /// Copy-constructor is not implemented. + SmallObject( const SmallObject & ); + /// Copy-assignment operator is not implemented. + SmallObject & operator = ( const SmallObject & ); + }; // end class SmallObject + + + /** @class SmallValueObject + @ingroup SmallObjectGroup + SmallValueObject Base class for small objects with value-type + semantics - offers fast allocations & deallocations. Destructor is + non-virtual, inline, and protected to prevent unintentional destruction + through base class. Default constructor is trivial. Copy-constructor + and copy-assignment operator are trivial since value-types almost always + need those operations. Class has no data members so compilers can use + Empty-Base-Optimization. + */ + template + < + template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, + std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE, + std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE, + std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT, + template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME, + class MutexPolicy = LOKI_DEFAULT_MUTEX + > + class SmallValueObject : public SmallObjectBase< ThreadingModel, chunkSize, + maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy > + { + protected: + inline SmallValueObject( void ) {} + inline SmallValueObject( const SmallValueObject & ) {} + inline SmallValueObject & operator = ( const SmallValueObject & ) + { return *this; } + inline ~SmallValueObject() {} + }; // end class SmallValueObject + +} // namespace Loki + +#endif // end file guardian + diff --git a/shared/loki/SmartPtr.h b/shared/loki/SmartPtr.h new file mode 100644 index 00000000..df548553 --- /dev/null +++ b/shared/loki/SmartPtr.h @@ -0,0 +1,1778 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_SMARTPTR_INC_ +#define LOKI_SMARTPTR_INC_ + +// $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $ + + +/// \defgroup SmartPointerGroup Smart pointers +/// Policy based implementation of a smart pointer +/// \defgroup SmartPointerOwnershipGroup Ownership policies +/// \ingroup SmartPointerGroup +/// \defgroup SmartPointerStorageGroup Storage policies +/// \ingroup SmartPointerGroup +/// \defgroup SmartPointerConversionGroup Conversion policies +/// \ingroup SmartPointerGroup +/// \defgroup SmartPointerCheckingGroup Checking policies +/// \ingroup SmartPointerGroup + +#include "LokiExport.h" +#include "SmallObj.h" +#include "TypeManip.h" +#include "static_check.h" +#include "RefToValue.h" +#include "ConstPolicy.h" + +#include <functional> +#include <stdexcept> +#include <cassert> +#include <string> + +#if !defined(_MSC_VER) +# if defined(__sparc__) +# include <inttypes.h> +# else +# include <stdint.h> +# endif +#endif + +#if defined(_MSC_VER) || defined(__GNUC__) +// GCC>=4.1 must use -ffriend-injection due to a bug in GCC +#define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND +#endif + + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +/// \class HeapStorage +/// +/// \ingroup SmartPointerStorageGroup +/// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call +/// to T's destructor followed by call to free. +//////////////////////////////////////////////////////////////////////////////// + + + template <class T> + class HeapStorage + { + public: + typedef T* StoredType; /// the type of the pointee_ object + typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. + typedef T* PointerType; /// type returned by operator-> + typedef T& ReferenceType; /// type returned by operator* + + HeapStorage() : pointee_(Default()) + {} + + // The storage policy doesn't initialize the stored pointer + // which will be initialized by the OwnershipPolicy's Clone fn + HeapStorage(const HeapStorage&) : pointee_(0) + {} + + template <class U> + HeapStorage(const HeapStorage<U>&) : pointee_(0) + {} + + HeapStorage(const StoredType& p) : pointee_(p) {} + + PointerType operator->() const { return pointee_; } + + ReferenceType operator*() const { return *pointee_; } + + void Swap(HeapStorage& rhs) + { std::swap(pointee_, rhs.pointee_); } + + // Accessors + template <class F> + friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp); + + template <class F> + friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp); + + template <class F> + friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp); + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + void Destroy() + { + if ( 0 != pointee_ ) + { + pointee_->~T(); + ::free( pointee_ ); + } + } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + // Data + StoredType pointee_; + }; + + template <class T> + inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp) + { return sp.pointee_; } + + +//////////////////////////////////////////////////////////////////////////////// +/// \class DefaultSPStorage +/// +/// \ingroup SmartPointerStorageGroup +/// Implementation of the StoragePolicy used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + + template <class T> + class DefaultSPStorage + { + public: + typedef T* StoredType; // the type of the pointee_ object + typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. + typedef T* PointerType; // type returned by operator-> + typedef T& ReferenceType; // type returned by operator* + + DefaultSPStorage() : pointee_(Default()) + {} + + // The storage policy doesn't initialize the stored pointer + // which will be initialized by the OwnershipPolicy's Clone fn + DefaultSPStorage(const DefaultSPStorage&) : pointee_(0) + {} + + template <class U> + DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0) + {} + + DefaultSPStorage(const StoredType& p) : pointee_(p) {} + + PointerType operator->() const { return pointee_; } + + ReferenceType operator*() const { return *pointee_; } + + void Swap(DefaultSPStorage& rhs) + { std::swap(pointee_, rhs.pointee_); } + + // Accessors + template <class F> + friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp); + + template <class F> + friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp); + + template <class F> + friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp); + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + // + // If your compiler gives you a warning in this area while + // compiling the tests, it is on purpose, please ignore it. + void Destroy() + { + delete pointee_; + } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + // Data + StoredType pointee_; + }; + + template <class T> + inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp) + { return sp.pointee_; } + + +//////////////////////////////////////////////////////////////////////////////// +/// \class LockedStorage +/// +/// \ingroup SmartPointerStorageGroup +/// Implementation of the StoragePolicy used by SmartPtr. +/// +/// Each call to operator-> locks the object for the duration of a call to a +/// member function of T. +/// +/// \par How It Works +/// LockedStorage has a helper class called Locker, which acts as a smart +/// pointer with limited abilities. LockedStorage::operator-> returns an +/// unnamed temporary of type Locker<T> that exists for the duration of the +/// call to a member function of T. The unnamed temporary locks the object +/// when it is constructed by operator-> and unlocks the object when it is +/// destructed. +/// +/// \note This storage policy requires class T to have member functions Lock +/// and Unlock. If your class does not have Lock or Unlock functions, you may +/// either make a child class which does, or make a policy class similar to +/// LockedStorage which calls other functions to lock the object. +//////////////////////////////////////////////////////////////////////////////// + + template <class T> + class Locker + { + public: + Locker( const T * p ) : pointee_( const_cast< T * >( p ) ) + { + if ( pointee_ != 0 ) + pointee_->Lock(); + } + + ~Locker( void ) + { + if ( pointee_ != 0 ) + pointee_->Unlock(); + } + + operator T * () + { + return pointee_; + } + + T * operator->() + { + return pointee_; + } + + private: + Locker( void ); + Locker & operator = ( const Locker & ); + T * pointee_; + }; + + template <class T> + class LockedStorage + { + public: + + typedef T* StoredType; /// the type of the pointee_ object + typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. + typedef Locker< T > PointerType; /// type returned by operator-> + typedef T& ReferenceType; /// type returned by operator* + + LockedStorage() : pointee_( Default() ) {} + + ~LockedStorage( void ) {} + + LockedStorage( const LockedStorage&) : pointee_( 0 ) {} + + LockedStorage( const StoredType & p ) : pointee_( p ) {} + + PointerType operator->() + { + return Locker< T >( pointee_ ); + } + + void Swap(LockedStorage& rhs) + { + std::swap( pointee_, rhs.pointee_ ); + } + + // Accessors + template <class F> + friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp); + + template <class F> + friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp); + + template <class F> + friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp); + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + void Destroy() + { + delete pointee_; + } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + /// Dereference operator is not implemented. + ReferenceType operator*(); + + // Data + StoredType pointee_; + }; + + template <class T> + inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp) + { return sp.pointee_; } + + +//////////////////////////////////////////////////////////////////////////////// +/// \class ArrayStorage +/// +/// \ingroup SmartPointerStorageGroup +/// Implementation of the ArrayStorage used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + + template <class T> + class ArrayStorage + { + public: + typedef T* StoredType; // the type of the pointee_ object + typedef T* InitPointerType; /// type used to declare OwnershipPolicy type. + typedef T* PointerType; // type returned by operator-> + typedef T& ReferenceType; // type returned by operator* + + ArrayStorage() : pointee_(Default()) + {} + + // The storage policy doesn't initialize the stored pointer + // which will be initialized by the OwnershipPolicy's Clone fn + ArrayStorage(const ArrayStorage&) : pointee_(0) + {} + + template <class U> + ArrayStorage(const ArrayStorage<U>&) : pointee_(0) + {} + + ArrayStorage(const StoredType& p) : pointee_(p) {} + + PointerType operator->() const { return pointee_; } + + ReferenceType operator*() const { return *pointee_; } + + void Swap(ArrayStorage& rhs) + { std::swap(pointee_, rhs.pointee_); } + + // Accessors + template <class F> + friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp); + + template <class F> + friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp); + + template <class F> + friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp); + + protected: + // Destroys the data stored + // (Destruction might be taken over by the OwnershipPolicy) + void Destroy() + { delete [] pointee_; } + + // Default value to initialize the pointer + static StoredType Default() + { return 0; } + + private: + // Data + StoredType pointee_; + }; + + template <class T> + inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp) + { return sp.pointee_; } + + template <class T> + inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp) + { return sp.pointee_; } + + +//////////////////////////////////////////////////////////////////////////////// +/// \class RefCounted +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Provides a classic external reference counting implementation +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + class RefCounted + { + public: + RefCounted() + : pCount_(static_cast<uintptr_t*>( + SmallObject<>::operator new(sizeof(uintptr_t)))) + { + assert(pCount_!=0); + *pCount_ = 1; + } + + RefCounted(const RefCounted& rhs) + : pCount_(rhs.pCount_) + {} + + // MWCW lacks template friends, hence the following kludge + template <typename P1> + RefCounted(const RefCounted<P1>& rhs) + : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_) + {} + + P Clone(const P& val) + { + ++*pCount_; + return val; + } + + bool Release(const P&) + { + if (!--*pCount_) + { + SmallObject<>::operator delete(pCount_, sizeof(uintptr_t)); + pCount_ = NULL; + return true; + } + return false; + } + + void Swap(RefCounted& rhs) + { std::swap(pCount_, rhs.pCount_); } + + enum { destructiveCopy = false }; + + private: + // Data + uintptr_t* pCount_; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct RefCountedMT +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Implements external reference counting for multithreaded programs +/// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT +/// +/// \par Warning +/// There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release" +/// http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644 +/// As stated in bug 1408845, the Release function is not thread safe if a +/// SmartPtr copy-constructor tries to copy the last pointer to an object in +/// one thread, while the destructor is acting on the last pointer in another +/// thread. The existence of a race between a copy-constructor and destructor +/// implies a design flaw at a higher level. That race condition must be +/// fixed at a higher design level, and no change to this class could fix it. +//////////////////////////////////////////////////////////////////////////////// + + template <template <class, class> class ThreadingModel, + class MX = LOKI_DEFAULT_MUTEX > + struct RefCountedMTAdj + { + template <class P> + class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX > + { + typedef ThreadingModel< RefCountedMT<P>, MX > base_type; + typedef typename base_type::IntType CountType; + typedef volatile CountType *CountPtrType; + + public: + RefCountedMT() + { + pCount_ = static_cast<CountPtrType>( + SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new( + sizeof(*pCount_))); + assert(pCount_); + //*pCount_ = 1; + ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1); + } + + RefCountedMT(const RefCountedMT& rhs) + : pCount_(rhs.pCount_) + {} + + //MWCW lacks template friends, hence the following kludge + template <typename P1> + RefCountedMT(const RefCountedMT<P1>& rhs) + : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_) + {} + + P Clone(const P& val) + { + ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_); + return val; + } + + bool Release(const P&) + { + bool isZero = false; + ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero ); + if ( isZero ) + { + SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete( + const_cast<CountType *>(pCount_), + sizeof(*pCount_)); + return true; + } + return false; + } + + void Swap(RefCountedMT& rhs) + { std::swap(pCount_, rhs.pCount_); } + + enum { destructiveCopy = false }; + + private: + // Data + CountPtrType pCount_; + }; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class COMRefCounted +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + class COMRefCounted + { + public: + COMRefCounted() + {} + + template <class U> + COMRefCounted(const COMRefCounted<U>&) + {} + + static P Clone(const P& val) + { + if(val!=0) + val->AddRef(); + return val; + } + + static bool Release(const P& val) + { + if(val!=0) + val->Release(); + return false; + } + + enum { destructiveCopy = false }; + + static void Swap(COMRefCounted&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct DeepCopy +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Implements deep copy semantics, assumes existence of a Clone() member +/// function of the pointee type +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct DeepCopy + { + DeepCopy() + {} + + template <class P1> + DeepCopy(const DeepCopy<P1>&) + {} + + static P Clone(const P& val) + { return val->Clone(); } + + static bool Release(const P&) + { return true; } + + static void Swap(DeepCopy&) + {} + + enum { destructiveCopy = false }; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class RefLinked +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Implements reference linking +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + class LOKI_EXPORT RefLinkedBase + { + public: + RefLinkedBase() + { prev_ = next_ = this; } + + RefLinkedBase(const RefLinkedBase& rhs); + + bool Release(); + + void Swap(RefLinkedBase& rhs); + + bool Merge( RefLinkedBase & rhs ); + + enum { destructiveCopy = false }; + + private: + static unsigned int CountPrevCycle( const RefLinkedBase * pThis ); + static unsigned int CountNextCycle( const RefLinkedBase * pThis ); + bool HasPrevNode( const RefLinkedBase * p ) const; + bool HasNextNode( const RefLinkedBase * p ) const; + + mutable const RefLinkedBase* prev_; + mutable const RefLinkedBase* next_; + }; + } + + template <class P> + class RefLinked : public Private::RefLinkedBase + { + public: + RefLinked() + {} + + template <class P1> + RefLinked(const RefLinked<P1>& rhs) + : Private::RefLinkedBase(rhs) + {} + + static P Clone(const P& val) + { return val; } + + bool Release(const P&) + { return Private::RefLinkedBase::Release(); } + + template < class P1 > + bool Merge( RefLinked< P1 > & rhs ) + { + return Private::RefLinkedBase::Merge( rhs ); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class DestructiveCopy +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Implements destructive copy semantics (a la std::auto_ptr) +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + class DestructiveCopy + { + public: + DestructiveCopy() + {} + + template <class P1> + DestructiveCopy(const DestructiveCopy<P1>&) + {} + + template <class P1> + static P Clone(P1& val) + { + P result(val); + val = P1(); + return result; + } + + static bool Release(const P&) + { return true; } + + static void Swap(DestructiveCopy&) + {} + + enum { destructiveCopy = true }; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class NoCopy +/// +/// \ingroup SmartPointerOwnershipGroup +/// Implementation of the OwnershipPolicy used by SmartPtr +/// Implements a policy that doesn't allow copying objects +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + class NoCopy + { + public: + NoCopy() + {} + + template <class P1> + NoCopy(const NoCopy<P1>&) + {} + + static P Clone(const P&) + { + // Make it depended on template parameter + static const bool DependedFalse = sizeof(P*) == 0; + + LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying); + } + + static bool Release(const P&) + { return true; } + + static void Swap(NoCopy&) + {} + + enum { destructiveCopy = false }; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct AllowConversion +/// +/// \ingroup SmartPointerConversionGroup +/// Implementation of the ConversionPolicy used by SmartPtr +/// Allows implicit conversion from SmartPtr to the pointee type +//////////////////////////////////////////////////////////////////////////////// + + struct AllowConversion + { + enum { allow = true }; + + void Swap(AllowConversion&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct DisallowConversion +/// +/// \ingroup SmartPointerConversionGroup +/// Implementation of the ConversionPolicy used by SmartPtr +/// Does not allow implicit conversion from SmartPtr to the pointee type +/// You can initialize a DisallowConversion with an AllowConversion +//////////////////////////////////////////////////////////////////////////////// + + struct DisallowConversion + { + DisallowConversion() + {} + + DisallowConversion(const AllowConversion&) + {} + + enum { allow = false }; + + void Swap(DisallowConversion&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct NoCheck +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Well, it's clear what it does :o) +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct NoCheck + { + NoCheck() + {} + + template <class P1> + NoCheck(const NoCheck<P1>&) + {} + + static void OnDefault(const P&) + {} + + static void OnInit(const P&) + {} + + static void OnDereference(const P&) + {} + + static void Swap(NoCheck&) + {} + }; + + +//////////////////////////////////////////////////////////////////////////////// +/// \struct AssertCheck +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Checks the pointer before dereference +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct AssertCheck + { + AssertCheck() + {} + + template <class P1> + AssertCheck(const AssertCheck<P1>&) + {} + + template <class P1> + AssertCheck(const NoCheck<P1>&) + {} + + static void OnDefault(const P&) + {} + + static void OnInit(const P&) + {} + + static void OnDereference(P val) + { assert(val); (void)val; } + + static void Swap(AssertCheck&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct AssertCheckStrict +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Checks the pointer against zero upon initialization and before dereference +/// You can initialize an AssertCheckStrict with an AssertCheck +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct AssertCheckStrict + { + AssertCheckStrict() + {} + + template <class U> + AssertCheckStrict(const AssertCheckStrict<U>&) + {} + + template <class U> + AssertCheckStrict(const AssertCheck<U>&) + {} + + template <class P1> + AssertCheckStrict(const NoCheck<P1>&) + {} + + static void OnDefault(P val) + { assert(val); } + + static void OnInit(P val) + { assert(val); } + + static void OnDereference(P val) + { assert(val); } + + static void Swap(AssertCheckStrict&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct NullPointerException +/// +/// \ingroup SmartPointerGroup +/// Used by some implementations of the CheckingPolicy used by SmartPtr +//////////////////////////////////////////////////////////////////////////////// + + struct NullPointerException : public std::runtime_error + { + NullPointerException() : std::runtime_error(std::string("")) + { } + const char* what() const throw() + { return "Null Pointer Exception"; } + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct RejectNullStatic +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Checks the pointer upon initialization and before dereference +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct RejectNullStatic + { + RejectNullStatic() + {} + + template <class P1> + RejectNullStatic(const RejectNullStatic<P1>&) + {} + + template <class P1> + RejectNullStatic(const NoCheck<P1>&) + {} + + template <class P1> + RejectNullStatic(const AssertCheck<P1>&) + {} + + template <class P1> + RejectNullStatic(const AssertCheckStrict<P1>&) + {} + + static void OnDefault(const P&) + { + // Make it depended on template parameter + static const bool DependedFalse = sizeof(P*) == 0; + + LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization); + } + + static void OnInit(const P& val) + { if (!val) throw NullPointerException(); } + + static void OnDereference(const P& val) + { if (!val) throw NullPointerException(); } + + static void Swap(RejectNullStatic&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct RejectNull +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Checks the pointer before dereference +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct RejectNull + { + RejectNull() + {} + + template <class P1> + RejectNull(const RejectNull<P1>&) + {} + + static void OnInit(P) + {} + + static void OnDefault(P) + {} + + void OnDereference(P val) + { if (!val) throw NullPointerException(); } + + void OnDereference(P val) const + { if (!val) throw NullPointerException(); } + + void Swap(RejectNull&) + {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct RejectNullStrict +/// +/// \ingroup SmartPointerCheckingGroup +/// Implementation of the CheckingPolicy used by SmartPtr +/// Checks the pointer upon initialization and before dereference +//////////////////////////////////////////////////////////////////////////////// + + template <class P> + struct RejectNullStrict + { + RejectNullStrict() + {} + + template <class P1> + RejectNullStrict(const RejectNullStrict<P1>&) + {} + + template <class P1> + RejectNullStrict(const RejectNull<P1>&) + {} + + static void OnInit(P val) + { if (!val) throw NullPointerException(); } + + void OnDereference(P val) + { OnInit(val); } + + void OnDereference(P val) const + { OnInit(val); } + + void Swap(RejectNullStrict&) + {} + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template SmartPtr (declaration) +// The reason for all the fuss above +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OwnershipPolicy = RefCounted, + class ConversionPolicy = DisallowConversion, + template <class> class CheckingPolicy = AssertCheck, + template <class> class StoragePolicy = DefaultSPStorage, + template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS + > + class SmartPtr; + +//////////////////////////////////////////////////////////////////////////////// +// class template SmartPtrDef (definition) +// this class added to unify the usage of SmartPtr +// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OwnershipPolicy = RefCounted, + class ConversionPolicy = DisallowConversion, + template <class> class CheckingPolicy = AssertCheck, + template <class> class StoragePolicy = DefaultSPStorage, + template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS + > + struct SmartPtrDef + { + typedef SmartPtr + < + T, + OwnershipPolicy, + ConversionPolicy, + CheckingPolicy, + StoragePolicy, + ConstnessPolicy + > + type; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class SmartPtr +/// +/// \ingroup SmartPointerGroup +/// +/// \param OwnershipPolicy default = RefCounted, +/// \param ConversionPolicy default = DisallowConversion, +/// \param CheckingPolicy default = AssertCheck, +/// \param StoragePolicy default = DefaultSPStorage +/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS +/// +/// \par IMPORTANT NOTE +/// Due to threading issues, the OwnershipPolicy has been changed as follows: +/// +/// - Release() returns a boolean saying if that was the last release +/// so the pointer can be deleted by the StoragePolicy +/// - IsUnique() was removed +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OwnershipPolicy, + class ConversionPolicy, + template <class> class CheckingPolicy, + template <class> class StoragePolicy, + template <class> class ConstnessPolicy + > + class SmartPtr + : public StoragePolicy<T> + , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> + , public CheckingPolicy<typename StoragePolicy<T>::StoredType> + , public ConversionPolicy + { + typedef StoragePolicy<T> SP; + typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP; + typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP; + typedef ConversionPolicy CP; + + public: + typedef typename ConstnessPolicy<T>::Type* ConstPointerType; + typedef typename ConstnessPolicy<T>::Type& ConstReferenceType; + + typedef typename SP::PointerType PointerType; + typedef typename SP::StoredType StoredType; + typedef typename SP::ReferenceType ReferenceType; + + typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result + CopyArg; + + private: + struct NeverMatched {}; + +#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY + typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg; + typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg; +#else + typedef const StoredType& ImplicitArg; + typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg; +#endif + + public: + + SmartPtr() + { + KP::OnDefault(GetImpl(*this)); + } + + explicit + SmartPtr(ExplicitArg p) : SP(p) + { + KP::OnInit(GetImpl(*this)); + } + + SmartPtr(ImplicitArg p) : SP(p) + { + KP::OnInit(GetImpl(*this)); + } + + SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + { + GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); + } + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + { + GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); + } + + SmartPtr(RefToValue<SmartPtr> rhs) + : SP(rhs), OP(rhs), KP(rhs), CP(rhs) + {} + + operator RefToValue<SmartPtr>() + { return RefToValue<SmartPtr>(*this); } + + SmartPtr& operator=(CopyArg& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) + { + SmartPtr temp(rhs); + temp.Swap(*this); + return *this; + } + + void Swap(SmartPtr& rhs) + { + OP::Swap(rhs); + CP::Swap(rhs); + KP::Swap(rhs); + SP::Swap(rhs); + } + + ~SmartPtr() + { + if (OP::Release(GetImpl(*static_cast<SP*>(this)))) + { + SP::Destroy(); + } + } + +#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND + + // old non standard in class definition of friends + friend inline void Release(SmartPtr& sp, typename SP::StoredType& p) + { + p = GetImplRef(sp); + GetImplRef(sp) = SP::Default(); + } + + friend inline void Reset(SmartPtr& sp, typename SP::StoredType p) + { SmartPtr(p).Swap(sp); } + +#else + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp, + typename SP1<T1>::StoredType& p); + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp, + typename SP1<T1>::StoredType p); +#endif + + + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) + { + if ( GetImpl( *this ) != GetImpl( rhs ) ) + { + return false; + } + return OP::template Merge( rhs ); + } + + PointerType operator->() + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator->(); + } + + ConstPointerType operator->() const + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator->(); + } + + ReferenceType operator*() + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator*(); + } + + ConstReferenceType operator*() const + { + KP::OnDereference(GetImplRef(*this)); + return SP::operator*(); + } + + bool operator!() const // Enables "if (!sp) ..." + { return GetImpl(*this) == 0; } + + static inline T * GetPointer( const SmartPtr & sp ) + { return GetImpl( sp ); } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const + { return GetImpl(*this) == GetImpl(rhs); } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const + { return !(*this == rhs); } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const + { return GetImpl(*this) < GetImpl(rhs); } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) + { + return ( GetImpl( rhs ) < GetImpl( *this ) ); + } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) + { + return !( GetImpl( rhs ) < GetImpl( *this ) ); + } + + // Ambiguity buster + template + < + typename T1, + template <class> class OP1, + class CP1, + template <class> class KP1, + template <class> class SP1, + template <class> class CNP1 + > + inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs ) + { + return !( GetImpl( *this ) < GetImpl( rhs ) ); + } + + private: + // Helper for enabling 'if (sp)' + struct Tester + { + Tester(int) {} + void dummy() {} + }; + + typedef void (Tester::*unspecified_boolean_type_)(); + + typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result + unspecified_boolean_type; + + public: + // enable 'if (sp)' + operator unspecified_boolean_type() const + { + return !*this ? 0 : &Tester::dummy; + } + + private: + // Helper for disallowing automatic conversion + struct Insipid + { + Insipid(PointerType) {} + }; + + typedef typename Select<CP::allow, PointerType, Insipid>::Result + AutomaticConversionResult; + + public: + operator AutomaticConversionResult() const + { return GetImpl(*this); } + }; + + +//////////////////////////////////////////////////////////////////////////////// +// friends +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP + > + inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp, + typename SP<T>::StoredType& p) + { + p = GetImplRef(sp); + GetImplRef(sp) = SP<T>::Default(); + } + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP + > + inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp, + typename SP<T>::StoredType p) + { SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); } + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// free comparison operators for class template SmartPtr +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// operator== for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP1, + typename U + > + inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs, + U* rhs) + { return GetImpl(lhs) == rhs; } + +//////////////////////////////////////////////////////////////////////////////// +/// operator== for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP1, + typename U + > + inline bool operator==(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs) + { return rhs == lhs; } + +//////////////////////////////////////////////////////////////////////////////// +/// operator!= for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + U* rhs) + { return !(lhs == rhs); } + +//////////////////////////////////////////////////////////////////////////////// +/// operator!= for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator!=(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) + { return rhs != lhs; } + +//////////////////////////////////////////////////////////////////////////////// +/// operator< for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + U* rhs) + { + return ( GetImpl( lhs ) < rhs ); + } + +//////////////////////////////////////////////////////////////////////////////// +/// operator< for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator<(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) + { + return ( GetImpl( rhs ) < lhs ); + } + +//////////////////////////////////////////////////////////////////////////////// +// operator> for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + U* rhs) + { return rhs < lhs; } + +//////////////////////////////////////////////////////////////////////////////// +/// operator> for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator>(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) + { return rhs < lhs; } + +//////////////////////////////////////////////////////////////////////////////// +/// operator<= for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + U* rhs) + { return !(rhs < lhs); } + +//////////////////////////////////////////////////////////////////////////////// +/// operator<= for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator<=(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) + { return !(rhs < lhs); } + +//////////////////////////////////////////////////////////////////////////////// +/// operator>= for lhs = SmartPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + U* rhs) + { return !(lhs < rhs); } + +//////////////////////////////////////////////////////////////////////////////// +/// operator>= for lhs = raw pointer, rhs = SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP, + typename U + > + inline bool operator>=(U* lhs, + const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) + { return !(lhs < rhs); } + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +/// specialization of std::less for SmartPtr +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + +namespace std +{ + template + < + typename T, + template <class> class OP, + class CP, + template <class> class KP, + template <class> class SP, + template <class> class CNP + > + struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > > + : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, + Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool> + { + bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs, + const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const + { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); } + }; +} + +#endif // end file guardian + diff --git a/shared/loki/StrongPtr.h b/shared/loki/StrongPtr.h new file mode 100644 index 00000000..7ec9766f --- /dev/null +++ b/shared/loki/StrongPtr.h @@ -0,0 +1,1697 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Rich Sposato +// The copyright on this file is protected under the terms of the MIT license. +// +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_STRONG_PTR_INC_ +#define LOKI_STRONG_PTR_INC_ + +// $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $ + + +#include <loki/SmartPtr.h> +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + #include <loki/Threads.h> +#endif + + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \par Terminology +/// These terms are used within this file's comments. +/// -# StrongPtr : Class used to implement both strong and weak pointers. The +/// second template parameter determines if a StrongPtr is weak or strong. +/// -# Strong pointer : A pointer that claims ownership of a shared object. +/// When the last strong copointer dies, the object is destroyed even if +/// there are weak copointers. +/// -# Weak pointer : A pointer that does not own the shared object it points +/// to. It only destroys the shared object if there no strong copointers +/// exist when it dies. +/// -# Copointers : All the pointers that refer to the same shared object. +/// The copointers must have the same ownership policy, but the other +/// policies may be different. +/// -# Pointee : The shared object. +/// +/// \par OwnershipPolicy +/// The ownership policy has the pointer to the actual object, and it also +/// keeps track of the strong and weak copointers so that it can know if any +/// strong copointers remain. The plain pointer it maintains is stored as a +/// void pointer, which allows the ownership policy classes to be monolithic +/// classes instead of template classes. As monolithic classes, they reduce +/// amount of code-bloat. +/// +/// \par Writing Your Own OwnershipPolicy +/// If you write your own policy, you must implement these 12 functions: +/// -# explicit YourPolicy( bool strong ) +/// -# YourPolicy( void * p, bool strong ) +/// -# YourPolicy( const YourPolicy & rhs, bool strong ) +/// -# bool Release( bool strong ) +/// -# void Increment( bool strong ) +/// -# bool Decrement( bool strong ) +/// -# bool HasStrongPointer( void ) const +/// -# void Swap( YourPolicy & rhs ) +/// -# void SetPointer( void * p ) +/// -# void ZapPointer( void ) +/// -# void * GetPointer( void ) const +/// -# void * & GetPointerRef( void ) const +/// It is strongly recommended that all 12 of these functions be protected +/// instead of public. These two functions are optional for single-threaded +/// policies, but required for multi-threaded policies: +/// -# void Lock( void ) const +/// -# void Unlock( void ) const +/// This function is entirely optional: +/// -# bool Merge( TwoRefLinks & rhs ) +/// +/// \par DeletePolicy +/// The delete policy provides a mechanism to destroy an object and a default +/// value for an uninitialized pointer. You can override this policy with +/// your own when using the Singleton, NullObject, or Prototype design +/// patterns. +/// +/// \par Writing Your Own DeletePolicy +/// If you write your own policy, you must implement these 3 functions: +/// -# void static Delete( const P * p ) +/// -# static P * Default( void ) +/// -# void Swap( YourResetPolicy & ) +/// +/// \par ResetPolicy +/// A reset policy tells the ReleaseAll and ResetAll functions whether they +/// should release or reset the StrongPtr copointers. These functions do +/// not affect just one StrongPtr, but all copointers. That is unlike +/// SmartPtr where the Release and Reset functions only affect 1 SmartPtr, +/// and leave all copointers untouched. A useful trick you can do with the +/// ResetPolicy is to not allow reset when a strong pointer exists, and then +/// use the NoCheck policy for all strong pointers. The reset policy +/// guarantees the strong pointers always have a valid pointee, so checking +/// is not required; but weak pointers may still require checking. +/// +/// \par Writing Your Own ResetPolicy +/// If you write your own policy, you must implement these 2 functions: +/// -# bool OnReleaseAll( bool ) const +/// -# bool OnResetAll( bool ) const +/// The bool parameter means that this was called with a strong pointer or +/// one of its copointers is strong. The return value means the pointer +/// can be reset or released. +/// +/// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies +/// \ingroup SmartPointerGroup +/// \defgroup StrongPointerDeleteGroup Delete policies +/// \ingroup SmartPointerGroup +/// \defgroup StrongPointerResetGroup Reset policies +/// \ingroup SmartPointerGroup +//////////////////////////////////////////////////////////////////////////////// + + +namespace Loki +{ + + +//////////////////////////////////////////////////////////////////////////////// +/// \class DeleteUsingFree +/// +/// \ingroup StrongPointerDeleteGroup +/// Implementation of the DeletePolicy used by StrongPtr. Uses explicit call +/// to T's destructor followed by call to free. This policy is useful for +/// managing the lifetime of pointers to structs returned by C functions. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +class DeleteUsingFree +{ +public: + inline void static Delete( const P * p ) + { + if ( 0 != p ) + { + p->~P(); + ::free( p ); + } + } + + /// Provides default value to initialize the pointer + inline static P * Default( void ) + { + return 0; + } + + inline void Swap( DeleteUsingFree & ) {} +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class DeleteNothing +/// +/// \ingroup StrongPointerDeleteGroup +/// Implementation of the DeletePolicy used by StrongPtr. This will never +/// delete anything. You can use this policy with pointers to an undefined +/// type or a pure interface class with a protected destructor. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +class DeleteNothing +{ +public: + inline static void Delete( const P * ) + { + // Do nothing at all! + } + + inline static P * Default( void ) + { + return 0; + } + + inline void Swap( DeleteNothing & ) {} +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class DeleteSingle +/// +/// \ingroup StrongPointerDeleteGroup +/// Implementation of the DeletePolicy used by StrongPtr. This deletes just +/// one shared object. This is the default class for the DeletePolicy. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +class DeleteSingle +{ +public: + inline static void Delete( const P * p ) + { + /** @note If you see an error message about a negative subscript, that + means your are attempting to use Loki to delete an incomplete type. + Please don't use this policy with incomplete types; you may want to + use DeleteNothing instead. + */ + typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ]; + delete p; + } + + inline static P * Default( void ) + { + return 0; + } + + inline void Swap( DeleteSingle & ) {} +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class DeleteArray +/// +/// \ingroup StrongPointerDeleteGroup +/// Implementation of the DeletePolicy used by StrongPtr. This deletes an +/// array of shared objects. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +class DeleteArray +{ +public: + inline static void Delete( const P * p ) + { + /** @note If you see an error message about a negative subscript, that + means your are attempting to use Loki to delete an incomplete type. + Please don't use this policy with incomplete types; you may want to + use DeleteNothing instead. + */ + typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ]; + delete [] p; + } + + inline static P * Default( void ) + { + return 0; + } + + inline void Swap( DeleteArray & ) {} +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class CantResetWithStrong +/// +/// \ingroup StrongPointerResetGroup +/// Implementation of the ResetPolicy used by StrongPtr. This is the default +/// ResetPolicy for StrongPtr. It forbids reset and release only if a strong +/// copointer exists. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +struct CantResetWithStrong +{ + inline bool OnReleaseAll( bool hasStrongPtr ) const + { + return ! hasStrongPtr; + } + + inline bool OnResetAll( bool hasStrongPtr ) const + { + return ! hasStrongPtr; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class AllowReset +/// +/// \ingroup StrongPointerResetGroup +/// Implementation of the ResetPolicy used by StrongPtr. It allows reset and +/// release under any circumstance. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +struct AllowReset +{ + inline bool OnReleaseAll( bool ) const + { + return true; + } + inline bool OnResetAll( bool ) const + { + return true; + } +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class NeverReset +/// +/// \ingroup StrongPointerResetGroup +/// Implementation of the ResetPolicy used by StrongPtr. It forbids reset and +/// release under any circumstance. +//////////////////////////////////////////////////////////////////////////////// + +template < class P > +struct NeverReset +{ + inline bool OnReleaseAll( bool ) const + { + return false; + } + inline bool OnResetAll( bool ) const + { + return false; + } +}; + +// ---------------------------------------------------------------------------- + +namespace Private +{ + +//////////////////////////////////////////////////////////////////////////////// +/// \class TwoRefCountInfo +/// +/// \ingroup StrongPointerOwnershipGroup +/// Implementation detail for reference counting strong and weak pointers. +/// It maintains a void pointer and 2 reference counts. Since it is just a +/// class for managing implementation details, it is not intended to be used +/// directly - which is why it is in a private namespace. Each instance is a +/// shared resource for all copointers, and there should be only one of these +/// for each set of copointers. This class is small, trivial, and inline. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT TwoRefCountInfo +{ +public: + + inline explicit TwoRefCountInfo( bool strong ) + : m_pointer( 0 ) + , m_strongCount( strong ? 1 : 0 ) + , m_weakCount( strong ? 0 : 1 ) + { + } + + inline TwoRefCountInfo( void * p, bool strong ) + : m_pointer( p ) + , m_strongCount( strong ? 1 : 0 ) + , m_weakCount( strong ? 0 : 1 ) + { + } + + inline ~TwoRefCountInfo( void ) + { + assert( 0 == m_strongCount ); + assert( 0 == m_weakCount ); + } + + inline bool HasStrongPointer( void ) const + { + return ( 0 < m_strongCount ); + } + + inline bool HasWeakPointer( void ) const + { + return ( 0 < m_weakCount ); + } + + inline void IncStrongCount( void ) + { + ++m_strongCount; + } + + inline void IncWeakCount( void ) + { + ++m_weakCount; + } + + inline bool DecStrongCount( void ) + { + assert( 0 < m_strongCount ); + --m_strongCount; + const bool isZero = ( 0 == m_strongCount ); + return isZero; + } + + inline void DecWeakCount( void ) + { + assert( 0 < m_weakCount ); + --m_weakCount; + } + + inline void ZapPointer( void ) + { + m_pointer = 0; + } + + void SetPointer( void * p ) + { + m_pointer = p; + } + + inline void * GetPointer( void ) const + { + return m_pointer; + } + + inline void * & GetPointerRef( void ) const + { + return const_cast< void * & >( m_pointer ); + } + +private: + /// Copy-constructor not implemented. + TwoRefCountInfo( const TwoRefCountInfo & ); + /// Copy-assignment operator not implemented. + TwoRefCountInfo & operator = ( const TwoRefCountInfo & ); + + void * m_pointer; + unsigned int m_strongCount; + unsigned int m_weakCount; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class LockableTwoRefCountInfo +/// +/// \ingroup StrongPointerOwnershipGroup +/// Implementation detail for thread-safe reference counting for strong and +/// weak pointers. It uses TwoRefCountInfo to manage the pointer and counts. +/// All this does is provide a thread safety mechanism. Since it is just a +/// class for managing implementation details, it is not intended to be used +/// directly - which is why it is in a private namespace. Each instance is a +/// shared resource for all copointers, and there should be only one of these +/// for each set of copointers. This class is small, trivial, and inline. +/// +/// \note This class is not designed for use with a single-threaded model. +/// Tests using a single-threaded model will not run properly, but tests in a +/// multi-threaded model with either class-level-locking or object-level-locking +/// do run properly. +//////////////////////////////////////////////////////////////////////////////// + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +class LOKI_EXPORT LockableTwoRefCountInfo + : private Loki::Private::TwoRefCountInfo +{ +public: + + inline explicit LockableTwoRefCountInfo( bool strong ) + : TwoRefCountInfo( strong ) + , m_Mutex() + { + } + + LockableTwoRefCountInfo( void * p, bool strong ) + : TwoRefCountInfo( p, strong ) + , m_Mutex() + { + } + + inline ~LockableTwoRefCountInfo( void ) + { + } + + inline void Lock( void ) const + { + m_Mutex.Lock(); + } + + inline void Unlock( void ) const + { + m_Mutex.Unlock(); + } + + inline bool HasStrongPointer( void ) const + { + m_Mutex.Lock(); + const bool has = TwoRefCountInfo::HasStrongPointer(); + m_Mutex.Unlock(); + return has; + } + + inline bool HasWeakPointer( void ) const + { + m_Mutex.Lock(); + const bool has = TwoRefCountInfo::HasWeakPointer(); + m_Mutex.Unlock(); + return has; + } + + inline void IncStrongCount( void ) + { + m_Mutex.Lock(); + TwoRefCountInfo::IncStrongCount(); + m_Mutex.Unlock(); + } + + inline void IncWeakCount( void ) + { + m_Mutex.Lock(); + TwoRefCountInfo::IncWeakCount(); + m_Mutex.Unlock(); + } + + inline bool DecStrongCount( void ) + { + m_Mutex.Lock(); + const bool isZero = TwoRefCountInfo::DecStrongCount(); + m_Mutex.Unlock(); + return isZero; + } + + inline void DecWeakCount( void ) + { + m_Mutex.Lock(); + TwoRefCountInfo::DecWeakCount(); + m_Mutex.Unlock(); + } + + inline void ZapPointer( void ) + { + m_Mutex.Lock(); + TwoRefCountInfo::ZapPointer(); + m_Mutex.Unlock(); + } + + void SetPointer( void * p ) + { + m_Mutex.Lock(); + TwoRefCountInfo::SetPointer( p ); + m_Mutex.Unlock(); + } + + inline void * GetPointer( void ) const + { + return TwoRefCountInfo::GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return TwoRefCountInfo::GetPointerRef(); + } + +private: + /// Default constructor is not available. + LockableTwoRefCountInfo( void ); + /// Copy constructor is not available. + LockableTwoRefCountInfo( const LockableTwoRefCountInfo & ); + /// Copy-assignment operator is not available. + LockableTwoRefCountInfo & operator = ( const LockableTwoRefCountInfo & ); + + mutable LOKI_DEFAULT_MUTEX m_Mutex; +}; + +#endif // if object-level-locking or class-level-locking + +} // end namespace Private + +//////////////////////////////////////////////////////////////////////////////// +/// \class TwoRefCounts +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a +/// shared instance of TwoRefCountInfo. This is the default policy for +/// OwnershipPolicy. Some functions are trivial enough to be inline, while +/// others are implemented elsewhere. It is not thread safe, and is intended +/// for single-threaded environments. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT TwoRefCounts +{ +protected: + + explicit TwoRefCounts( bool strong ); + + TwoRefCounts( const void * p, bool strong ); + + TwoRefCounts( const TwoRefCounts & rhs, bool strong ) : + m_counts( rhs.m_counts ) + { + Increment( strong ); + } + + /** The destructor does not need to do anything since the call to + ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which + this dtor would have done. + */ + inline ~TwoRefCounts( void ) {} + + inline bool Release( bool strong ) + { + return Decrement( strong ); + } + + bool HasStrongPointer( void ) const + { + return m_counts->HasStrongPointer(); + } + + void Swap( TwoRefCounts & rhs ); + + void SetPointer( void * p ) + { + m_counts->SetPointer( p ); + } + + void ZapPointer( void ); + + inline void * & GetPointerRef( void ) const + { + return m_counts->GetPointerRef(); + } + + inline void * GetPointer( void ) const + { + return m_counts->GetPointer(); + } + +private: + TwoRefCounts( void ); + TwoRefCounts & operator = ( const TwoRefCounts & ); + + void Increment( bool strong ); + + bool Decrement( bool strong ); + + /// Pointer to all shared data. + Loki::Private::TwoRefCountInfo * m_counts; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class LockableTwoRefCounts +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a +/// shared instance of LockableTwoRefCountInfo. It behaves very similarly to +/// TwoRefCounts, except that it provides thread-safety. Some functions are +/// trivial enough to be inline, while others are implemented elsewhere. +/// +/// \note This class is not designed for use with a single-threaded model. +/// Tests using a single-threaded model will not run properly, but tests in a +/// multi-threaded model with either class-level-locking or object-level-locking +/// do run properly. +//////////////////////////////////////////////////////////////////////////////// + +#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING) + +class LOKI_EXPORT LockableTwoRefCounts +{ + typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator; + +protected: + + explicit LockableTwoRefCounts( bool strong ) + : m_counts( NULL ) + { + void * temp = ThreadSafePointerAllocator::operator new( + sizeof(Loki::Private::LockableTwoRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong ); + } + + LockableTwoRefCounts( const void * p, bool strong ) + : m_counts( NULL ) + { + void * temp = ThreadSafePointerAllocator::operator new( + sizeof(Loki::Private::LockableTwoRefCountInfo) ); +#ifdef DO_EXTRA_LOKI_TESTS + assert( temp != 0 ); +#endif + void * p2 = const_cast< void * >( p ); + m_counts = new ( temp ) + Loki::Private::LockableTwoRefCountInfo( p2, strong ); + } + + LockableTwoRefCounts( const LockableTwoRefCounts & rhs, bool strong ) : + m_counts( rhs.m_counts ) + { + Increment( strong ); + } + + /** The destructor does not need to do anything since the call to + ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which + this dtor would have done. + */ + inline ~LockableTwoRefCounts( void ) {} + + inline void Lock( void ) const + { + m_counts->Lock(); + } + + inline void Unlock( void ) const + { + m_counts->Unlock(); + } + + inline bool Release( bool strong ) + { + return Decrement( strong ); + } + + void Increment( bool strong ) + { + if ( strong ) + { + m_counts->IncStrongCount(); + } + else + { + m_counts->IncWeakCount(); + } + } + + bool Decrement( bool strong ) + { + bool noStrongPointers = false; + if ( strong ) + { + noStrongPointers = m_counts->DecStrongCount(); + } + else + { + m_counts->DecWeakCount(); + noStrongPointers = !m_counts->HasStrongPointer(); + } + return noStrongPointers; + } + + bool HasStrongPointer( void ) const + { + return m_counts->HasStrongPointer(); + } + + void Swap( LockableTwoRefCounts & rhs ) + { + std::swap( m_counts, rhs.m_counts ); + } + + void SetPointer( void * p ) + { + m_counts->SetPointer( p ); + } + + void ZapPointer( void ) + { +#ifdef DO_EXTRA_LOKI_TESTS + assert( !m_counts->HasStrongPointer() ); +#endif + if ( m_counts->HasWeakPointer() ) + { + m_counts->ZapPointer(); + } + else + { + ThreadSafePointerAllocator::operator delete ( m_counts, + sizeof(Loki::Private::LockableTwoRefCountInfo) ); + m_counts = NULL; + } + } + + inline void * GetPointer( void ) const + { + return m_counts->GetPointer(); + } + + inline void * & GetPointerRef( void ) const + { + return m_counts->GetPointerRef(); + } + +private: + LockableTwoRefCounts( void ); + LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & ); + + /// Pointer to all shared data. + Loki::Private::LockableTwoRefCountInfo * m_counts; +}; + +#endif // if object-level-locking or class-level-locking + +//////////////////////////////////////////////////////////////////////////////// +/// \class TwoRefLinks +/// +/// \ingroup StrongPointerOwnershipGroup +/// This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked +/// cycle of copointers to a shared object. Some functions are trivial enough +/// to be inline, while others are implemented in elsewhere. It is not thread +/// safe, and is intended for single-threaded environments. +//////////////////////////////////////////////////////////////////////////////// + +class LOKI_EXPORT TwoRefLinks +{ +protected: + + inline explicit TwoRefLinks( bool strong ) + : m_pointer( 0 ) + , m_strong( strong ) + { + m_prev = m_next = this; + } + + TwoRefLinks( const void * p, bool strong ); + + TwoRefLinks( const TwoRefLinks & rhs, bool strong ); + + bool Release( bool strong ); + + void Swap( TwoRefLinks & rhs ); + + bool Merge( TwoRefLinks & rhs ); + + bool HasStrongPointer( void ) const; + + inline void ZapPointer( void ) + { + ZapAllNodes(); + } + + void SetPointer( void * p ); + + inline void * GetPointer( void ) const + { + return m_pointer; + } + + inline void * & GetPointerRef( void ) const + { + return const_cast< void * & >( m_pointer ); + } + +private: + static unsigned int CountPrevCycle( const TwoRefLinks * pThis ); + static unsigned int CountNextCycle( const TwoRefLinks * pThis ); + + /// Not implemented. + TwoRefLinks( void ); + /// Not implemented. + TwoRefLinks & operator = ( const TwoRefLinks & ); + + bool HasPrevNode( const TwoRefLinks * p ) const; + bool HasNextNode( const TwoRefLinks * p ) const; + bool AllNodesHaveSamePointer( void ) const; + void ZapAllNodes( void ); + + void * m_pointer; + mutable TwoRefLinks * m_prev; + mutable TwoRefLinks * m_next; + const bool m_strong; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class StrongPtr +/// +/// \ingroup SmartPointerGroup +/// +/// \param Strong default = true, +/// \param OwnershipPolicy default = TwoRefCounts, +/// \param ConversionPolicy default = DisallowConversion, +/// \param CheckingPolicy default = AssertCheck, +/// \param ResetPolicy default = CantResetWithStrong, +/// \param DeletePolicy default = DeleteSingle +/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS +//////////////////////////////////////////////////////////////////////////////// + +template +< + typename T, + bool Strong = true, + class OwnershipPolicy = Loki::TwoRefCounts, + class ConversionPolicy = Loki::DisallowConversion, + template < class > class CheckingPolicy = Loki::AssertCheck, + template < class > class ResetPolicy = Loki::CantResetWithStrong, + template < class > class DeletePolicy = Loki::DeleteSingle, + template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS +> +class StrongPtr + : public OwnershipPolicy + , public ConversionPolicy + , public CheckingPolicy< T * > + , public ResetPolicy< T > + , public DeletePolicy< T > +{ + typedef ConversionPolicy CP; + typedef CheckingPolicy< T * > KP; + typedef ResetPolicy< T > RP; + typedef DeletePolicy< T > DP; + +public: + + typedef OwnershipPolicy OP; + + typedef T * StoredType; // the type of the pointer + typedef T * PointerType; // type returned by operator-> + typedef T & ReferenceType; // type returned by operator* + + typedef typename ConstnessPolicy< T >::Type * ConstPointerType; + typedef typename ConstnessPolicy< T >::Type & ConstReferenceType; + +private: + struct NeverMatched {}; + +#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY + typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg; + typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg; +#else + typedef const StoredType& ImplicitArg; + typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg; +#endif + +public: + + StrongPtr( void ) : OP( Strong ) + { + KP::OnDefault( GetPointer() ); + } + + explicit StrongPtr( ExplicitArg p ) : OP( p, Strong ) + { + KP::OnInit( GetPointer() ); + } + + StrongPtr( ImplicitArg p ) : OP( p, Strong ) + { + KP::OnInit( GetPointer() ); + } + + StrongPtr( const StrongPtr & rhs ) + : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs ) + { + } + + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + StrongPtr( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) + : OP( rhs, Strong ) + { + } + + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + StrongPtr( + StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) + : OP( rhs, Strong ) + { + } + + StrongPtr( RefToValue< StrongPtr > rhs ) + : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs ) + { + } + + operator RefToValue< StrongPtr >( void ) + { + return RefToValue< StrongPtr >( *this ); + } + + StrongPtr & operator = ( const StrongPtr & rhs ) + { + if ( GetPointer() != rhs.GetPointer() ) + { + StrongPtr temp( rhs ); + temp.Swap( *this ); + } + return *this; + } + + StrongPtr & operator = ( T * p ) + { + if ( GetPointer() != p ) + { + StrongPtr temp( p ); + Swap( temp ); + } + return *this; + } + + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + StrongPtr & operator = ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) + { + if ( !rhs.Equals( GetPointer() ) ) + { + StrongPtr temp( rhs ); + temp.Swap( *this ); + } + return *this; + } + + bool IsStrong( void ) const + { + return Strong; + } + + void Swap( StrongPtr & rhs ) + { + OP::Swap( rhs ); + CP::Swap( rhs ); + KP::Swap( rhs ); + DP::Swap( rhs ); + } + + ~StrongPtr() + { + if ( OP::Release( Strong ) ) + { + // Must zap the pointer before deleteing the object. Otherwise a + // cycle of weak pointers will lead to recursion, which leads to + // to deleting the shared object multiple times, which leads to + // undefined behavior. Therefore, this must get pointer before + // zapping it, and then delete the temp pointer. + T * p = GetPointer(); + OP::ZapPointer(); + if ( p != 0 ) + { + DP::Delete( p ); + } + } + } + +#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND + + // old non standard in class definition of friends + friend bool ReleaseAll( StrongPtr & sp, + typename StrongPtr::StoredType & p ) + { + if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + { + return false; + } + p = sp.GetPointer(); + sp.OP::SetPointer( sp.DP::Default() ); + return true; + } + + friend bool ResetAll( StrongPtr & sp, + typename StrongPtr::StoredType p ) + { + if ( sp.OP::GetPointer() == p ) + { + return true; + } + if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + { + return false; + } + sp.DP::Delete( sp.GetPointer() ); + sp.OP::SetPointer( p ); + return true; + } + +#else + + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp, + typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType & p ); + + + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp, + typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p ); + +#endif + + + /** Merges ownership of two StrongPtr's that point to same shared object + but are not copointers. Requires Merge function in OwnershipPolicy. + \return True for success, false if not pointer to same object. + */ + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) + { + if ( OP::GetPointer() != rhs.OP::GetPointer() ) + { + return false; + } + return OP::Merge( rhs ); + } + + /** Locks StrongPtr so other threads can't affect pointer. Requires the + OwnershipPolicy to have Lock function. + */ + void Lock( void ) + { + OP::Lock(); + } + + /** Unlocks StrongPtr so other threads can affect pointer. Requires the + OwnershipPolicy to have Unlock function. + */ + void Unlock( void ) + { + OP::Unlock(); + } + + PointerType operator -> () + { + KP::OnDereference( GetPointer() ); + return GetPointer(); + } + + ConstPointerType operator -> () const + { + KP::OnDereference( GetPointer() ); + return GetPointer(); + } + + ReferenceType operator * () + { + KP::OnDereference( GetPointer() ); + return * GetPointer(); + } + + ConstReferenceType operator * () const + { + KP::OnDereference( GetPointer() ); + return * GetPointer(); + } + + /// Helper function which can be called to avoid exposing GetPointer function. + template < class T1 > + bool Equals( const T1 * p ) const + { + return ( GetPointer() == p ); + } + + /// Helper function which can be called to avoid exposing GetPointer function. + template < class T1 > + bool LessThan( const T1 * p ) const + { + return ( GetPointer() < p ); + } + + /// Helper function which can be called to avoid exposing GetPointer function. + template < class T1 > + bool GreaterThan( const T1 * p ) const + { + return ( GetPointer() > p ); + } + + /// Equality comparison operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + bool operator == ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return ( rhs.Equals( GetPointer() ) ); + } + + /// Inequality comparison operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + bool operator != ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return !( rhs.Equals( GetPointer() ) ); + } + + /// Less-than comparison operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + bool operator < ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return ( rhs.GreaterThan( GetPointer() ) ); + } + + /// Greater-than comparison operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + inline bool operator > ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return ( rhs.LessThan( GetPointer() ) ); + } + + /// Less-than-or-equal-to operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + inline bool operator <= ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return !( rhs.LessThan( GetPointer() ) ); + } + + /// Greater-than-or-equal-to operator is templated to handle ambiguity. + template + < + typename T1, + bool S1, + class OP1, + class CP1, + template < class > class KP1, + template < class > class RP1, + template < class > class DP1, + template < class > class CNP1 + > + inline bool operator >= ( + const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const + { + return !( rhs.GreaterThan( GetPointer() ) ); + } + + inline bool operator ! () const // Enables "if ( !sp ) ..." + { + return ( 0 == OP::GetPointer() ); + } + +protected: + + inline PointerType GetPointer( void ) + { + return reinterpret_cast< PointerType >( OP::GetPointer() ); + } + + inline ConstPointerType GetPointer( void ) const + { + return reinterpret_cast< ConstPointerType >( OP::GetPointer() ); + } + +private: + + inline ReferenceType GetPointerRef( void ) + { + return reinterpret_cast< ReferenceType >( OP::GetPointerRef() ); + } + + inline ConstReferenceType GetPointerRef( void ) const + { + return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() ); + } + + // Helper for enabling 'if (sp)' + struct Tester + { + Tester(int) {} + void dummy() {} + }; + + typedef void (Tester::*unspecified_boolean_type_)(); + + typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result + unspecified_boolean_type; + +public: + // enable 'if (sp)' + operator unspecified_boolean_type() const + { + return !*this ? 0 : &Tester::dummy; + } + +private: + // Helper for disallowing automatic conversion + struct Insipid + { + Insipid(PointerType) {} + }; + + typedef typename Select< CP::allow, PointerType, Insipid >::Result + AutomaticConversionResult; + +public: + operator AutomaticConversionResult() const + { + return GetPointer(); + } + +}; + +// ---------------------------------------------------------------------------- + +// friend functions + +#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND + +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp, + typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p ) +{ + if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + { + return false; + } + p = sp.GetPointer(); + sp.OP::SetPointer( sp.DP<T>::Default() ); + return true; +} + +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp, + typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p ) +{ + if ( sp.OP::GetPointer() == p ) + { + return true; + } + if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) ) + { + return false; + } + sp.DP<T>::Delete( sp.GetPointer() ); + sp.OP::SetPointer( p ); + return true; +} +#endif + + +// free comparison operators for class template StrongPtr + +/// operator== for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator == ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return ( lhs.Equals( rhs ) ); +} + +/// operator== for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator == ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return ( rhs.Equals( lhs ) ); +} + +/// operator!= for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator != ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return !( lhs.Equals( rhs ) ); +} + +/// operator!= for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator != ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return !( rhs.Equals( lhs ) ); +} + +/// operator< for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator < ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return ( lhs.LessThan( rhs ) ); +} + +/// operator< for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator < ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return ( rhs.GreaterThan( lhs ) ); +} + +// operator> for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator > ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return ( lhs.GreaterThan( rhs ) ); +} + +/// operator> for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator > ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return ( rhs.LessThan( lhs ) ); +} + +/// operator<= for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator <= ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return !( lhs.GreaterThan( rhs ) ); +} + +/// operator<= for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator <= ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return !( rhs.LessThan( lhs ) ); +} + +/// operator>= for lhs = StrongPtr, rhs = raw pointer +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator >= ( + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs ) +{ + return !( lhs.LessThan( rhs ) ); +} + +/// operator>= for lhs = raw pointer, rhs = StrongPtr +/// \ingroup SmartPointerGroup +template +< + typename U, + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP +> +inline bool operator >= ( U * lhs, + const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) +{ + return !( rhs.GreaterThan( lhs ) ); +} + +} // namespace Loki + +namespace std +{ + //////////////////////////////////////////////////////////////////////////////// + /// specialization of std::less for StrongPtr + /// \ingroup SmartPointerGroup + //////////////////////////////////////////////////////////////////////////////// + template + < + typename T, + bool S, + class OP, + class CP, + template < class > class KP, + template < class > class RP, + template < class > class DP, + template < class > class CNP + > + struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > > + : public binary_function< + Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, + Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool > + { + bool operator () ( + const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, + const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const + { + return ( lhs < rhs ); + } + }; +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif // end file guardian + diff --git a/shared/loki/Threads.h b/shared/loki/Threads.h new file mode 100644 index 00000000..cb44f094 --- /dev/null +++ b/shared/loki/Threads.h @@ -0,0 +1,609 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_THREADS_INC_ +#define LOKI_THREADS_INC_ + +// $Id: Threads.h 902 2008-11-10 05:47:06Z rich_sposato $ + + +/// @defgroup ThreadingGroup Threading +/// Policies to for the threading model: +/// +/// - SingleThreaded +/// - ObjectLevelLockable +/// - ClassLevelLockable +/// +/// All classes in Loki have configurable threading model. +/// +/// The macro LOKI_DEFAULT_THREADING selects the default +/// threading model for certain components of Loki +/// (it affects only default template arguments) +/// +/// \par Usage: +/// +/// To use a specific threading model define +/// +/// - nothing, single-theading is default +/// - LOKI_OBJECT_LEVEL_THREADING for object-level-threading +/// - LOKI_CLASS_LEVEL_THREADING for class-level-threading +/// +/// \par Supported platfroms: +/// +/// - Windows (windows.h) +/// - POSIX (pthread.h): +/// No recursive mutex support with pthread. +/// This means: calling Lock() on a Loki::Mutex twice from the +/// same thread before unlocking the mutex deadlocks the system. +/// To avoid this redesign your synchronization. See also: +/// http://sourceforge.net/tracker/index.php?func=detail&aid=1516182&group_id=29557&atid=396647 + + +#include <cassert> + +#if defined(LOKI_CLASS_LEVEL_THREADING) || defined(LOKI_OBJECT_LEVEL_THREADING) + + #define LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL ::Loki::ClassLevelLockable + + #if defined(LOKI_CLASS_LEVEL_THREADING) && !defined(LOKI_OBJECT_LEVEL_THREADING) + #define LOKI_DEFAULT_THREADING ::Loki::ClassLevelLockable + #else + #define LOKI_DEFAULT_THREADING ::Loki::ObjectLevelLockable + #endif + + #if defined(_WIN32) || defined(_WIN64) + #include <windows.h> + #define LOKI_WINDOWS_H + #else + #include <pthread.h> + #define LOKI_PTHREAD_H + #endif + +#else + + #define LOKI_DEFAULT_THREADING ::Loki::SingleThreaded + #define LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL ::Loki::SingleThreaded + +#endif + +#ifndef LOKI_DEFAULT_MUTEX +#define LOKI_DEFAULT_MUTEX ::Loki::Mutex +#endif + +#ifdef LOKI_WINDOWS_H + +#define LOKI_THREADS_MUTEX(x) CRITICAL_SECTION (x); +#define LOKI_THREADS_MUTEX_INIT(x) ::InitializeCriticalSection (x) +#define LOKI_THREADS_MUTEX_DELETE(x) ::DeleteCriticalSection (x) +#define LOKI_THREADS_MUTEX_LOCK(x) ::EnterCriticalSection (x) +#define LOKI_THREADS_MUTEX_UNLOCK(x) ::LeaveCriticalSection (x) +#define LOKI_THREADS_LONG LONG +#define LOKI_THREADS_MUTEX_CTOR(x) + +#define LOKI_THREADS_ATOMIC_FUNCTIONS \ + static IntType AtomicMultiply(volatile IntType& lval, const IntType val) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval *= val; \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDivide(volatile IntType& lval, const IntType val) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval /= val; \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicIncrement(volatile IntType& lval) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + ++lval; \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDecrement(volatile IntType& lval) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + --lval; \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static void AtomicAssign(volatile IntType& lval, const IntType val) \ + { InterlockedExchange(&const_cast<IntType&>(lval), val); } \ + \ + static void AtomicAssign(IntType& lval, volatile const IntType& val) \ + { InterlockedExchange(&lval, val); } \ + \ + static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + ++lval; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + --lval; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicAdd(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval += val; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicSubtract(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval -= val; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval *= val; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::EnterCriticalSection( &atomic_mutex_ ); \ + lval /= val; \ + matches = ( lval == compare ); \ + ::LeaveCriticalSection( &atomic_mutex_ ); \ + return lval; \ + } + +#elif defined(LOKI_PTHREAD_H) + + +#define LOKI_THREADS_MUTEX(x) pthread_mutex_t (x); + +#define LOKI_THREADS_MUTEX_INIT(x) ::pthread_mutex_init(x, 0) + +// define to 1 to enable recursive mutex support +#if 0 +// experimental recursive mutex support +#define LOKI_THREADS_MUTEX_CTOR(x) : x(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +#else +// no recursive mutex support +#define LOKI_THREADS_MUTEX_CTOR(x) +#endif + +#define LOKI_THREADS_MUTEX_DELETE(x) ::pthread_mutex_destroy (x) +#define LOKI_THREADS_MUTEX_LOCK(x) ::pthread_mutex_lock (x) +#define LOKI_THREADS_MUTEX_UNLOCK(x) ::pthread_mutex_unlock (x) +#define LOKI_THREADS_LONG long + +#define LOKI_THREADS_ATOMIC(x) \ + pthread_mutex_lock(&atomic_mutex_); \ + x; \ + pthread_mutex_unlock(&atomic_mutex_) + +#define LOKI_THREADS_ATOMIC_FUNCTIONS \ + private: \ + static pthread_mutex_t atomic_mutex_; \ + public: \ + static IntType AtomicMultiply(volatile IntType& lval, const IntType val) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval *= val; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDivide(volatile IntType& lval, const IntType val) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval /= val; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicIncrement(volatile IntType& lval) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + ++lval; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDecrement(volatile IntType& lval) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + --lval; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static void AtomicAssign(volatile IntType& lval, const IntType val) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval = val; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static void AtomicAssign(IntType& lval, volatile const IntType& val) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval = val; \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + ++lval; \ + matches = ( compare == lval ); \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches ) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + --lval; \ + matches = ( compare == lval ); \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval *= val; \ + matches = ( lval == compare ); \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } \ + \ + static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \ + { \ + ::pthread_mutex_lock( &atomic_mutex_ ); \ + lval /= val; \ + matches = ( lval == compare ); \ + ::pthread_mutex_unlock( &atomic_mutex_ ); \ + return lval; \ + } + +#else // single threaded + +#define LOKI_THREADS_MUTEX(x) +#define LOKI_THREADS_MUTEX_INIT(x) +#define LOKI_THREADS_MUTEX_DELETE(x) +#define LOKI_THREADS_MUTEX_LOCK(x) +#define LOKI_THREADS_MUTEX_UNLOCK(x) +#define LOKI_THREADS_LONG +#define LOKI_THREADS_MUTEX_CTOR(x) + +#endif + + + +namespace Loki +{ + + //////////////////////////////////////////////////////////////////////////////// + /// \class Mutex + // + /// \ingroup ThreadingGroup + /// A simple and portable Mutex. A default policy class for locking objects. + //////////////////////////////////////////////////////////////////////////////// + + class Mutex + { + public: + Mutex() LOKI_THREADS_MUTEX_CTOR(mtx_) + { + LOKI_THREADS_MUTEX_INIT(&mtx_); + } + ~Mutex() + { + LOKI_THREADS_MUTEX_DELETE(&mtx_); + } + void Lock() + { + LOKI_THREADS_MUTEX_LOCK(&mtx_); + } + void Unlock() + { + LOKI_THREADS_MUTEX_UNLOCK(&mtx_); + } + private: + /// Copy-constructor not implemented. + Mutex(const Mutex &); + /// Copy-assignement operator not implemented. + Mutex & operator = (const Mutex &); + LOKI_THREADS_MUTEX(mtx_) + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// \class SingleThreaded + /// + /// \ingroup ThreadingGroup + /// Implementation of the ThreadingModel policy used by various classes + /// Implements a single-threaded model; no synchronization + //////////////////////////////////////////////////////////////////////////////// + template <class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX> + class SingleThreaded + { + public: + /// \struct Lock + /// Dummy Lock class + struct Lock + { + Lock() {} + explicit Lock(const SingleThreaded&) {} + explicit Lock(const SingleThreaded*) {} + }; + + typedef Host VolatileType; + + typedef int IntType; + + static IntType AtomicAdd(volatile IntType& lval, const IntType val) + { return lval += val; } + + static IntType AtomicSubtract(volatile IntType& lval, const IntType val) + { return lval -= val; } + + static IntType AtomicMultiply(volatile IntType& lval, const IntType val) + { return lval *= val; } + + static IntType AtomicDivide(volatile IntType& lval, const IntType val) + { return lval /= val; } + + static IntType AtomicIncrement(volatile IntType& lval) + { return ++lval; } + + static IntType AtomicDecrement(volatile IntType& lval) + { return --lval; } + + static void AtomicAssign(volatile IntType & lval, const IntType val) + { lval = val; } + + static void AtomicAssign(IntType & lval, volatile IntType & val) + { lval = val; } + + static IntType AtomicAdd(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) + { + lval += val; + matches = ( lval == compare ); + return lval; + } + + static IntType AtomicSubtract(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) + { + lval -= val; + matches = ( lval == compare ); + return lval; + } + + static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) + { + lval *= val; + matches = ( lval == compare ); + return lval; + } + + static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) + { + lval /= val; + matches = ( lval == compare ); + return lval; + } + + static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) + { + ++lval; + matches = ( lval == compare ); + return lval; + } + + static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches ) + { + --lval; + matches = ( lval == compare ); + return lval; + } + + }; + + +#if defined(LOKI_WINDOWS_H) || defined(LOKI_PTHREAD_H) + + //////////////////////////////////////////////////////////////////////////////// + /// \class ObjectLevelLockable + /// + /// \ingroup ThreadingGroup + /// Implementation of the ThreadingModel policy used by various classes + /// Implements a object-level locking scheme + //////////////////////////////////////////////////////////////////////////////// + template < class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX > + class ObjectLevelLockable + { + mutable MutexPolicy mtx_; + + public: + ObjectLevelLockable() : mtx_() {} + + ObjectLevelLockable(const ObjectLevelLockable&) : mtx_() {} + + ~ObjectLevelLockable() {} + + class Lock; + friend class Lock; + + /// \struct Lock + /// Lock class to lock on object level + class Lock + { + public: + + /// Lock object + explicit Lock(const ObjectLevelLockable& host) : host_(host) + { + host_.mtx_.Lock(); + } + + /// Lock object + explicit Lock(const ObjectLevelLockable* host) : host_(*host) + { + host_.mtx_.Lock(); + } + + /// Unlock object + ~Lock() + { + host_.mtx_.Unlock(); + } + + private: + /// private by design of the object level threading + Lock(); + Lock(const Lock&); + Lock& operator=(const Lock&); + const ObjectLevelLockable& host_; + }; + + typedef volatile Host VolatileType; + + typedef LOKI_THREADS_LONG IntType; + + LOKI_THREADS_ATOMIC_FUNCTIONS + + }; + +#ifdef LOKI_PTHREAD_H + template <class Host, class MutexPolicy> + pthread_mutex_t ObjectLevelLockable<Host, MutexPolicy>::atomic_mutex_ = PTHREAD_MUTEX_INITIALIZER; +#endif + + //////////////////////////////////////////////////////////////////////////////// + /// \class ClassLevelLockable + /// + /// \ingroup ThreadingGroup + /// Implementation of the ThreadingModel policy used by various classes + /// Implements a class-level locking scheme + //////////////////////////////////////////////////////////////////////////////// + template <class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX > + class ClassLevelLockable + { + struct Initializer + { + bool init_; + MutexPolicy mtx_; + + Initializer() : init_(false), mtx_() + { + init_ = true; + } + + ~Initializer() + { + assert(init_); + } + }; + + static Initializer initializer_; + + public: + + class Lock; + friend class Lock; + + /// \struct Lock + /// Lock class to lock on class level + class Lock + { + public: + + /// Lock class + Lock() + { + assert(initializer_.init_); + initializer_.mtx_.Lock(); + } + + /// Lock class + explicit Lock(const ClassLevelLockable&) + { + assert(initializer_.init_); + initializer_.mtx_.Lock(); + } + + /// Lock class + explicit Lock(const ClassLevelLockable*) + { + assert(initializer_.init_); + initializer_.mtx_.Lock(); + } + + /// Unlock class + ~Lock() + { + assert(initializer_.init_); + initializer_.mtx_.Unlock(); + } + + private: + Lock(const Lock&); + Lock& operator=(const Lock&); + }; + + typedef volatile Host VolatileType; + + typedef LOKI_THREADS_LONG IntType; + + LOKI_THREADS_ATOMIC_FUNCTIONS + + }; + +#ifdef LOKI_PTHREAD_H + template <class Host, class MutexPolicy> + pthread_mutex_t ClassLevelLockable<Host, MutexPolicy>::atomic_mutex_ = PTHREAD_MUTEX_INITIALIZER; +#endif + + template < class Host, class MutexPolicy > + typename ClassLevelLockable< Host, MutexPolicy >::Initializer + ClassLevelLockable< Host, MutexPolicy >::initializer_; + +#endif // #if defined(LOKI_WINDOWS_H) || defined(LOKI_PTHREAD_H) + +} // namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/Tuple.h b/shared/loki/Tuple.h new file mode 100644 index 00000000..47fc19e2 --- /dev/null +++ b/shared/loki/Tuple.h @@ -0,0 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: June 20, 2001 + +//////////////////////////////////////////////////////////////////////////////// +// This file is intentionally left empty +// Due to compiler limitations, its contents has been moved to +// HierarchyGenerators.h +//////////////////////////////////////////////////////////////////////////////// diff --git a/shared/loki/TypeManip.h b/shared/loki/TypeManip.h new file mode 100644 index 00000000..e08b4e03 --- /dev/null +++ b/shared/loki/TypeManip.h @@ -0,0 +1,284 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_TYPEMANIP_INC_ +#define LOKI_TYPEMANIP_INC_ + +// $Id: TypeManip.h 749 2006-10-17 19:49:26Z syntheticpp $ + + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template Int2Type +// Converts each integral constant into a unique type +// Invocation: Int2Type<v> where v is a compile-time constant integral +// Defines 'value', an enum that evaluates to v +//////////////////////////////////////////////////////////////////////////////// + + template <int v> + struct Int2Type + { + enum { value = v }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Type2Type +// Converts each type into a unique, insipid type +// Invocation Type2Type<T> where T is a type +// Defines the type OriginalType which maps back to T +//////////////////////////////////////////////////////////////////////////////// + + template <typename T> + struct Type2Type + { + typedef T OriginalType; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Select +// Selects one of two types based upon a boolean constant +// Invocation: Select<flag, T, U>::Result +// where: +// flag is a compile-time boolean constant +// T and U are types +// Result evaluates to T if flag is true, and to U otherwise. +//////////////////////////////////////////////////////////////////////////////// + + template <bool flag, typename T, typename U> + struct Select + { + typedef T Result; + }; + template <typename T, typename U> + struct Select<false, T, U> + { + typedef U Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template IsSameType +// Return true iff two given types are the same +// Invocation: SameType<T, U>::value +// where: +// T and U are types +// Result evaluates to true iff U == T (types equal) +//////////////////////////////////////////////////////////////////////////////// + + template <typename T, typename U> + struct IsSameType + { + enum { value = false }; + }; + + template <typename T> + struct IsSameType<T,T> + { + enum { value = true }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + template <class T, class U> + struct ConversionHelper + { + typedef char Small; + struct Big { char dummy[2]; }; + static Big Test(...); + static Small Test(U); + static T MakeT(); + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template Conversion +// Figures out the conversion relationships between two types +// Invocations (T and U are types): +// a) Conversion<T, U>::exists +// returns (at compile time) true if there is an implicit conversion from T +// to U (example: Derived to Base) +// b) Conversion<T, U>::exists2Way +// returns (at compile time) true if there are both conversions from T +// to U and from U to T (example: int to char and back) +// c) Conversion<T, U>::sameType +// returns (at compile time) true if T and U represent the same type +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + + template <class T, class U> + struct Conversion + { + typedef Private::ConversionHelper<T, U> H; +#ifndef __MWERKS__ + enum { exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))) }; +#else + enum { exists = false }; +#endif + enum { exists2Way = exists && Conversion<U, T>::exists }; + enum { sameType = false }; + }; + + template <class T> + struct Conversion<T, T> + { + enum { exists = 1, exists2Way = 1, sameType = 1 }; + }; + + template <class T> + struct Conversion<void, T> + { + enum { exists = 0, exists2Way = 0, sameType = 0 }; + }; + + template <class T> + struct Conversion<T, void> + { + enum { exists = 0, exists2Way = 0, sameType = 0 }; + }; + + template <> + struct Conversion<void, void> + { + public: + enum { exists = 1, exists2Way = 1, sameType = 1 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template SuperSubclass +// Invocation: SuperSubclass<B, D>::value where B and D are types. +// Returns true if B is a public base of D, or if B and D are aliases of the +// same type. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +template <class T, class U> +struct SuperSubclass +{ + enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists && + !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) }; +}; + +template <> +struct SuperSubclass<void, void> +{ + enum { value = false }; +}; + +template <class U> +struct SuperSubclass<void, U> +{ + enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists && + !::Loki::Conversion<const volatile void*, const volatile void*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) }; +}; + +template <class T> +struct SuperSubclass<T, void> +{ + enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists && + !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template SuperSubclassStrict +// Invocation: SuperSubclassStrict<B, D>::value where B and D are types. +// Returns true if B is a public base of D. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +template<class T,class U> +struct SuperSubclassStrict +{ + enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists && + !::Loki::Conversion<const volatile T*, const volatile void*>::sameType && + !::Loki::Conversion<const volatile T*, const volatile U*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) }; +}; + +template<> +struct SuperSubclassStrict<void, void> +{ + enum { value = false }; +}; + +template<class U> +struct SuperSubclassStrict<void, U> +{ + enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists && + !::Loki::Conversion<const volatile void*, const volatile void*>::sameType && + !::Loki::Conversion<const volatile void*, const volatile U*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) }; +}; + +template<class T> +struct SuperSubclassStrict<T, void> +{ + enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists && + !::Loki::Conversion<const volatile T*, const volatile void*>::sameType && + !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) }; + + // Dummy enum to make sure that both classes are fully defined. + enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) }; +}; + + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D, or if B and D are aliases of the +// same type. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +// Deprecated: Use SuperSubclass class template instead. +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_SUPERSUBCLASS(T, U) \ + ::Loki::SuperSubclass<T,U>::value + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS_STRICT +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +// Deprecated: Use SuperSubclassStrict class template instead. +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_SUPERSUBCLASS_STRICT(T, U) \ + ::Loki::SuperSubclassStrict<T,U>::value + + +#endif // end file guardian + diff --git a/shared/loki/TypeTraits.h b/shared/loki/TypeTraits.h new file mode 100644 index 00000000..a592cab9 --- /dev/null +++ b/shared/loki/TypeTraits.h @@ -0,0 +1,2228 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_TYPETRAITS_INC_ +#define LOKI_TYPETRAITS_INC_ + +// $Id: TypeTraits.h 835 2007-08-02 19:39:02Z syntheticpp $ + + +#include "Typelist.h" +#include "Sequence.h" + +#if (defined _MSC_VER) && (_MSC_VER < 1400) +#include <string> +#endif + + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4180 ) //qualifier applied to function type has no meaning; ignored +#endif + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomUnsignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomUnsignedInt<T> where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template <typename T> + struct IsCustomUnsignedInt + { + enum { value = 0 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomSignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomSignedInt<T> where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in signed +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template <typename T> + struct IsCustomSignedInt + { + enum { value = 0 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomFloat +// Offers a means to integrate nonstandard floating point types with the +// TypeTraits class template defined below. +// Invocation: IsCustomFloat<T> where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in +// floating point type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template <typename T> + struct IsCustomFloat + { + enum { value = 0 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// Helper types for class template TypeTraits defined below +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { +#ifndef LOKI_DISABLE_TYPELIST_MACROS + typedef LOKI_TYPELIST_4(unsigned char, unsigned short int,unsigned int, unsigned long int) + StdUnsignedInts; + typedef LOKI_TYPELIST_4(signed char, short int,int, long int) + StdSignedInts; + typedef LOKI_TYPELIST_3(bool, char, wchar_t) + StdOtherInts; + typedef LOKI_TYPELIST_3(float, double, long double) + StdFloats; +#else + typedef Loki::Seq<unsigned char, unsigned short int,unsigned int, unsigned long int>::Type + StdUnsignedInts; + typedef Loki::Seq<signed char, short int,int, long int>::Type + StdSignedInts; + typedef Loki::Seq<bool, char, wchar_t>::Type + StdOtherInts; + typedef Loki::Seq<float, double, long double>::Type + StdFloats; + +#endif + template <typename U> struct AddPointer + { + typedef U* Result; + }; + + template <typename U> struct AddPointer<U&> + { + typedef U* Result; + }; + + template <class U> struct AddReference + { + typedef U & Result; + }; + + template <class U> struct AddReference<U &> + { + typedef U & Result; + }; + + template <> struct AddReference<void> + { + typedef NullType Result; + }; + + template <class U> struct AddParameterType + { + typedef const U & Result; + }; + + template <class U> struct AddParameterType<U &> + { + typedef U & Result; + }; + + template <> struct AddParameterType<void> + { + typedef NullType Result; + }; + + template <typename T> + struct IsFunctionPointerRaw + {enum{result = 0};}; + + template <typename T> + struct IsFunctionPointerRaw<T(*)()> + {enum {result = 1};}; + + template <typename T, + typename P01> + struct IsFunctionPointerRaw<T(*)(P01)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02> + struct IsFunctionPointerRaw<T(*)( + P01, P02)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20)> + {enum {result = 1};}; + + template <typename T> + struct IsFunctionPointerRaw<T(*)( + ...)> + {enum {result = 1};}; + + template <typename T, + typename P01> + struct IsFunctionPointerRaw<T(*)( + P01, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02> + struct IsFunctionPointerRaw<T(*)( + P01, P02, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, ...)> + {enum {result = 1};}; + + template <typename T, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsFunctionPointerRaw<T(*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20, + ...)> + {enum {result = 1};}; + + + template <typename T> + struct IsMemberFunctionPointerRaw + {enum{result = 0};}; + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)()> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)(P01)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20)> + {enum {result = 1};}; + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)( + ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, ...)> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20, + ...)> + {enum {result = 1};}; + + // Const versions + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)() const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)(P01) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20) const> + {enum {result = 1};}; + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)( + ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, ...) const> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20, + ...) const> + {enum {result = 1};}; + + // Volatile versions + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)() volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)(P01) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20) volatile> + {enum {result = 1};}; + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)( + ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, ...) volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20, + ...) volatile> + {enum {result = 1};}; + + // Const volatile versions + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)() const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)(P01) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20) const volatile> + {enum {result = 1};}; + + template <typename T, typename S> + struct IsMemberFunctionPointerRaw<T (S::*)( + ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, ...) const volatile> + {enum {result = 1};}; + + template <typename T, typename S, + typename P01, typename P02, typename P03, typename P04, typename P05, + typename P06, typename P07, typename P08, typename P09, typename P10, + typename P11, typename P12, typename P13, typename P14, typename P15, + typename P16, typename P17, typename P18, typename P19, typename P20> + struct IsMemberFunctionPointerRaw<T (S::*)( + P01, P02, P03, P04, P05, + P06, P07, P08, P09, P10, + P11, P12, P13, P14, P15, + P16, P17, P18, P19, P20, + ...) const volatile> + {enum {result = 1};}; + + }// namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeTraits +// +// Figures out at compile time various properties of any given type +// Invocations (T is a type, TypeTraits<T>::Property): +// +// - isPointer : returns true if T is a pointer type +// - PointeeType : returns the type to which T points if T is a pointer +// type, NullType otherwise +// - isReference : returns true if T is a reference type +// - ReferredType : returns the type to which T refers if T is a reference +// type, NullType otherwise +// - isMemberPointer : returns true if T is a pointer to member type +// - isStdUnsignedInt: returns true if T is a standard unsigned integral type +// - isStdSignedInt : returns true if T is a standard signed integral type +// - isStdIntegral : returns true if T is a standard integral type +// - isStdFloat : returns true if T is a standard floating-point type +// - isStdArith : returns true if T is a standard arithmetic type +// - isStdFundamental: returns true if T is a standard fundamental type +// - isUnsignedInt : returns true if T is a unsigned integral type +// - isSignedInt : returns true if T is a signed integral type +// - isIntegral : returns true if T is a integral type +// - isFloat : returns true if T is a floating-point type +// - isArith : returns true if T is a arithmetic type +// - isFundamental : returns true if T is a fundamental type +// - ParameterType : returns the optimal type to be used as a parameter for +// functions that take Ts +// - isConst : returns true if T is a const-qualified type +// - NonConstType : Type with removed 'const' qualifier from T, if any +// - isVolatile : returns true if T is a volatile-qualified type +// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any +// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from +// T, if any +// - ParameterType : returns the optimal type to be used as a parameter +// for functions that take 'const T's +// +//////////////////////////////////////////////////////////////////////////////// + + template <typename T> + class TypeTraits + { + private: + + template <class U> struct ReferenceTraits + { + enum { result = false }; + typedef U ReferredType; + }; + + template <class U> struct ReferenceTraits<U&> + { + enum { result = true }; + typedef U ReferredType; + }; + + template <class U> struct PointerTraits + { + enum { result = false }; + typedef NullType PointeeType; + }; + + template <class U> struct PointerTraits<U*> + { + enum { result = true }; + typedef U PointeeType; + }; + + template <class U> struct PointerTraits<U*&> + { + enum { result = true }; + typedef U PointeeType; + }; + + template <class U> struct PToMTraits + { + enum { result = false }; + }; + + template <class U, class V> struct PToMTraits<U V::*> + { + enum { result = true }; + }; + + template <class U, class V> struct PToMTraits<U V::*&> + { + enum { result = true }; + }; + + template <class U> struct FunctionPointerTraits + { + enum{ result = Private::IsFunctionPointerRaw<U>::result }; + }; + + template <typename U> struct PToMFunctionTraits + { + enum{ result = Private::IsMemberFunctionPointerRaw<U>::result }; + }; + + template <class U> struct UnConst + { + typedef U Result; + enum { isConst = 0 }; + }; + + template <class U> struct UnConst<const U> + { + typedef U Result; + enum { isConst = 1 }; + }; + + template <class U> struct UnConst<const U&> + { + typedef U& Result; + enum { isConst = 1 }; + }; + + template <class U> struct UnVolatile + { + typedef U Result; + enum { isVolatile = 0 }; + }; + + template <class U> struct UnVolatile<volatile U> + { + typedef U Result; + enum { isVolatile = 1 }; + }; + + template <class U> struct UnVolatile<volatile U&> + { + typedef U& Result; + enum { isVolatile = 1 }; + }; + + public: + typedef typename UnConst<T>::Result + NonConstType; + typedef typename UnVolatile<T>::Result + NonVolatileType; + typedef typename UnVolatile<typename UnConst<T>::Result>::Result + UnqualifiedType; + typedef typename PointerTraits<UnqualifiedType>::PointeeType + PointeeType; + typedef typename ReferenceTraits<T>::ReferredType + ReferredType; + + enum { isConst = UnConst<T>::isConst }; + enum { isVolatile = UnVolatile<T>::isVolatile }; + enum { isReference = ReferenceTraits<UnqualifiedType>::result }; + enum { isFunction = FunctionPointerTraits<typename Private::AddPointer<T>::Result >::result }; + enum { isFunctionPointer= FunctionPointerTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result }; + enum { isMemberFunctionPointer= PToMFunctionTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result }; + enum { isMemberPointer = PToMTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result || + isMemberFunctionPointer }; + enum { isPointer = PointerTraits< + typename ReferenceTraits<UnqualifiedType>::ReferredType >::result || + isFunctionPointer }; + + enum { isStdUnsignedInt = TL::IndexOf<Private::StdUnsignedInts, UnqualifiedType>::value >= 0 || + TL::IndexOf<Private::StdUnsignedInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdSignedInt = TL::IndexOf<Private::StdSignedInts, UnqualifiedType>::value >= 0 || + TL::IndexOf<Private::StdSignedInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || + TL::IndexOf<Private::StdOtherInts, UnqualifiedType>::value >= 0 || + TL::IndexOf<Private::StdOtherInts, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdFloat = TL::IndexOf<Private::StdFloats, UnqualifiedType>::value >= 0 || + TL::IndexOf<Private::StdFloats, + typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0}; + enum { isStdArith = isStdIntegral || isStdFloat }; + enum { isStdFundamental = isStdArith || isStdFloat || Conversion<T, void>::sameType }; + + enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<UnqualifiedType>::value }; + enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<UnqualifiedType>::value }; + enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; + enum { isFloat = isStdFloat || IsCustomFloat<UnqualifiedType>::value }; + enum { isArith = isIntegral || isFloat }; + enum { isFundamental = isStdFundamental || isArith }; + + typedef typename Select<isStdArith || isPointer || isMemberPointer, T, + typename Private::AddParameterType<T>::Result>::Result + ParameterType; + }; +} + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif // _MSC_VER + + +#endif // end file guardian + diff --git a/shared/loki/Typelist.h b/shared/loki/Typelist.h new file mode 100644 index 00000000..6a885927 --- /dev/null +++ b/shared/loki/Typelist.h @@ -0,0 +1,459 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_TYPELIST_INC_ +#define LOKI_TYPELIST_INC_ + +// $Id: Typelist.h 749 2006-10-17 19:49:26Z syntheticpp $ + + +#include "NullType.h" +#include "TypeManip.h" +#include "TypelistMacros.h" + + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template Typelist +// The building block of typelists of any length +// Use it through the LOKI_TYPELIST_NN macros +// Defines nested types: +// Head (first element, a non-typelist type by convention) +// Tail (second element, can be another typelist) +//////////////////////////////////////////////////////////////////////////////// + + template <class T, class U> + struct Typelist + { + typedef T Head; + typedef U Tail; + }; + +// Typelist utility algorithms + + namespace TL + { + +//////////////////////////////////////////////////////////////////////////////// +// class template MakeTypelist +// Takes a number of arguments equal to its numeric suffix +// The arguments are type names. +// MakeTypelist<T1, T2, ...>::Result +// returns a typelist that is of T1, T2, ... +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename T1 = NullType, typename T2 = NullType, typename T3 = NullType, + typename T4 = NullType, typename T5 = NullType, typename T6 = NullType, + typename T7 = NullType, typename T8 = NullType, typename T9 = NullType, + typename T10 = NullType, typename T11 = NullType, typename T12 = NullType, + typename T13 = NullType, typename T14 = NullType, typename T15 = NullType, + typename T16 = NullType, typename T17 = NullType, typename T18 = NullType + > + struct MakeTypelist + { + private: + typedef typename MakeTypelist + < + T2 , T3 , T4 , + T5 , T6 , T7 , + T8 , T9 , T10, + T11, T12, T13, + T14, T15, T16, + T17, T18 + > + ::Result TailResult; + + public: + typedef Typelist<T1, TailResult> Result; + }; + + template<> + struct MakeTypelist<> + { + typedef NullType Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Length +// Computes the length of a typelist +// Invocation (TList is a typelist): +// Length<TList>::value +// returns a compile-time constant containing the length of TList, not counting +// the end terminator (which by convention is NullType) +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> struct Length; + template <> struct Length<NullType> + { + enum { value = 0 }; + }; + + template <class T, class U> + struct Length< Typelist<T, U> > + { + enum { value = 1 + Length<U>::value }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAt +// Finds the type at a given index in a typelist +// Invocation (TList is a typelist and index is a compile-time integral +// constant): +// TypeAt<TList, index>::Result +// returns the type in position 'index' in TList +// If you pass an out-of-bounds index, the result is a compile-time error +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, unsigned int index> struct TypeAt; + + template <class Head, class Tail> + struct TypeAt<Typelist<Head, Tail>, 0> + { + typedef Head Result; + }; + + template <class Head, class Tail, unsigned int i> + struct TypeAt<Typelist<Head, Tail>, i> + { + typedef typename TypeAt<Tail, i - 1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAtNonStrict +// Finds the type at a given index in a typelist +// Invocations (TList is a typelist and index is a compile-time integral +// constant): +// a) TypeAt<TList, index>::Result +// returns the type in position 'index' in TList, or NullType if index is +// out-of-bounds +// b) TypeAt<TList, index, D>::Result +// returns the type in position 'index' in TList, or D if index is out-of-bounds +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, unsigned int index, + typename DefaultType = NullType> + struct TypeAtNonStrict + { + typedef DefaultType Result; + }; + + template <class Head, class Tail, typename DefaultType> + struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType> + { + typedef Head Result; + }; + + template <class Head, class Tail, unsigned int i, typename DefaultType> + struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType> + { + typedef typename + TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template IndexOf +// Finds the index of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// IndexOf<TList, T>::value +// returns the position of T in TList, or NullType if T is not found in TList +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T> struct IndexOf; + + template <class T> + struct IndexOf<NullType, T> + { + enum { value = -1 }; + }; + + template <class T, class Tail> + struct IndexOf<Typelist<T, Tail>, T> + { + enum { value = 0 }; + }; + + template <class Head, class Tail, class T> + struct IndexOf<Typelist<Head, Tail>, T> + { + private: + enum { temp = IndexOf<Tail, T>::value }; + public: + enum { value = (temp == -1 ? -1 : 1 + temp) }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Append +// Appends a type or a typelist to another +// Invocation (TList is a typelist and T is either a type or a typelist): +// Append<TList, T>::Result +// returns a typelist that is TList followed by T and NullType-terminated +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T> struct Append; + + template <> struct Append<NullType, NullType> + { + typedef NullType Result; + }; + + template <class T> struct Append<NullType, T> + { + typedef Typelist<T,NullType> Result; + }; + + template <class Head, class Tail> + struct Append<NullType, Typelist<Head, Tail> > + { + typedef Typelist<Head, Tail> Result; + }; + + template <class Head, class Tail, class T> + struct Append<Typelist<Head, Tail>, T> + { + typedef Typelist<Head, + typename Append<Tail, T>::Result> + Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Erase +// Erases the first occurence, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// Erase<TList, T>::Result +// returns a typelist that is TList without the first occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T> struct Erase; + + template <class T> // Specialization 1 + struct Erase<NullType, T> + { + typedef NullType Result; + }; + + template <class T, class Tail> // Specialization 2 + struct Erase<Typelist<T, Tail>, T> + { + typedef Tail Result; + }; + + template <class Head, class Tail, class T> // Specialization 3 + struct Erase<Typelist<Head, Tail>, T> + { + typedef Typelist<Head, + typename Erase<Tail, T>::Result> + Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template EraseAll +// Erases all first occurences, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// EraseAll<TList, T>::Result +// returns a typelist that is TList without any occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T> struct EraseAll; + template <class T> + struct EraseAll<NullType, T> + { + typedef NullType Result; + }; + template <class T, class Tail> + struct EraseAll<Typelist<T, Tail>, T> + { + // Go all the way down the list removing the type + typedef typename EraseAll<Tail, T>::Result Result; + }; + template <class Head, class Tail, class T> + struct EraseAll<Typelist<Head, Tail>, T> + { + // Go all the way down the list removing the type + typedef Typelist<Head, + typename EraseAll<Tail, T>::Result> + Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDuplicates +// Removes all duplicate types in a typelist +// Invocation (TList is a typelist): +// NoDuplicates<TList, T>::Result +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> struct NoDuplicates; + + template <> struct NoDuplicates<NullType> + { + typedef NullType Result; + }; + + template <class Head, class Tail> + struct NoDuplicates< Typelist<Head, Tail> > + { + private: + typedef typename NoDuplicates<Tail>::Result L1; + typedef typename Erase<L1, Head>::Result L2; + public: + typedef Typelist<Head, L2> Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Replace +// Replaces the first occurence of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace<TList, T, U>::Result +// returns a typelist in which the first occurence of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T, class U> struct Replace; + + template <class T, class U> + struct Replace<NullType, T, U> + { + typedef NullType Result; + }; + + template <class T, class Tail, class U> + struct Replace<Typelist<T, Tail>, T, U> + { + typedef Typelist<U, Tail> Result; + }; + + template <class Head, class Tail, class T, class U> + struct Replace<Typelist<Head, Tail>, T, U> + { + typedef Typelist<Head, + typename Replace<Tail, T, U>::Result> + Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ReplaceAll +// Replaces all occurences of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace<TList, T, U>::Result +// returns a typelist in which all occurences of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T, class U> struct ReplaceAll; + + template <class T, class U> + struct ReplaceAll<NullType, T, U> + { + typedef NullType Result; + }; + + template <class T, class Tail, class U> + struct ReplaceAll<Typelist<T, Tail>, T, U> + { + typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result; + }; + + template <class Head, class Tail, class T, class U> + struct ReplaceAll<Typelist<Head, Tail>, T, U> + { + typedef Typelist<Head, + typename ReplaceAll<Tail, T, U>::Result> + Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Reverse +// Reverses a typelist +// Invocation (TList is a typelist): +// Reverse<TList>::Result +// returns a typelist that is TList reversed +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> struct Reverse; + + template <> + struct Reverse<NullType> + { + typedef NullType Result; + }; + + template <class Head, class Tail> + struct Reverse< Typelist<Head, Tail> > + { + typedef typename Append< + typename Reverse<Tail>::Result, Head>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template MostDerived +// Finds the type in a typelist that is the most derived from a given type +// Invocation (TList is a typelist, T is a type): +// MostDerived<TList, T>::Result +// returns the type in TList that's the most derived from T +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, class T> struct MostDerived; + + template <class T> + struct MostDerived<NullType, T> + { + typedef T Result; + }; + + template <class Head, class Tail, class T> + struct MostDerived<Typelist<Head, Tail>, T> + { + private: + typedef typename MostDerived<Tail, T>::Result Candidate; + public: + typedef typename Select< + SuperSubclass<Candidate,Head>::value, + Head, Candidate>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DerivedToFront +// Arranges the types in a typelist so that the most derived types appear first +// Invocation (TList is a typelist): +// DerivedToFront<TList>::Result +// returns the reordered TList +//////////////////////////////////////////////////////////////////////////////// + + template <class TList> struct DerivedToFront; + + template <> + struct DerivedToFront<NullType> + { + typedef NullType Result; + }; + + template <class Head, class Tail> + struct DerivedToFront< Typelist<Head, Tail> > + { + private: + typedef typename MostDerived<Tail, Head>::Result + TheMostDerived; + typedef typename Replace<Tail, + TheMostDerived, Head>::Result Temp; + typedef typename DerivedToFront<Temp>::Result L; + public: + typedef Typelist<TheMostDerived, L> Result; + }; + + } // namespace TL +} // namespace Loki + + +#endif // end file guardian + diff --git a/shared/loki/TypelistMacros.h b/shared/loki/TypelistMacros.h new file mode 100644 index 00000000..6c14b348 --- /dev/null +++ b/shared/loki/TypelistMacros.h @@ -0,0 +1,353 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_TYPELISTMACROS_INC_ +#define LOKI_TYPELISTMACROS_INC_ + +// $Id: TypelistMacros.h 749 2006-10-17 19:49:26Z syntheticpp $ + + +//#define LOKI_DISABLE_TYPELIST_MACROS +#ifndef LOKI_DISABLE_TYPELIST_MACROS + +//////////////////////////////////////////////////////////////////////////////// +// macros LOKI_TYPELIST_1, LOKI_TYPELIST_2, ... LOKI_TYPELIST_50 +// Each takes a number of arguments equal to its numeric suffix +// The arguments are type names. LOKI_TYPELIST_NN generates a typelist containing +// all types passed as arguments, in that order. +// Example: LOKI_TYPELIST_2(char, int) generates a type containing char and int. +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType> + +#define LOKI_TYPELIST_2(T1, T2) ::Loki::Typelist<T1, LOKI_TYPELIST_1(T2) > + +#define LOKI_TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, LOKI_TYPELIST_2(T2, T3) > + +#define LOKI_TYPELIST_4(T1, T2, T3, T4) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_3(T2, T3, T4) > + +#define LOKI_TYPELIST_5(T1, T2, T3, T4, T5) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_4(T2, T3, T4, T5) > + +#define LOKI_TYPELIST_6(T1, T2, T3, T4, T5, T6) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_5(T2, T3, T4, T5, T6) > + +#define LOKI_TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_6(T2, T3, T4, T5, T6, T7) > + +#define LOKI_TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) > + +#define LOKI_TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9) > + +#define LOKI_TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10) > + +#define LOKI_TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_10(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) > + +#define LOKI_TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_11(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12) > + +#define LOKI_TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_12(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13) > + +#define LOKI_TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_13(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14) > + +#define LOKI_TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_14(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15) > + +#define LOKI_TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_15(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16) > + +#define LOKI_TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_16(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17) > + +#define LOKI_TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_17(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18) > + +#define LOKI_TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_18(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19) > + +#define LOKI_TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_19(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) > + +#define LOKI_TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_20(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) > + +#define LOKI_TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_21(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) > + +#define LOKI_TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_22(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) > + +#define LOKI_TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_23(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) > + +#define LOKI_TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_24(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25) > + +#define LOKI_TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_25(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26) > + +#define LOKI_TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_26(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27) > + +#define LOKI_TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_27(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28) > + +#define LOKI_TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_28(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29) > + +#define LOKI_TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_29(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) > + +#define LOKI_TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_30(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) > + +#define LOKI_TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_31(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) > + +#define LOKI_TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_32(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) > + +#define LOKI_TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_33(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) > + +#define LOKI_TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_34(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35) > + +#define LOKI_TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_35(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36) > + +#define LOKI_TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_36(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37) > + +#define LOKI_TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_37(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38) > + +#define LOKI_TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_38(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39) > + +#define LOKI_TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_39(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) > + +#define LOKI_TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_40(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) > + +#define LOKI_TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_41(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) > + +#define LOKI_TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_42(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) > + +#define LOKI_TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_43(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) > + +#define LOKI_TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_44(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45) > + +#define LOKI_TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_45(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46) > + +#define LOKI_TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_46(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47) > + +#define LOKI_TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_47(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48) > + +#define LOKI_TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_48(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49) > + +#define LOKI_TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \ + ::Loki::Typelist<T1, LOKI_TYPELIST_49(T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) > + +#endif //LOKI_DISABLE_TYPELIST_MACROS + +#endif // end file guardian + diff --git a/shared/loki/Visitor.h b/shared/loki/Visitor.h new file mode 100644 index 00000000..4425a9fa --- /dev/null +++ b/shared/loki/Visitor.h @@ -0,0 +1,355 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_VISITOR_INC_ +#define LOKI_VISITOR_INC_ + +// $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $ + + +/// \defgroup VisitorGroup Visitor + +#include "Typelist.h" +#include "HierarchyGenerators.h" + +namespace Loki +{ + +//////////////////////////////////////////////////////////////////////////////// +/// \class BaseVisitor +/// +/// \ingroup VisitorGroup +/// The base class of any Acyclic Visitor +//////////////////////////////////////////////////////////////////////////////// + + class BaseVisitor + { + public: + virtual ~BaseVisitor() {} + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \class Visitor +/// +/// \ingroup VisitorGroup +/// The building block of Acyclic Visitor +/// +/// \par Usage +/// +/// Defining the visitable class: +/// +/// \code +/// class RasterBitmap : public BaseVisitable<> +/// { +/// public: +/// LOKI_DEFINE_VISITABLE() +/// }; +/// \endcode +/// +/// Way 1 to define a visitor: +/// \code +/// class SomeVisitor : +/// public BaseVisitor // required +/// public Visitor<RasterBitmap>, +/// public Visitor<Paragraph> +/// { +/// public: +/// void Visit(RasterBitmap&); // visit a RasterBitmap +/// void Visit(Paragraph &); // visit a Paragraph +/// }; +/// \endcode +/// +/// Way 2 to define the visitor: +/// \code +/// class SomeVisitor : +/// public BaseVisitor // required +/// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)> +/// { +/// public: +/// void Visit(RasterBitmap&); // visit a RasterBitmap +/// void Visit(Paragraph &); // visit a Paragraph +/// }; +/// \endcode +/// +/// Way 3 to define the visitor: +/// \code +/// class SomeVisitor : +/// public BaseVisitor // required +/// public Visitor<Seq<RasterBitmap, Paragraph>::Type> +/// { +/// public: +/// void Visit(RasterBitmap&); // visit a RasterBitmap +/// void Visit(Paragraph &); // visit a Paragraph +/// }; +/// \endcode +/// +/// \par Using const visit functions: +/// +/// Defining the visitable class (true for const): +/// +/// \code +/// class RasterBitmap : public BaseVisitable<void, DefaultCatchAll, true> +/// { +/// public: +/// LOKI_DEFINE_CONST_VISITABLE() +/// }; +/// \endcode +/// +/// Defining the visitor which only calls const member functions: +/// \code +/// class SomeVisitor : +/// public BaseVisitor // required +/// public Visitor<RasterBitmap, void, true>, +/// { +/// public: +/// void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function +/// }; +/// \endcode +/// +/// \par Example: +/// +/// test/Visitor/main.cpp +//////////////////////////////////////////////////////////////////////////////// + + template <class T, typename R = void, bool ConstVisit = false> + class Visitor; + + template <class T, typename R> + class Visitor<T, R, false> + { + public: + typedef R ReturnType; + typedef T ParamType; + virtual ~Visitor() {} + virtual ReturnType Visit(ParamType&) = 0; + }; + + template <class T, typename R> + class Visitor<T, R, true> + { + public: + typedef R ReturnType; + typedef const T ParamType; + virtual ~Visitor() {} + virtual ReturnType Visit(ParamType&) = 0; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Visitor (specialization) +// This specialization is not present in the book. It makes it easier to define +// Visitors for multiple types in a shot by using a typelist. Example: +// +// class SomeVisitor : +// public BaseVisitor // required +// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)> +// { +// public: +// void Visit(RasterBitmap&); // visit a RasterBitmap +// void Visit(Paragraph &); // visit a Paragraph +// }; +//////////////////////////////////////////////////////////////////////////////// + + template <class Head, class Tail, typename R> + class Visitor<Typelist<Head, Tail>, R, false> + : public Visitor<Head, R, false>, public Visitor<Tail, R, false> + { + public: + typedef R ReturnType; + // using Visitor<Head, R>::Visit; + // using Visitor<Tail, R>::Visit; + }; + + template <class Head, typename R> + class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false> + { + public: + typedef R ReturnType; + using Visitor<Head, R, false>::Visit; + }; + + template <class Head, class Tail, typename R> + class Visitor<Typelist<Head, Tail>, R, true> + : public Visitor<Head, R, true>, public Visitor<Tail, R, true> + { + public: + typedef R ReturnType; + // using Visitor<Head, R>::Visit; + // using Visitor<Tail, R>::Visit; + }; + + template <class Head, typename R> + class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true> + { + public: + typedef R ReturnType; + using Visitor<Head, R, true>::Visit; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitorImpl +// Implements non-strict visitation (you can implement only part of the Visit +// functions) +//////////////////////////////////////////////////////////////////////////////// + + template <class TList, typename R = void> class BaseVisitorImpl; + + template <class Head, class Tail, typename R> + class BaseVisitorImpl<Typelist<Head, Tail>, R> + : public Visitor<Head, R> + , public BaseVisitorImpl<Tail, R> + { + public: + // using BaseVisitorImpl<Tail, R>::Visit; + + virtual R Visit(Head&) + { return R(); } + }; + + template <class Head, typename R> + class BaseVisitorImpl<Typelist<Head, NullType>, R> + : public Visitor<Head, R> + { + public: + virtual R Visit(Head&) + { return R(); } + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitable +//////////////////////////////////////////////////////////////////////////////// + +template <typename R, typename Visited> +struct DefaultCatchAll +{ + static R OnUnknownVisitor(Visited&, BaseVisitor&) + { return R(); } +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template BaseVisitable +//////////////////////////////////////////////////////////////////////////////// + + template + < + typename R = void, + template <typename, class> class CatchAll = DefaultCatchAll, + bool ConstVisitable = false + > + class BaseVisitable; + + template<typename R,template <typename, class> class CatchAll> + class BaseVisitable<R, CatchAll, false> + { + public: + typedef R ReturnType; + virtual ~BaseVisitable() {} + virtual ReturnType Accept(BaseVisitor&) = 0; + + protected: // give access only to the hierarchy + template <class T> + static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) + { + // Apply the Acyclic Visitor + if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest)) + { + return p->Visit(visited); + } + return CatchAll<R, T>::OnUnknownVisitor(visited, guest); + } + }; + + template<typename R,template <typename, class> class CatchAll> + class BaseVisitable<R, CatchAll, true> + { + public: + typedef R ReturnType; + virtual ~BaseVisitable() {} + virtual ReturnType Accept(BaseVisitor&) const = 0; + + protected: // give access only to the hierarchy + template <class T> + static ReturnType AcceptImpl(const T& visited, BaseVisitor& guest) + { + // Apply the Acyclic Visitor + if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest)) + { + return p->Visit(visited); + } + return CatchAll<R, T>::OnUnknownVisitor(const_cast<T&>(visited), guest); + } + }; + + +//////////////////////////////////////////////////////////////////////////////// +/// \def LOKI_DEFINE_VISITABLE() +/// \ingroup VisitorGroup +/// Put it in every class that you want to make visitable +/// (in addition to deriving it from BaseVisitable<R>) +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_DEFINE_VISITABLE() \ + virtual ReturnType Accept(::Loki::BaseVisitor& guest) \ + { return AcceptImpl(*this, guest); } + +//////////////////////////////////////////////////////////////////////////////// +/// \def LOKI_DEFINE_CONST_VISITABLE() +/// \ingroup VisitorGroup +/// Put it in every class that you want to make visitable by const member +/// functions (in addition to deriving it from BaseVisitable<R>) +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_DEFINE_CONST_VISITABLE() \ + virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \ + { return AcceptImpl(*this, guest); } + +//////////////////////////////////////////////////////////////////////////////// +/// \class CyclicVisitor +/// +/// \ingroup VisitorGroup +/// Put it in every class that you want to make visitable (in addition to +/// deriving it from BaseVisitable<R> +//////////////////////////////////////////////////////////////////////////////// + + template <typename R, class TList> + class CyclicVisitor : public Visitor<TList, R> + { + public: + typedef R ReturnType; + // using Visitor<TList, R>::Visit; + + template <class Visited> + ReturnType GenericVisit(Visited& host) + { + Visitor<Visited, ReturnType>& subObj = *this; + return subObj.Visit(host); + } + }; + +//////////////////////////////////////////////////////////////////////////////// +/// \def LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) +/// \ingroup VisitorGroup +/// Put it in every class that you want to make visitable by a cyclic visitor +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \ + virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \ + { return guest.GenericVisit(*this); } + +} // namespace Loki + + + +#endif // end file guardian + diff --git a/shared/loki/readme.txt b/shared/loki/readme.txt new file mode 100644 index 00000000..a35cf387 --- /dev/null +++ b/shared/loki/readme.txt @@ -0,0 +1,12 @@ +// $Id: readme.txt 753 2006-10-17 19:54:22Z syntheticpp $ + +The Golden Code +KEEPEN DER DAMDDEN FUGGERMUTTENS OTTEN DIS CODDEN FIL + +A compliant C++ compiler will compile all of this code as is. +See the respective vendor directories for code that actually compiles & runs. + +Note: Right now, this code contains CodeWarrior & gcc modifications, +which may be removed at a future point in time +(by moving them to a vendor specific implementation). +MKH
\ No newline at end of file diff --git a/shared/loki/static_check.h b/shared/loki/static_check.h new file mode 100644 index 00000000..51ce389e --- /dev/null +++ b/shared/loki/static_check.h @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Wesley Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_STATIC_CHECK_INC_ +#define LOKI_STATIC_CHECK_INC_ + +// $Id: static_check.h 752 2006-10-17 19:52:18Z syntheticpp $ + + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// Helper structure for the STATIC_CHECK macro +//////////////////////////////////////////////////////////////////////////////// + + template<int> struct CompileTimeError; + template<> struct CompileTimeError<true> {}; +} + +//////////////////////////////////////////////////////////////////////////////// +// macro STATIC_CHECK +// Invocation: STATIC_CHECK(expr, id) +// where: +// expr is a compile-time integral or pointer expression +// id is a C++ identifier that does not need to be defined +// If expr is zero, id will appear in a compile-time error message. +//////////////////////////////////////////////////////////////////////////////// + +#define LOKI_STATIC_CHECK(expr, msg) \ + { Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } + + +#endif // end file guardian + diff --git a/shared/shadow.cpp b/shared/shadow.cpp index 02a6a522..da7cfd99 100644 --- a/shared/shadow.cpp +++ b/shared/shadow.cpp @@ -30,9 +30,9 @@ public: private: ShadowlDllHandler() : - createShadowCopy(NULL), - releaseShadowCopy(NULL), - hShadow(NULL) + createShadowCopy(NULL), + releaseShadowCopy(NULL), + hShadow(NULL) { //get a handle to the DLL module containing the required functionality hShadow = ::LoadLibrary(L"Shadow.dll"); @@ -53,7 +53,7 @@ private: ShadowCopy::ShadowCopy() : - backupHandle(NULL) {} + backupHandle(NULL) {} ShadowCopy::~ShadowCopy() diff --git a/shared/shadow.h b/shared/shadow.h index 15fd4d9d..8affdebf 100644 --- a/shared/shadow.h +++ b/shared/shadow.h @@ -11,21 +11,21 @@ header should be used in the windows build only! namespace FreeFileSync { - class ShadowCopy //buffer access to Windows Volume Shadow Copy Service - { - public: - ShadowCopy(); - ~ShadowCopy(); +class ShadowCopy //buffer access to Windows Volume Shadow Copy Service +{ +public: + ShadowCopy(); + ~ShadowCopy(); - Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy + Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy - private: - bool isOkay(); +private: + bool isOkay(); - Zstring realVolumeLast; //buffer last volume name - Zstring shadowVolumeLast; //buffer last created shadow volume - void* backupHandle; - }; + Zstring realVolumeLast; //buffer last volume name + Zstring shadowVolumeLast; //buffer last created shadow volume + void* backupHandle; +}; } #endif // SHADOW_H_INCLUDED diff --git a/shared/standardPaths.cpp b/shared/standardPaths.cpp index 54774673..3d5cfdb5 100644 --- a/shared/standardPaths.cpp +++ b/shared/standardPaths.cpp @@ -2,20 +2,23 @@ #include <wx/stdpaths.h> #include <wx/filename.h> #include "systemConstants.h" +#include "stringConv.h" + +using namespace FreeFileSync; wxString assembleFileForUserData(const wxString fileName) { - static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("uninstall.exe")); //this check is a bit lame... + static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("uninstall.exe")); //this check is a bit lame... if (isPortableVersion) //use current working directory - return wxString(wxT(".")) + globalFunctions::FILE_NAME_SEPARATOR + fileName; + return wxString(wxT(".")) + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + fileName; else //usen OS' standard paths { wxString userDirectory = wxStandardPathsBase::Get().GetUserDataDir(); - if (!userDirectory.EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR))) - userDirectory += globalFunctions::FILE_NAME_SEPARATOR; + if (!userDirectory.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR))) + userDirectory += zToWx(globalFunctions::FILE_NAME_SEPARATOR); if (!wxDirExists(userDirectory)) ::wxMkdir(userDirectory); //only top directory needs to be created: no recursion necessary diff --git a/shared/standardPaths.h b/shared/standardPaths.h index 64811246..34f6ab48 100644 --- a/shared/standardPaths.h +++ b/shared/standardPaths.h @@ -9,11 +9,11 @@ namespace FreeFileSync //------------------------------------------------------------------------------ //global functions //------------------------------------------------------------------------------ - const wxString& getGlobalConfigFile(); - const wxString& getDefaultLogDirectory(); - const wxString& getLastErrorTxtFile(); - const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator - const wxString& getConfigDir(); +const wxString& getGlobalConfigFile(); +const wxString& getDefaultLogDirectory(); +const wxString& getLastErrorTxtFile(); +const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator +const wxString& getConfigDir(); //------------------------------------------------------------------------------ } diff --git a/shared/stringConv.h b/shared/stringConv.h new file mode 100644 index 00000000..f4048aab --- /dev/null +++ b/shared/stringConv.h @@ -0,0 +1,104 @@ +#ifndef STRINGCONV_H_INCLUDED +#define STRINGCONV_H_INCLUDED + +#include <wx/string.h> +#include "zstring.h" + +namespace FreeFileSync +{ +//conversion from Zstring to wxString +wxString zToWx(const Zstring& str); +wxString zToWx(const DefaultChar* str); +wxString zToWx(DefaultChar ch); +//conversion from wxString to Zstring +Zstring wxToZ(const wxString& str); +Zstring wxToZ(const wxChar* str); +Zstring wxToZ(wxChar ch); + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//---------------Inline Implementation--------------------------------------------------- +inline +wxString zToWx(const Zstring& str) +{ +#ifdef ZSTRING_CHAR + return wxString::FromUTF8(str.c_str(), str.length()); +#elif defined ZSTRING_WIDE_CHAR + return wxString(str.c_str(), str.length()); +#endif +} + + +inline +wxString zToWx(const DefaultChar* str) +{ +#ifdef ZSTRING_CHAR + return wxString::FromUTF8(str); +#elif defined ZSTRING_WIDE_CHAR + return str; +#endif +} + + +inline +wxString zToWx(DefaultChar ch) +{ + return zToWx(Zstring() + ch); +} + +//----------------------------------------------------------------- +inline +Zstring wxToZ(const wxString& str) +{ +#ifdef ZSTRING_CHAR + return Zstring(str.ToUTF8()); +#elif defined ZSTRING_WIDE_CHAR + return Zstring(str.c_str(), str.length()); +#endif +} + + +inline +Zstring wxToZ(const wxChar* str) +{ +#ifdef ZSTRING_CHAR + return Zstring(wxString(str).ToUTF8()); +#elif defined ZSTRING_WIDE_CHAR + return str; +#endif +} + + +inline +Zstring wxToZ(wxChar ch) +{ + return wxToZ(wxString(ch)); +} +} + +#endif // STRINGCONV_H_INCLUDED diff --git a/shared/systemConstants.h b/shared/systemConstants.h index 84c1ae85..bae23d5a 100644 --- a/shared/systemConstants.h +++ b/shared/systemConstants.h @@ -2,7 +2,7 @@ #define SYSTEMCONSTANTS_H_INCLUDED #include "zstring.h" - +#include <wx/string.h> namespace globalFunctions { @@ -10,11 +10,11 @@ namespace globalFunctions // GLOBALS //------------------------------------------------ #ifdef FFS_WIN - const DefaultChar FILE_NAME_SEPARATOR = '\\'; - static const DefaultChar* const LINE_BREAK = L"\r\n"; //internal linkage +const DefaultChar FILE_NAME_SEPARATOR = '\\'; +static const wxChar* const LINE_BREAK = wxT("\r\n"); //internal linkage #elif defined FFS_LINUX - const DefaultChar FILE_NAME_SEPARATOR = '/'; - static const DefaultChar* const LINE_BREAK = "\n"; +const DefaultChar FILE_NAME_SEPARATOR = '/'; +static const wxChar* const LINE_BREAK = wxT("\n"); #endif } diff --git a/shared/systemFunctions.cpp b/shared/systemFunctions.cpp index 4fd17fc1..3d6915cd 100644 --- a/shared/systemFunctions.cpp +++ b/shared/systemFunctions.cpp @@ -11,27 +11,29 @@ #ifdef FFS_WIN -wxString FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try to get additional Windows error information +wxString FreeFileSync::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information { //determine error code if none was specified - const unsigned long lastErrorCode = lastError == 0 ? ::GetLastError() : lastError; + if (lastError == 0) + lastError = ::GetLastError(); - wxString output = wxString(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastErrorCode); + wxString output = wxString(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastError); WCHAR buffer[1001]; - if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, lastErrorCode, 0, buffer, 1001, NULL) != 0) + if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, lastError, 0, buffer, 1001, NULL) != 0) output += wxString(wxT(": ")) + buffer; return output; } #elif defined FFS_LINUX -wxString FreeFileSync::getLastErrorFormatted(const int lastError) //try to get additional Linux error information +wxString FreeFileSync::getLastErrorFormatted(int lastError) //try to get additional Linux error information { //determine error code if none was specified - const int lastErrorCode = lastError == 0 ? errno : lastError; + if (lastError == 0) + lastError = errno; //don't use :: errno is a macro! - wxString output = wxString(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastErrorCode); - output += wxString(wxT(": ")) + ::strerror(lastErrorCode); + wxString output = wxString(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastError); + output += wxString(wxT(": ")) + wxString::FromUTF8(::strerror(lastError)); return output; } #endif diff --git a/shared/systemFunctions.h b/shared/systemFunctions.h index b449d8d2..bfeacdd4 100644 --- a/shared/systemFunctions.h +++ b/shared/systemFunctions.h @@ -8,9 +8,9 @@ namespace FreeFileSync { #ifdef FFS_WIN - wxString getLastErrorFormatted(const unsigned long lastError = 0); //try to get additional Windows error information +wxString getLastErrorFormatted(unsigned long lastError = 0); //try to get additional Windows error information #elif defined FFS_LINUX - wxString getLastErrorFormatted(const int lastError = 0); //try to get additional Linux error information +wxString getLastErrorFormatted(int lastError = 0); //try to get additional Linux error information #endif } diff --git a/shared/tinyxml/tinyxml.cpp b/shared/tinyxml/tinyxml.cpp index aa13deec..033d13be 100644 --- a/shared/tinyxml/tinyxml.cpp +++ b/shared/tinyxml/tinyxml.cpp @@ -504,7 +504,7 @@ const TiXmlDocument* TiXmlNode::GetDocument() const TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; @@ -513,7 +513,7 @@ TiXmlElement::TiXmlElement (const char * _value) #ifdef TIXML_USE_STL TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; @@ -522,7 +522,7 @@ TiXmlElement::TiXmlElement( const std::string& _value ) TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) + : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; copy.CopyTo( this ); @@ -1418,7 +1418,7 @@ TiXmlNode* TiXmlText::Clone() const TiXmlDeclaration::TiXmlDeclaration( const char * _version, const char * _encoding, const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; @@ -1430,7 +1430,7 @@ TiXmlDeclaration::TiXmlDeclaration( const char * _version, TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; @@ -1440,7 +1440,7 @@ TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) + : TiXmlNode( TiXmlNode::DECLARATION ) { copy.CopyTo( this ); } diff --git a/shared/tinyxml/tinyxmlparser.cpp b/shared/tinyxml/tinyxmlparser.cpp index a601016a..503becde 100644 --- a/shared/tinyxml/tinyxmlparser.cpp +++ b/shared/tinyxml/tinyxmlparser.cpp @@ -433,11 +433,11 @@ const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncodi { const char* start = p; while ( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) { //(*name) += *p; // expensive ++p; @@ -588,11 +588,11 @@ bool TiXmlBase::StringEqual( const char* p, } const char* TiXmlBase::ReadText( const char* p, - TIXML_STRING * text, - bool trimWhiteSpace, - const char* endTag, - bool caseInsensitive, - TiXmlEncoding encoding ) + TIXML_STRING * text, + bool trimWhiteSpace, + const char* endTag, + bool caseInsensitive, + TiXmlEncoding encoding ) { *text = ""; if ( !trimWhiteSpace // certain tags always keep whitespace diff --git a/shared/toggleButton.h b/shared/toggleButton.h index b7475e0c..1110ad5d 100644 --- a/shared/toggleButton.h +++ b/shared/toggleButton.h @@ -14,8 +14,8 @@ public: long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxButtonNameStr) : - wxBitmapButton(parent, id, bitmap, pos, size, style, validator, name), - active(false) {} + wxBitmapButton(parent, id, bitmap, pos, size, style, validator, name), + active(false) {} void init(const wxBitmap& activeBmp, const wxString& activeTooltip, diff --git a/shared/xmlBase.cpp b/shared/xmlBase.cpp index ba96b663..c098f94a 100644 --- a/shared/xmlBase.cpp +++ b/shared/xmlBase.cpp @@ -43,7 +43,8 @@ xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename) return XML_OTHER; } catch (const std::exception&) - { //unfortunately TiXml isn't very smart and tries to allocate space for the complete file: length_error exception is thrown for large files! + { + //unfortunately TiXml isn't very smart and tries to allocate space for the complete file: length_error exception is thrown for large files! return XML_OTHER; } diff --git a/shared/xmlBase.h b/shared/xmlBase.h index ed838843..3a01c515 100644 --- a/shared/xmlBase.h +++ b/shared/xmlBase.h @@ -10,108 +10,108 @@ namespace xmlAccess { - enum XmlType - { - XML_GUI_CONFIG, - XML_BATCH_CONFIG, - XML_GLOBAL_SETTINGS, - XML_REAL_CONFIG, - XML_OTHER - }; +enum XmlType +{ + XML_GUI_CONFIG, + XML_BATCH_CONFIG, + XML_GLOBAL_SETTINGS, + XML_REAL_CONFIG, + XML_OTHER +}; - XmlType getXmlType(const wxString& filename); +XmlType getXmlType(const wxString& filename); - bool loadXmlDocument(const wxString& fileName, const XmlType type, TiXmlDocument& document); - void getDefaultXmlDocument(const XmlType type, TiXmlDocument& document); - bool saveXmlDocument(const wxString& fileName, const TiXmlDocument& document); +bool loadXmlDocument(const wxString& fileName, const XmlType type, TiXmlDocument& document); +void getDefaultXmlDocument(const XmlType type, TiXmlDocument& document); +bool saveXmlDocument(const wxString& fileName, const TiXmlDocument& document); //------------------------------------------------------------------------------------------ - //small helper functions - bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::string& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, wxString& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, int& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, unsigned int& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, long& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, bool& output); - bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::vector<wxString>& output); - - bool readXmlAttribute(const std::string& name, const TiXmlElement* node, std::string& output); - bool readXmlAttribute(const std::string& name, const TiXmlElement* node, wxString& output); - bool readXmlAttribute(const std::string& name, const TiXmlElement* node, int& output); - bool readXmlAttribute(const std::string& name, const TiXmlElement* node, unsigned int& output); - bool readXmlAttribute(const std::string& name, const TiXmlElement* node, bool& output); - - void addXmlElement(const std::string& name, const std::string& value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const wxString& value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const int value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const unsigned int value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const long value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const bool value, TiXmlElement* parent); - void addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent); - - void addXmlAttribute(const std::string& name, const std::string& value, TiXmlElement* node); - void addXmlAttribute(const std::string& name, const wxString& value, TiXmlElement* node); - void addXmlAttribute(const std::string& name, const int value, TiXmlElement* node); - void addXmlAttribute(const std::string& name, const unsigned int value, TiXmlElement* node); - void addXmlAttribute(const std::string& name, const bool value, TiXmlElement* node); - - - - class XmlParser +//small helper functions +bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::string& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, wxString& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, int& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, unsigned int& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, long& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, bool& output); +bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::vector<wxString>& output); + +bool readXmlAttribute(const std::string& name, const TiXmlElement* node, std::string& output); +bool readXmlAttribute(const std::string& name, const TiXmlElement* node, wxString& output); +bool readXmlAttribute(const std::string& name, const TiXmlElement* node, int& output); +bool readXmlAttribute(const std::string& name, const TiXmlElement* node, unsigned int& output); +bool readXmlAttribute(const std::string& name, const TiXmlElement* node, bool& output); + +void addXmlElement(const std::string& name, const std::string& value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const wxString& value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const int value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const unsigned int value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const long value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const bool value, TiXmlElement* parent); +void addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent); + +void addXmlAttribute(const std::string& name, const std::string& value, TiXmlElement* node); +void addXmlAttribute(const std::string& name, const wxString& value, TiXmlElement* node); +void addXmlAttribute(const std::string& name, const int value, TiXmlElement* node); +void addXmlAttribute(const std::string& name, const unsigned int value, TiXmlElement* node); +void addXmlAttribute(const std::string& name, const bool value, TiXmlElement* node); + + + +class XmlParser +{ +public: + XmlParser(const TiXmlElement* rootElement) : root(rootElement) {} + + void logError(const std::string& nodeName); + bool errorsOccured() const; + const wxString getErrorMessageFormatted() const; + +protected: + //another level of indirection: if errors occur during xml parsing they are logged + template <class T> + void readXmlElementLogging(const std::string& name, const TiXmlElement* parent, T& output) { - public: - XmlParser(const TiXmlElement* rootElement) : root(rootElement) {} - - void logError(const std::string& nodeName); - bool errorsOccured() const; - const wxString getErrorMessageFormatted() const; - - protected: - //another level of indirection: if errors occur during xml parsing they are logged - template <class T> - void readXmlElementLogging(const std::string& name, const TiXmlElement* parent, T& output) - { - if (!readXmlElement(name, parent, output)) - logError(name); - } - - template <class T> - void readXmlAttributeLogging(const std::string& name, const TiXmlElement* node, T& output) - { - if (!readXmlAttribute(name, node, output)) - logError(name); - } - - const TiXmlElement* const root; - std::vector<wxString> failedNodes; - }; + if (!readXmlElement(name, parent, output)) + logError(name); + } + template <class T> + void readXmlAttributeLogging(const std::string& name, const TiXmlElement* node, T& output) + { + if (!readXmlAttribute(name, node, output)) + logError(name); + } - class XmlError //Exception class + const TiXmlElement* const root; + std::vector<wxString> failedNodes; +}; + + +class XmlError //Exception class +{ +public: + enum Severity { - public: - enum Severity - { - WARNING = 77, - FATAL - }; - - XmlError(const wxString& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {} - - const wxString& show() const - { - return errorMessage; - } - Severity getSeverity() const - { - return m_severity; - } - private: - const wxString errorMessage; - const Severity m_severity; + WARNING = 77, + FATAL }; + + XmlError(const wxString& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {} + + const wxString& show() const + { + return errorMessage; + } + Severity getSeverity() const + { + return m_severity; + } +private: + const wxString errorMessage; + const Severity m_severity; +}; } diff --git a/shared/zstring.cpp b/shared/zstring.cpp index 6b2b68c6..9909abb9 100644 --- a/shared/zstring.cpp +++ b/shared/zstring.cpp @@ -1,8 +1,8 @@ #include "zstring.h" +#include <stdexcept> #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" -#include <stdexcept> #endif //FFS_WIN #ifdef __WXDEBUG__ @@ -27,12 +27,12 @@ AllocationCount::~AllocationCount() leakingStrings += wxT("\"\n"); } - MessageBox(NULL, wxString(wxT("Memory leak detected! (No problem if it occurs while Unit testing only!)")) + wxT("\n\n") + MessageBox(NULL, wxString(wxT("Memory leak detected!")) + wxT("\n\n") + wxT("Candidates:\n") + leakingStrings, wxString::Format(wxT("%i"), activeStrings.size()), 0); } #else - std::abort(); + throw std::logic_error("Memory leak!"); #endif } @@ -198,7 +198,8 @@ Zstring& Zstring::Trim(bool fromRight) if (descr->refCount > 1) //allocate new string *this = Zstring(cursor, thisLen - diff); else - { //overwrite this string + { + //overwrite this string ::memmove(strBegin, cursor, (thisLen - diff + 1) * sizeof(DefaultChar)); //note: do not simply let data point to different location: this corrupts reserve()! descr->length -= diff; } @@ -307,7 +308,8 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t const size_t newLen = oldLen - n1 + n2; if (newLen > oldLen || descr->refCount > 1) - { //allocate a new string + { + //allocate a new string StringDescriptor* newDescr = allocate(newLen); //assemble new string with replacement @@ -342,7 +344,8 @@ Zstring& Zstring::operator=(const DefaultChar* source) if (descr->refCount > 1 || descr->capacity < sourceLen) //allocate new string *this = Zstring(source, sourceLen); else - { //overwrite this string + { + //overwrite this string ::memcpy(data(), source, (sourceLen + 1) * sizeof(DefaultChar)); //include null-termination descr->length = sourceLen; } @@ -355,7 +358,8 @@ Zstring& Zstring::assign(const DefaultChar* source, size_t len) if (descr->refCount > 1 || descr->capacity < len) //allocate new string *this = Zstring(source, len); else - { //overwrite this string + { + //overwrite this string ::memcpy(data(), source, len * sizeof(DefaultChar)); //don't know if source is null-terminated data()[len] = 0; //include null-termination descr->length = len; @@ -412,7 +416,8 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity assert(capacityNeeded != 0); if (descr->refCount > 1) - { //allocate a new string + { + //allocate a new string const size_t oldLength = length(); assert(oldLength <= getCapacityToAllocate(capacityNeeded)); @@ -425,7 +430,8 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity descr = newDescr; } else if (descr->capacity < capacityNeeded) - { //try to resize the current string (allocate anew if necessary) + { + //try to resize the current string (allocate anew if necessary) const size_t newCapacity = getCapacityToAllocate(capacityNeeded); #ifdef __WXDEBUG__ diff --git a/shared/zstring.h b/shared/zstring.h index 018ca42e..9c7c2245 100644 --- a/shared/zstring.h +++ b/shared/zstring.h @@ -13,6 +13,7 @@ #include <new> #include <stdlib.h> #include <vector> +#include <sstream> #ifdef __WXDEBUG__ #include <set> @@ -22,8 +23,10 @@ #ifdef ZSTRING_CHAR typedef char DefaultChar; //use char strings +#define DefaultStr(x) x // #elif defined ZSTRING_WIDE_CHAR typedef wchar_t DefaultChar; //use wide character strings +#define DefaultStr(x) L ## x // #endif @@ -123,6 +126,10 @@ private: }; +template <class T> +Zstring numberToZstring(const T& number); //convert number to Zstring + + //####################################################################################### //begin of implementation @@ -146,13 +153,13 @@ int defaultCompare(const char* str1, const char* str2, const size_t count) } inline -char* defaultStrFind(const char* str1, const char* str2) +const char* defaultStrFind(const char* str1, const char* str2) { return strstr(str1, str2); } inline -char* defaultStrFind(const char* str1, int ch) +const char* defaultStrFind(const char* str1, int ch) { return strchr(str1, ch); } @@ -236,6 +243,7 @@ public: private: AllocationCount() {} + AllocationCount(const AllocationCount&); ~AllocationCount(); wxCriticalSection lockActStrings; @@ -253,11 +261,12 @@ size_t getCapacityToAllocate(const size_t length) inline Zstring::StringDescriptor* Zstring::allocate(const size_t newLength) -{ //allocate and set data for new string +{ + //allocate and set data for new string const size_t newCapacity = getCapacityToAllocate(newLength); assert(newCapacity); - StringDescriptor* newDescr = static_cast<StringDescriptor*>(::malloc(sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar))); //use C-memory functions because of realloc() + StringDescriptor* const newDescr = static_cast<StringDescriptor*>(::malloc(sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar))); //use C-memory functions because of realloc() if (newDescr == NULL) throw std::bad_alloc(); @@ -288,6 +297,7 @@ Zstring::Zstring() inline + Zstring::Zstring(const DefaultChar* source) { initAndCopy(source, defaultLength(source)); @@ -671,4 +681,17 @@ const Zstring Zstring::operator+(const DefaultChar ch) const } +template <class T> +inline +Zstring numberToZstring(const T& number) //convert number to string the C++ way +{ +#ifdef ZSTRING_CHAR + std::stringstream ss; +#elif defined ZSTRING_WIDE_CHAR + std::wstringstream ss; +#endif + ss << number; + return Zstring(ss.str().c_str(), ss.str().length()); +} + #endif // ZSTRING_H_INCLUDED diff --git a/structures.cpp b/structures.cpp index 57bea755..31c66650 100644 --- a/structures.cpp +++ b/structures.cpp @@ -7,6 +7,28 @@ using FreeFileSync::SyncConfiguration; using FreeFileSync::MainConfiguration; +Zstring FreeFileSync::defaultIncludeFilter() +{ + static Zstring include(DefaultStr("*")); //include all files/folders + return include; +} + + +Zstring FreeFileSync::defaultExcludeFilter() +{ +#ifdef FFS_WIN + static Zstring exclude(wxT("\ +\\System Volume Information\\\n\ +\\RECYCLER\\\n\ +\\RECYCLED\\\n\ +\\$Recycle.Bin\\")); //exclude Recycle Bin +#elif defined FFS_LINUX + static Zstring exclude; //exclude nothing +#endif + return exclude; +} + + bool FreeFileSync::recycleBinExistsWrap() { return recycleBinExists(); @@ -30,28 +52,31 @@ wxString FreeFileSync::getVariantName(CompareVariant var) SyncConfiguration::Variant SyncConfiguration::getVariant() const { - if ( exLeftSideOnly == SYNC_DIR_CFG_RIGHT && - exRightSideOnly == SYNC_DIR_CFG_RIGHT && - leftNewer == SYNC_DIR_CFG_RIGHT && - rightNewer == SYNC_DIR_CFG_RIGHT && - different == SYNC_DIR_CFG_RIGHT && - conflict == SYNC_DIR_CFG_NONE) + if (automatic == true) + return AUTOMATIC; //automatic mode + + if ( exLeftSideOnly == SYNC_DIR_RIGHT && + exRightSideOnly == SYNC_DIR_RIGHT && + leftNewer == SYNC_DIR_RIGHT && + rightNewer == SYNC_DIR_RIGHT && + different == SYNC_DIR_RIGHT && + conflict == SYNC_DIR_RIGHT) return MIRROR; //one way -> - else if (exLeftSideOnly == SYNC_DIR_CFG_RIGHT && - exRightSideOnly == SYNC_DIR_CFG_NONE && - leftNewer == SYNC_DIR_CFG_RIGHT && - rightNewer == SYNC_DIR_CFG_NONE && - different == SYNC_DIR_CFG_NONE && - conflict == SYNC_DIR_CFG_NONE) + else if (exLeftSideOnly == SYNC_DIR_RIGHT && + exRightSideOnly == SYNC_DIR_NONE && + leftNewer == SYNC_DIR_RIGHT && + rightNewer == SYNC_DIR_NONE && + different == SYNC_DIR_NONE && + conflict == SYNC_DIR_NONE) return UPDATE; //Update -> - else if (exLeftSideOnly == SYNC_DIR_CFG_RIGHT && - exRightSideOnly == SYNC_DIR_CFG_LEFT && - leftNewer == SYNC_DIR_CFG_RIGHT && - rightNewer == SYNC_DIR_CFG_LEFT && - different == SYNC_DIR_CFG_NONE && - conflict == SYNC_DIR_CFG_NONE) + else if (exLeftSideOnly == SYNC_DIR_RIGHT && + exRightSideOnly == SYNC_DIR_LEFT && + leftNewer == SYNC_DIR_RIGHT && + rightNewer == SYNC_DIR_LEFT && + different == SYNC_DIR_NONE && + conflict == SYNC_DIR_NONE) return TWOWAY; //two way <-> else return CUSTOM; //other @@ -62,29 +87,35 @@ void SyncConfiguration::setVariant(const Variant var) { switch (var) { + case AUTOMATIC: + automatic = true; + break; case MIRROR: - exLeftSideOnly = SYNC_DIR_CFG_RIGHT; - exRightSideOnly = SYNC_DIR_CFG_RIGHT; - leftNewer = SYNC_DIR_CFG_RIGHT; - rightNewer = SYNC_DIR_CFG_RIGHT; - different = SYNC_DIR_CFG_RIGHT; - conflict = SYNC_DIR_CFG_NONE; + automatic = false; + exLeftSideOnly = SYNC_DIR_RIGHT; + exRightSideOnly = SYNC_DIR_RIGHT; + leftNewer = SYNC_DIR_RIGHT; + rightNewer = SYNC_DIR_RIGHT; + different = SYNC_DIR_RIGHT; + conflict = SYNC_DIR_RIGHT; break; case UPDATE: - exLeftSideOnly = SYNC_DIR_CFG_RIGHT; - exRightSideOnly = SYNC_DIR_CFG_NONE; - leftNewer = SYNC_DIR_CFG_RIGHT; - rightNewer = SYNC_DIR_CFG_NONE; - different = SYNC_DIR_CFG_NONE; - conflict = SYNC_DIR_CFG_NONE; + automatic = false; + exLeftSideOnly = SYNC_DIR_RIGHT; + exRightSideOnly = SYNC_DIR_NONE; + leftNewer = SYNC_DIR_RIGHT; + rightNewer = SYNC_DIR_NONE; + different = SYNC_DIR_NONE; + conflict = SYNC_DIR_NONE; break; case TWOWAY: - exLeftSideOnly = SYNC_DIR_CFG_RIGHT; - exRightSideOnly = SYNC_DIR_CFG_LEFT; - leftNewer = SYNC_DIR_CFG_RIGHT; - rightNewer = SYNC_DIR_CFG_LEFT; - different = SYNC_DIR_CFG_NONE; - conflict = SYNC_DIR_CFG_NONE; + automatic = false; + exLeftSideOnly = SYNC_DIR_RIGHT; + exRightSideOnly = SYNC_DIR_LEFT; + leftNewer = SYNC_DIR_RIGHT; + rightNewer = SYNC_DIR_LEFT; + different = SYNC_DIR_NONE; + conflict = SYNC_DIR_NONE; break; case CUSTOM: assert(false); @@ -104,6 +135,8 @@ wxString MainConfiguration::getSyncVariantName() //seems to be all in sync... switch (mainVariant) { + case SyncConfiguration::AUTOMATIC: + return _("<Automatic>"); case SyncConfiguration::MIRROR: return _("Mirror ->>"); case SyncConfiguration::UPDATE: diff --git a/structures.h b/structures.h index 4d383d22..cdfea74e 100644 --- a/structures.h +++ b/structures.h @@ -11,309 +11,307 @@ namespace FreeFileSync { - enum CompareVariant - { - CMP_BY_TIME_SIZE, - CMP_BY_CONTENT - }; +enum CompareVariant +{ + CMP_BY_TIME_SIZE, + CMP_BY_CONTENT +}; + +wxString getVariantName(CompareVariant var); - wxString getVariantName(CompareVariant var); + +enum SyncDirection +{ + SYNC_DIR_LEFT = 0, + SYNC_DIR_RIGHT, + SYNC_DIR_NONE, //NOTE: align with SyncDirectionIntern before adding anything here! +}; - enum SyncDirectionCfg +class SyncConfiguration +{ +public: + SyncConfiguration() : + automatic(true), + exLeftSideOnly( SYNC_DIR_RIGHT), + exRightSideOnly(SYNC_DIR_LEFT), + leftNewer( SYNC_DIR_RIGHT), + rightNewer( SYNC_DIR_LEFT), + different( SYNC_DIR_NONE), + conflict( SYNC_DIR_NONE) {} + + bool operator==(const SyncConfiguration& other) const { - SYNC_DIR_CFG_LEFT = 0, - SYNC_DIR_CFG_RIGHT, - SYNC_DIR_CFG_NONE - }; - //attention make sure these /|\ \|/ two enums match!!! - enum SyncDirection + return exLeftSideOnly == other.exLeftSideOnly && + exRightSideOnly == other.exRightSideOnly && + leftNewer == other.leftNewer && + rightNewer == other.rightNewer && + different == other.different && + conflict == other.conflict; + } + + //get/set default configuration variants + enum Variant { - SYNC_DIR_LEFT = SYNC_DIR_CFG_LEFT, - SYNC_DIR_RIGHT = SYNC_DIR_CFG_RIGHT, - SYNC_DIR_NONE = SYNC_DIR_CFG_NONE, + AUTOMATIC, + MIRROR, + UPDATE, + TWOWAY, + CUSTOM }; + Variant getVariant() const; + void setVariant(const Variant var); + + bool automatic; //use sync-database + SyncDirection exLeftSideOnly; + SyncDirection exRightSideOnly; + SyncDirection leftNewer; + SyncDirection rightNewer; + SyncDirection different; + SyncDirection conflict; +}; + + +enum DeletionPolicy +{ + DELETE_PERMANENTLY = 5, + MOVE_TO_RECYCLE_BIN, + MOVE_TO_CUSTOM_DIRECTORY +}; - inline - SyncDirection convertToSyncDirection(SyncDirectionCfg syncCfg) +struct HiddenSettings +{ + HiddenSettings() : + fileTimeTolerance(2), //default 2s: FAT vs NTFS + traverseDirectorySymlinks(false), + copyFileSymlinks(true), + verifyFileCopy(false) {} + + unsigned int fileTimeTolerance; //max. allowed file time deviation + bool traverseDirectorySymlinks; + bool copyFileSymlinks; //copy symbolic link instead of target file + bool verifyFileCopy; //verify copied files + + bool operator==(const HiddenSettings& other) const { - return static_cast<SyncDirection>(syncCfg); + return fileTimeTolerance == other.fileTimeTolerance && + traverseDirectorySymlinks == other.traverseDirectorySymlinks && + copyFileSymlinks == other.copyFileSymlinks && + verifyFileCopy == other.verifyFileCopy; } +}; - struct SyncConfiguration - { - SyncConfiguration() : - exLeftSideOnly( SYNC_DIR_CFG_RIGHT), - exRightSideOnly(SYNC_DIR_CFG_LEFT), - leftNewer( SYNC_DIR_CFG_RIGHT), - rightNewer( SYNC_DIR_CFG_LEFT), - different( SYNC_DIR_CFG_NONE), - conflict( SYNC_DIR_CFG_NONE) {} - - SyncDirectionCfg exLeftSideOnly; - SyncDirectionCfg exRightSideOnly; - SyncDirectionCfg leftNewer; - SyncDirectionCfg rightNewer; - SyncDirectionCfg different; - SyncDirectionCfg conflict; - - bool operator==(const SyncConfiguration& other) const - { - return exLeftSideOnly == other.exLeftSideOnly && - exRightSideOnly == other.exRightSideOnly && - leftNewer == other.leftNewer && - rightNewer == other.rightNewer && - different == other.different && - conflict == other.conflict; - } - - //get/set default configuration variants - enum Variant - { - MIRROR, - UPDATE, - TWOWAY, - CUSTOM - }; - Variant getVariant() const; - void setVariant(const Variant var); - }; +bool recycleBinExistsWrap(); - enum DeletionPolicy - { - DELETE_PERMANENTLY = 5, - MOVE_TO_RECYCLE_BIN, - MOVE_TO_CUSTOM_DIRECTORY - }; +struct AlternateSyncConfig +{ + AlternateSyncConfig(const SyncConfiguration& syncCfg, + const DeletionPolicy handleDel, + const wxString& customDelDir) : + syncConfiguration(syncCfg), + handleDeletion(handleDel), + customDeletionDirectory(customDelDir) {}; + AlternateSyncConfig() : //construct with default values + handleDeletion(FreeFileSync::recycleBinExistsWrap() ? MOVE_TO_RECYCLE_BIN : DELETE_PERMANENTLY) {} //enable if OS supports it; else user will have to activate first and then get an error message - struct HiddenSettings + //Synchronisation settings + SyncConfiguration syncConfiguration; + + //misc options + DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location + wxString customDeletionDirectory; + + bool operator==(const AlternateSyncConfig& other) const { - HiddenSettings() : - fileTimeTolerance(2), //default 2s: FAT vs NTFS - traverseDirectorySymlinks(false), - copyFileSymlinks(true), - verifyFileCopy(false) {} - - unsigned int fileTimeTolerance; //max. allowed file time deviation - bool traverseDirectorySymlinks; - bool copyFileSymlinks; //copy symbolic link instead of target file - bool verifyFileCopy; //verify copied files - - bool operator==(const HiddenSettings& other) const - { - return fileTimeTolerance == other.fileTimeTolerance && - traverseDirectorySymlinks == other.traverseDirectorySymlinks && - copyFileSymlinks == other.copyFileSymlinks && - verifyFileCopy == other.verifyFileCopy; - } - }; + return syncConfiguration == other.syncConfiguration && + handleDeletion == other.handleDeletion && + customDeletionDirectory == other.customDeletionDirectory; + } +}; +//standard filter settings, OS dependent +Zstring defaultIncludeFilter(); +Zstring defaultExcludeFilter(); - bool recycleBinExistsWrap(); +struct AlternateFilter +{ + AlternateFilter(const Zstring& include, const Zstring& exclude) : + includeFilter(include), + excludeFilter(exclude) {} - struct AlternateSyncConfig - { - AlternateSyncConfig(const SyncConfiguration& syncCfg, - const DeletionPolicy handleDel, - const wxString& customDelDir) : - syncConfiguration(syncCfg), - handleDeletion(handleDel), - customDeletionDirectory(customDelDir) {}; - - AlternateSyncConfig() : //construct with default values - handleDeletion(FreeFileSync::recycleBinExistsWrap() ? MOVE_TO_RECYCLE_BIN : DELETE_PERMANENTLY) {} //enable if OS supports it; else user will have to activate first and then get an error message - - //Synchronisation settings - SyncConfiguration syncConfiguration; - - //misc options - DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location - wxString customDeletionDirectory; - - bool operator==(const AlternateSyncConfig& other) const - { - return syncConfiguration == other.syncConfiguration && - handleDeletion == other.handleDeletion && - customDeletionDirectory == other.customDeletionDirectory; - } - }; + AlternateFilter() : //construct with default values + includeFilter(defaultIncludeFilter()), + excludeFilter(defaultExcludeFilter()) {} + Zstring includeFilter; + Zstring excludeFilter; - struct AlternateFilter + bool operator==(const AlternateFilter& other) const { - AlternateFilter(const wxString& include, const wxString& exclude) : - includeFilter(include), - excludeFilter(exclude) {} - - AlternateFilter() : //construct with default values - includeFilter(wxT("*")), //include all files/folders - excludeFilter(wxEmptyString) {} //exclude nothing - - wxString includeFilter; - wxString excludeFilter; - - bool operator==(const AlternateFilter& other) const - { - return includeFilter == other.includeFilter && - excludeFilter == other.excludeFilter; - } - }; + return includeFilter == other.includeFilter && + excludeFilter == other.excludeFilter; + } +}; - struct FolderPair - { - FolderPair(const Zstring& leftDir, const Zstring& rightDir) : - leftDirectory(leftDir), - rightDirectory(rightDir) {} - - Zstring leftDirectory; - Zstring rightDirectory; - - bool operator==(const FolderPair& other) const - { - return leftDirectory == other.leftDirectory && - rightDirectory == other.rightDirectory; - } - }; +struct FolderPair +{ + FolderPair(const Zstring& leftDir, const Zstring& rightDir) : + leftDirectory(leftDir), + rightDirectory(rightDir) {} + Zstring leftDirectory; + Zstring rightDirectory; - struct FolderPairEnh //enhanced folder pairs with (optional) alternate configuration + bool operator==(const FolderPair& other) const { - FolderPairEnh() {} - - FolderPairEnh(const Zstring& leftDir, - const Zstring& rightDir, - const boost::shared_ptr<const AlternateSyncConfig>& syncConfig, - const boost::shared_ptr<const AlternateFilter>& filter) : - leftDirectory(leftDir), - rightDirectory(rightDir) , - altSyncConfig(syncConfig), - altFilter(filter) {} - - Zstring leftDirectory; - Zstring rightDirectory; - - boost::shared_ptr<const AlternateSyncConfig> altSyncConfig; //optional - boost::shared_ptr<const AlternateFilter> altFilter; //optional - - bool operator==(const FolderPairEnh& other) const - { - return leftDirectory == other.leftDirectory && - rightDirectory == other.rightDirectory && - - (altSyncConfig.get() && other.altSyncConfig.get() ? - *altSyncConfig == *other.altSyncConfig : - altSyncConfig.get() == other.altSyncConfig.get()) && - - (altFilter.get() && other.altFilter.get() ? - *altFilter == *other.altFilter : - altFilter.get() == other.altFilter.get()); - } - }; + return leftDirectory == other.leftDirectory && + rightDirectory == other.rightDirectory; + } +}; - struct MainConfiguration - { - MainConfiguration() : - mainFolderPair(Zstring(), Zstring()), - compareVar(CMP_BY_TIME_SIZE), - filterIsActive(false), //do not filter by default - includeFilter(wxT("*")), //include all files/folders - excludeFilter(wxEmptyString), //exclude nothing - handleDeletion(FreeFileSync::recycleBinExistsWrap() ? MOVE_TO_RECYCLE_BIN : DELETE_PERMANENTLY) {} //enable if OS supports it; else user will have to activate first and then get an error message - - FolderPair mainFolderPair; - std::vector<FolderPairEnh> additionalPairs; - - //Compare setting - CompareVariant compareVar; - - //Synchronisation settings - SyncConfiguration syncConfiguration; - - //Filter setting - bool filterIsActive; - wxString includeFilter; - wxString excludeFilter; - - //misc options - HiddenSettings hidden; //settings not visible on GUI - - DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location - wxString customDeletionDirectory; - - wxString getSyncVariantName(); - - bool operator==(const MainConfiguration& other) const - { - return mainFolderPair == other.mainFolderPair && - additionalPairs == other.additionalPairs && - compareVar == other.compareVar && - syncConfiguration == other.syncConfiguration && - filterIsActive == other.filterIsActive && - includeFilter == other.includeFilter && - excludeFilter == other.excludeFilter && - hidden == other.hidden && - handleDeletion == other.handleDeletion && - customDeletionDirectory == other.customDeletionDirectory; - } - }; +struct FolderPairEnh //enhanced folder pairs with (optional) alternate configuration +{ + FolderPairEnh() {} + FolderPairEnh(const Zstring& leftDir, + const Zstring& rightDir, + const boost::shared_ptr<const AlternateSyncConfig>& syncConfig, + const boost::shared_ptr<const AlternateFilter>& filter) : + leftDirectory(leftDir), + rightDirectory(rightDir) , + altSyncConfig(syncConfig), + altFilter(filter) {} - enum CompareFilesResult - { - FILE_LEFT_SIDE_ONLY = 0, - FILE_RIGHT_SIDE_ONLY, - FILE_LEFT_NEWER, - FILE_RIGHT_NEWER, - FILE_DIFFERENT, - FILE_EQUAL, - FILE_CONFLICT - }; - //attention make sure these /|\ \|/ two enums match!!! - enum CompareDirResult - { - DIR_LEFT_SIDE_ONLY = FILE_LEFT_SIDE_ONLY, - DIR_RIGHT_SIDE_ONLY = FILE_RIGHT_SIDE_ONLY, - DIR_EQUAL = FILE_EQUAL - }; + Zstring leftDirectory; + Zstring rightDirectory; + boost::shared_ptr<const AlternateSyncConfig> altSyncConfig; //optional + boost::shared_ptr<const AlternateFilter> altFilter; //optional - inline - CompareFilesResult convertToFilesResult(CompareDirResult value) + bool operator==(const FolderPairEnh& other) const { - return static_cast<CompareFilesResult>(value); + return leftDirectory == other.leftDirectory && + rightDirectory == other.rightDirectory && + + (altSyncConfig.get() && other.altSyncConfig.get() ? + *altSyncConfig == *other.altSyncConfig : + altSyncConfig.get() == other.altSyncConfig.get()) && + + (altFilter.get() && other.altFilter.get() ? + *altFilter == *other.altFilter : + altFilter.get() == other.altFilter.get()); } +}; + + +struct MainConfiguration +{ + MainConfiguration() : + mainFolderPair(Zstring(), Zstring()), + compareVar(CMP_BY_TIME_SIZE), +#ifdef FFS_WIN + filterIsActive(true), +#elif defined FFS_LINUX + filterIsActive(false), +#endif + includeFilter(defaultIncludeFilter()), + excludeFilter(defaultExcludeFilter()), + handleDeletion(FreeFileSync::recycleBinExistsWrap() ? MOVE_TO_RECYCLE_BIN : DELETE_PERMANENTLY) {} //enable if OS supports it; else user will have to activate first and then get an error message + + FolderPair mainFolderPair; + std::vector<FolderPairEnh> additionalPairs; + //Compare setting + CompareVariant compareVar; + //Synchronisation settings + SyncConfiguration syncConfiguration; - wxString getDescription(CompareFilesResult cmpRes); - wxString getSymbol(CompareFilesResult cmpRes); + //Filter setting + bool filterIsActive; + Zstring includeFilter; + Zstring excludeFilter; + //misc options + HiddenSettings hidden; //settings not visible on GUI - enum SyncOperation + DeletionPolicy handleDeletion; //use Recycle, delete permanently or move to user-defined location + wxString customDeletionDirectory; + + wxString getSyncVariantName(); + + bool operator==(const MainConfiguration& other) const { - SO_CREATE_NEW_LEFT, - SO_CREATE_NEW_RIGHT, - SO_DELETE_LEFT, - SO_DELETE_RIGHT, - SO_OVERWRITE_LEFT, - SO_OVERWRITE_RIGHT, - SO_DO_NOTHING, - SO_UNRESOLVED_CONFLICT - }; + return mainFolderPair == other.mainFolderPair && + additionalPairs == other.additionalPairs && + compareVar == other.compareVar && + syncConfiguration == other.syncConfiguration && + filterIsActive == other.filterIsActive && + includeFilter == other.includeFilter && + excludeFilter == other.excludeFilter && + hidden == other.hidden && + handleDeletion == other.handleDeletion && + customDeletionDirectory == other.customDeletionDirectory; + } +}; - wxString getDescription(SyncOperation op); - wxString getSymbol(SyncOperation op); +enum CompareFilesResult +{ + FILE_LEFT_SIDE_ONLY = 0, + FILE_RIGHT_SIDE_ONLY, + FILE_LEFT_NEWER, + FILE_RIGHT_NEWER, + FILE_DIFFERENT, + FILE_EQUAL, + FILE_CONFLICT +}; +//attention make sure these /|\ \|/ two enums match!!! +enum CompareDirResult +{ + DIR_LEFT_SIDE_ONLY = FILE_LEFT_SIDE_ONLY, + DIR_RIGHT_SIDE_ONLY = FILE_RIGHT_SIDE_ONLY, + DIR_EQUAL = FILE_EQUAL +}; - //Exception class used to abort the "compare" and "sync" process - class AbortThisProcess {}; + +inline +CompareFilesResult convertToFilesResult(CompareDirResult value) +{ + return static_cast<CompareFilesResult>(value); +} + + + +wxString getDescription(CompareFilesResult cmpRes); +wxString getSymbol(CompareFilesResult cmpRes); + + +enum SyncOperation +{ + SO_CREATE_NEW_LEFT, + SO_CREATE_NEW_RIGHT, + SO_DELETE_LEFT, + SO_DELETE_RIGHT, + SO_OVERWRITE_LEFT, + SO_OVERWRITE_RIGHT, + SO_DO_NOTHING, + SO_UNRESOLVED_CONFLICT +}; + +wxString getDescription(SyncOperation op); +wxString getSymbol(SyncOperation op); + + +//Exception class used to abort the "compare" and "sync" process +class AbortThisProcess {}; } #endif // FREEFILESYNC_H_INCLUDED diff --git a/synchronization.cpp b/synchronization.cpp index 59f3692d..66108ade 100644 --- a/synchronization.cpp +++ b/synchronization.cpp @@ -3,13 +3,15 @@ #include <wx/intl.h> #include <wx/msgdlg.h> #include <wx/log.h> -#include "algorithm.h" +#include "shared/stringConv.h" +#include "ui/util.h" #include "shared/systemConstants.h" #include "library/statusHandler.h" #include "shared/fileHandling.h" #include <wx/file.h> #include <boost/bind.hpp> #include "shared/globalFunctions.h" +#include <boost/scoped_array.hpp> using namespace FreeFileSync; @@ -27,10 +29,10 @@ void SyncStatistics::init() } -SyncStatistics::SyncStatistics(const BaseDirMapping& baseDir) +SyncStatistics::SyncStatistics(const HierarchyObject& hierObj) { init(); - getNumbersRecursively(baseDir); + getNumbersRecursively(hierObj); } @@ -102,7 +104,7 @@ void SyncStatistics::getNumbersRecursively(const HierarchyObject& hierObj) inline void SyncStatistics::getFileNumbers(const FileMapping& fileObj) { - switch (FreeFileSync::getSyncOperation(fileObj)) //evaluate comparison result and sync direction + switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: ++createLeft; @@ -145,7 +147,7 @@ void SyncStatistics::getFileNumbers(const FileMapping& fileObj) inline void SyncStatistics::getDirNumbers(const DirMapping& dirObj) { - switch (FreeFileSync::getSyncOperation(dirObj)) //evaluate comparison result and sync direction + switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: ++createLeft; @@ -181,14 +183,16 @@ std::vector<FreeFileSync::FolderPairSyncCfg> FreeFileSync::extractSyncCfg(const //add main pair output.push_back( - FolderPairSyncCfg(mainCfg.handleDeletion, - mainCfg.customDeletionDirectory)); + FolderPairSyncCfg(mainCfg.syncConfiguration.automatic, + mainCfg.handleDeletion, + wxToZ(mainCfg.customDeletionDirectory))); //add additional pairs for (std::vector<FolderPairEnh>::const_iterator i = mainCfg.additionalPairs.begin(); i != mainCfg.additionalPairs.end(); ++i) output.push_back( - FolderPairSyncCfg(i->altSyncConfig.get() ? i->altSyncConfig->handleDeletion : mainCfg.handleDeletion, - i->altSyncConfig.get() ? i->altSyncConfig->customDeletionDirectory : mainCfg.customDeletionDirectory)); + FolderPairSyncCfg(i->altSyncConfig.get() ? i->altSyncConfig->syncConfiguration.automatic : mainCfg.syncConfiguration.automatic, + i->altSyncConfig.get() ? i->altSyncConfig->handleDeletion : mainCfg.handleDeletion, + wxToZ(i->altSyncConfig.get() ? i->altSyncConfig->customDeletionDirectory : mainCfg.customDeletionDirectory))); return output; } @@ -214,28 +218,44 @@ private: //process files for (HierarchyObject::SubFileMapping::const_iterator i = hierObj.subFiles.begin(); i != hierObj.subFiles.end(); ++i) - if (i->selectedForSynchronization) //do not add filtered entries + switch (i->getSyncOperation()) //evaluate comparison result and sync direction { - //get data to process - switch (i->syncDir) - { - case SYNC_DIR_LEFT: //copy from right to left - if (!recyclerUsed) - spaceNeededLeft -= globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); - spaceNeededLeft += globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); - break; - - case SYNC_DIR_RIGHT: //copy from left to right - if (!recyclerUsed) - spaceNeededRight -= globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); - spaceNeededRight += globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); - break; - - case SYNC_DIR_NONE: - break; - } + case SO_CREATE_NEW_LEFT: + spaceNeededLeft += globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_CREATE_NEW_RIGHT: + spaceNeededRight += globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DELETE_LEFT: + if (!recyclerUsed) + spaceNeededLeft -= globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DELETE_RIGHT: + if (!recyclerUsed) + spaceNeededRight -= globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_OVERWRITE_LEFT: + if (!recyclerUsed) + spaceNeededLeft -= globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); + spaceNeededLeft += globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); + break; + + case SO_OVERWRITE_RIGHT: + if (!recyclerUsed) + spaceNeededRight -= globalFunctions::convertToSigned(i->getFileSize<RIGHT_SIDE>()); + spaceNeededRight += globalFunctions::convertToSigned(i->getFileSize<LEFT_SIDE>()); + break; + + case SO_DO_NOTHING: + case SO_UNRESOLVED_CONFLICT: + break; } + //recurse into sub-dirs std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), boost::bind(&DiskSpaceNeeded<recyclerUsed>::processRecursively, this, _1)); } @@ -254,7 +274,7 @@ std::pair<wxLongLong, wxLongLong> freeDiskSpaceNeeded(const BaseDirMapping& base case FreeFileSync::MOVE_TO_RECYCLE_BIN: return DiskSpaceNeeded<true>(baseDirObj).getSpaceTotal(); case FreeFileSync::MOVE_TO_CUSTOM_DIRECTORY: - //warning: this is not necessarily correct! it needs to be checked if user-def recycle bin dir and sync-dir are on same drive + //warning: this is not necessarily correct! it needs to be checked if user-def recycle bin dir and sync-dir are on same drive return DiskSpaceNeeded<true>(baseDirObj).getSpaceTotal(); } @@ -302,106 +322,32 @@ bool significantDifferenceDetected(const SyncStatistics& folderPairStat) } -FreeFileSync::SyncOperation FreeFileSync::getSyncOperation( //evaluate comparison result and sync direction - const CompareFilesResult cmpResult, - const bool selectedForSynchronization, - const SyncDirection syncDir) -{ - if (!selectedForSynchronization) return SO_DO_NOTHING; - - switch (cmpResult) - { - case FILE_LEFT_SIDE_ONLY: - switch (syncDir) - { - case SYNC_DIR_LEFT: - return SO_DELETE_LEFT; //delete files on left - case SYNC_DIR_RIGHT: - return SO_CREATE_NEW_RIGHT; //copy files to right - case SYNC_DIR_NONE: - return SO_DO_NOTHING; - } - break; - - case FILE_RIGHT_SIDE_ONLY: - switch (syncDir) - { - case SYNC_DIR_LEFT: - return SO_CREATE_NEW_LEFT; //copy files to left - case SYNC_DIR_RIGHT: - return SO_DELETE_RIGHT; //delete files on right - case SYNC_DIR_NONE: - return SO_DO_NOTHING; - } - break; - - case FILE_LEFT_NEWER: - case FILE_RIGHT_NEWER: - case FILE_DIFFERENT: - switch (syncDir) - { - case SYNC_DIR_LEFT: - return SO_OVERWRITE_LEFT; //copy from right to left - case SYNC_DIR_RIGHT: - return SO_OVERWRITE_RIGHT; //copy from left to right - case SYNC_DIR_NONE: - return SO_DO_NOTHING; - } - break; - - case FILE_CONFLICT: - switch (syncDir) - { - case SYNC_DIR_LEFT: - return SO_OVERWRITE_LEFT; //copy from right to left - case SYNC_DIR_RIGHT: - return SO_OVERWRITE_RIGHT; //copy from left to right - case SYNC_DIR_NONE: - return SO_UNRESOLVED_CONFLICT; - } - break; - - case FILE_EQUAL: - assert(syncDir == SYNC_DIR_NONE); - return SO_DO_NOTHING; - } - - return SO_DO_NOTHING; //dummy -} - - -SyncOperation FreeFileSync::getSyncOperation(const FileSystemObject& fsObj) //convenience function -{ - return getSyncOperation(fsObj.getCategory(), fsObj.selectedForSynchronization, fsObj.syncDir); -} - - /*add some postfix to alternate deletion directory: customDir\2009-06-30 12-59-12\ */ -wxString getSessionDeletionDir(const wxString& customDeletionDirectory) +Zstring getSessionDeletionDir(const Zstring& customDeletionDirectory) { wxString timeNow = wxDateTime::Now().FormatISOTime(); timeNow.Replace(wxT(":"), wxT("-")); const wxString sessionDir = wxDateTime::Now().FormatISODate() + wxChar(' ') + timeNow; - wxString formattedDirectory = FreeFileSync::getFormattedDirectoryName(customDeletionDirectory.c_str()).c_str(); + Zstring formattedDirectory = FreeFileSync::getFormattedDirectoryName(customDeletionDirectory); if (formattedDirectory.empty()) - return wxEmptyString; //no valid directory for deletion specified (checked later) + return Zstring(); //no valid directory for deletion specified (checked later) - if (!formattedDirectory.EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR))) + if (!formattedDirectory.EndsWith(globalFunctions::FILE_NAME_SEPARATOR)) formattedDirectory += globalFunctions::FILE_NAME_SEPARATOR; - formattedDirectory += sessionDir; + formattedDirectory += wxToZ(sessionDir); //ensure that session directory does not yet exist (must be unique) if (FreeFileSync::dirExists(formattedDirectory)) { //if it's not unique, add a postfix number int postfix = 1; - while (FreeFileSync::dirExists(formattedDirectory + wxT("_") + globalFunctions::numberToWxString(postfix))) + while (FreeFileSync::dirExists(formattedDirectory + DefaultStr("_") + numberToZstring(postfix))) ++postfix; - formattedDirectory += wxT("_") + globalFunctions::numberToWxString(postfix); + formattedDirectory += Zstring(DefaultStr("_")) + numberToZstring(postfix); } formattedDirectory += globalFunctions::FILE_NAME_SEPARATOR; @@ -414,30 +360,30 @@ SyncProcess::SyncProcess(const bool copyFileSymLinks, xmlAccess::OptionalDialogs& warnings, const bool verifyCopiedFiles, StatusHandler* handler) : - m_copyFileSymLinks(copyFileSymLinks), - m_traverseDirSymLinks(traverseDirSymLinks), - m_verifyCopiedFiles(verifyCopiedFiles), - m_warnings(warnings), + m_copyFileSymLinks(copyFileSymLinks), + m_traverseDirSymLinks(traverseDirSymLinks), + m_verifyCopiedFiles(verifyCopiedFiles), + m_warnings(warnings), #ifdef FFS_WIN - shadowCopyHandler(new ShadowCopy), + shadowCopyHandler(new ShadowCopy), #endif - statusUpdater(handler), - txtCopyingFile(Zstring(_("Copying file %x to %y")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)), - txtOverwritingFile(Zstring(_("Copying file %x to %y overwriting target")).Replace(wxT("%x"), wxT("\"%x\""), false).Replace(wxT("%y"), wxT("\n\"%y\""), false)), - txtCreatingFolder(Zstring(_("Creating folder %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)), - txtDeletingFile(Zstring(_("Deleting file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)), - txtDeletingFolder(Zstring(_("Deleting folder %x")).Replace( wxT("%x"), wxT("\n\"%x\""), false)), - txtMoveToRecycler(Zstring(_("Moving %x to Recycle Bin")).Replace(wxT("%x"), wxT("\"%x\""), false)), - txtVerifying(Zstring(_("Verifying file %x")).Replace(wxT("%x"), wxT("\n\"%x\""), false)) + statusUpdater(handler), + txtCopyingFile(wxToZ(_("Copying file %x to %y")).Replace(DefaultStr("%x"), DefaultStr("\"%x\""), false).Replace(DefaultStr("%y"), DefaultStr("\n\"%y\""), false)), + txtOverwritingFile(wxToZ(_("Copying file %x to %y overwriting target")).Replace(DefaultStr("%x"), DefaultStr("\"%x\""), false).Replace(DefaultStr("%y"), DefaultStr("\n\"%y\""), false)), + txtCreatingFolder(wxToZ(_("Creating folder %x")).Replace(DefaultStr("%x"), DefaultStr("\n\"%x\""), false)), + txtDeletingFile(wxToZ(_("Deleting file %x")).Replace(DefaultStr("%x"), DefaultStr("\n\"%x\""), false)), + txtDeletingFolder(wxToZ(_("Deleting folder %x")).Replace( DefaultStr("%x"), DefaultStr("\n\"%x\""), false)), + txtMoveToRecycler(wxToZ(_("Moving %x to Recycle Bin")).Replace(DefaultStr("%x"), DefaultStr("\"%x\""), false)), + txtVerifying(wxToZ(_("Verifying file %x")).Replace(DefaultStr("%x"), DefaultStr("\n\"%x\""), false)) {} SyncProcess::DeletionHandling::DeletionHandling(const DeletionPolicy handleDel, - const wxString& custDelFolder) : - handleDeletion(handleDel), - currentDelFolder(getSessionDeletionDir(custDelFolder).c_str()), //ends with path separator - txtMoveFileUserDefined( Zstring(_("Moving file %x to user-defined directory %y")). Replace(wxT("%x"), wxT("\"%x\"\n"), false).Replace(wxT("%y"), Zstring(wxT("\"")) + custDelFolder.c_str() + wxT("\""), false)), - txtMoveFolderUserDefined(Zstring(_("Moving folder %x to user-defined directory %y")).Replace(wxT("%x"), wxT("\"%x\"\n"), false).Replace(wxT("%y"), Zstring(wxT("\"")) + custDelFolder.c_str() + wxT("\""), false)) + const Zstring& custDelFolder) : + handleDeletion(handleDel), + currentDelFolder(getSessionDeletionDir(custDelFolder)), //ends with path separator + txtMoveFileUserDefined( wxToZ(_("Moving file %x to user-defined directory %y")). Replace(DefaultStr("%x"), DefaultStr("\"%x\"\n"), false).Replace(DefaultStr("%y"), Zstring(DefaultStr("\"")) + custDelFolder + DefaultStr("\""), false)), + txtMoveFolderUserDefined(wxToZ(_("Moving folder %x to user-defined directory %y")).Replace(DefaultStr("%x"), DefaultStr("\"%x\"\n"), false).Replace(DefaultStr("%y"), Zstring(DefaultStr("\"")) + custDelFolder + DefaultStr("\""), false)) {} @@ -476,7 +422,7 @@ void SyncProcess::removeFile(const FileMapping& fileObj, const DeletionHandling& if (showStatusUpdate) //status information { statusText = txtDeletingFile; - statusText.Replace(wxT("%x"), fileObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), fileObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh } @@ -486,7 +432,7 @@ void SyncProcess::removeFile(const FileMapping& fileObj, const DeletionHandling& if (showStatusUpdate) //status information { statusText = txtMoveToRecycler; - statusText.Replace(wxT("%x"), fileObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), fileObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh } @@ -498,7 +444,7 @@ void SyncProcess::removeFile(const FileMapping& fileObj, const DeletionHandling& if (showStatusUpdate) //status information { statusText = delHandling.txtMoveFileUserDefined; - statusText.Replace(wxT("%x"), fileObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), fileObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh } @@ -530,14 +476,14 @@ void SyncProcess::synchronizeFile(FileMapping& fileObj, const DeletionHandling& Zstring statusText; Zstring target; - switch (getSyncOperation(fileObj)) //evaluate comparison result and sync direction + switch (fileObj.getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: target = fileObj.getBaseDirPf<LEFT_SIDE>() + fileObj.getRelativeName<RIGHT_SIDE>(); statusText = txtCopyingFile; - statusText.Replace(wxT("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(wxT("%y"), target.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); + statusText.Replace(DefaultStr("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); + statusText.Replace(DefaultStr("%y"), target.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -548,8 +494,8 @@ void SyncProcess::synchronizeFile(FileMapping& fileObj, const DeletionHandling& target = fileObj.getBaseDirPf<RIGHT_SIDE>() + fileObj.getRelativeName<LEFT_SIDE>(); statusText = txtCopyingFile; - statusText.Replace(wxT("%x"), fileObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(wxT("%y"), target.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); + statusText.Replace(DefaultStr("%x"), fileObj.getShortName<LEFT_SIDE>(), false); + statusText.Replace(DefaultStr("%y"), target.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -566,8 +512,8 @@ void SyncProcess::synchronizeFile(FileMapping& fileObj, const DeletionHandling& case SO_OVERWRITE_RIGHT: statusText = txtOverwritingFile; - statusText.Replace(wxT("%x"), fileObj.getShortName<LEFT_SIDE>(), false); - statusText.Replace(wxT("%y"), fileObj.getFullName<RIGHT_SIDE>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); + statusText.Replace(DefaultStr("%x"), fileObj.getShortName<LEFT_SIDE>(), false); + statusText.Replace(DefaultStr("%y"), fileObj.getFullName<RIGHT_SIDE>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -577,8 +523,8 @@ void SyncProcess::synchronizeFile(FileMapping& fileObj, const DeletionHandling& case SO_OVERWRITE_LEFT: statusText = txtOverwritingFile; - statusText.Replace(wxT("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); - statusText.Replace(wxT("%y"), fileObj.getFullName<LEFT_SIDE>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); + statusText.Replace(DefaultStr("%x"), fileObj.getShortName<RIGHT_SIDE>(), false); + statusText.Replace(DefaultStr("%y"), fileObj.getFullName<LEFT_SIDE>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -591,23 +537,12 @@ void SyncProcess::synchronizeFile(FileMapping& fileObj, const DeletionHandling& return; //no update on processed data! } + //update FileMapping + fileObj.synchronizeSides(); + //progress indicator update //indicator is updated only if file is sync'ed correctly (and if some sync was done)! statusUpdater->updateProcessedData(1, 0); //processed data is communicated in subfunctions! - - //update FileMapping - switch (fileObj.syncDir) - { - case SYNC_DIR_LEFT: - fileObj.copyTo<LEFT_SIDE>(); - break; - case SYNC_DIR_RIGHT: - fileObj.copyTo<RIGHT_SIDE>(); - break; - case SYNC_DIR_NONE: - assert(!"if nothing's todo then why arrive here?"); - break; - } } @@ -622,7 +557,7 @@ void SyncProcess::removeFolder(const DirMapping& dirObj, const DeletionHandling& case FreeFileSync::DELETE_PERMANENTLY: //status information statusText = txtDeletingFolder; - statusText.Replace(wxT("%x"), dirObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), dirObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -631,7 +566,7 @@ void SyncProcess::removeFolder(const DirMapping& dirObj, const DeletionHandling& case FreeFileSync::MOVE_TO_RECYCLE_BIN: //status information statusText = txtMoveToRecycler; - statusText.Replace(wxT("%x"), dirObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), dirObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -642,7 +577,7 @@ void SyncProcess::removeFolder(const DirMapping& dirObj, const DeletionHandling& { //status information statusText = delHandling.txtMoveFolderUserDefined; - statusText.Replace(wxT("%x"), dirObj.getFullName<side>(), false); + statusText.Replace(DefaultStr("%x"), dirObj.getFullName<side>(), false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -675,19 +610,19 @@ void SyncProcess::synchronizeFolder(DirMapping& dirObj, const DeletionHandling& Zstring target; //synchronize folders: - switch (getSyncOperation(dirObj)) //evaluate comparison result and sync direction + switch (dirObj.getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: target = dirObj.getBaseDirPf<LEFT_SIDE>() + dirObj.getRelativeName<RIGHT_SIDE>(); statusText = txtCreatingFolder; - statusText.Replace(wxT("%x"), target, false); + statusText.Replace(DefaultStr("%x"), target, false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh //some check to catch the error that directory on source has been deleted externally after "compare"... if (!FreeFileSync::dirExists(dirObj.getFullName<RIGHT_SIDE>())) - throw FileError(wxString(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + dirObj.getFullName<RIGHT_SIDE>() + wxT("\"")); + throw FileError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(dirObj.getFullName<RIGHT_SIDE>()) + wxT("\"")); createDirectory(target, dirObj.getFullName<RIGHT_SIDE>(), !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks break; @@ -695,22 +630,38 @@ void SyncProcess::synchronizeFolder(DirMapping& dirObj, const DeletionHandling& target = dirObj.getBaseDirPf<RIGHT_SIDE>() + dirObj.getRelativeName<LEFT_SIDE>(); statusText = txtCreatingFolder; - statusText.Replace(wxT("%x"), target, false); + statusText.Replace(DefaultStr("%x"), target, false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh //some check to catch the error that directory on source has been deleted externally after "compare"... if (!FreeFileSync::dirExists(dirObj.getFullName<LEFT_SIDE>())) - throw FileError(wxString(_("Error: Source directory does not exist anymore:")) + wxT("\n\"") + dirObj.getFullName<LEFT_SIDE>() + wxT("\"")); + throw FileError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(dirObj.getFullName<LEFT_SIDE>()) + wxT("\"")); createDirectory(target, dirObj.getFullName<LEFT_SIDE>(), !m_traverseDirSymLinks); //traverse symlinks <=> !copy symlinks break; case SO_DELETE_LEFT: removeFolder<LEFT_SIDE>(dirObj, delHandling); + { + //progress indicator update: DON'T forget to notify about implicitly deleted objects! + const SyncStatistics subObjects(dirObj); + //...then remove everything + dirObj.subFiles.clear(); + dirObj.subDirs.clear(); + statusUpdater->updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), subObjects.getDataToProcess().ToDouble()); + } break; case SO_DELETE_RIGHT: removeFolder<RIGHT_SIDE>(dirObj, delHandling); + { + //progress indicator update: DON'T forget to notify about implicitly deleted objects! + const SyncStatistics subObjects(dirObj); + //...then remove everything + dirObj.subFiles.clear(); + dirObj.subDirs.clear(); + statusUpdater->updateProcessedData(subObjects.getCreate() + subObjects.getOverwrite() + subObjects.getDelete(), subObjects.getDataToProcess().ToDouble()); + } break; case SO_OVERWRITE_RIGHT: @@ -721,23 +672,12 @@ void SyncProcess::synchronizeFolder(DirMapping& dirObj, const DeletionHandling& return; //no update on processed data! } + //update DirMapping + dirObj.synchronizeSides(); + //progress indicator update //indicator is updated only if directory is sync'ed correctly (and if some work was done)! statusUpdater->updateProcessedData(1, 0); //each call represents one processed file - - //update DirMapping - switch (dirObj.syncDir) - { - case SYNC_DIR_LEFT: - dirObj.copyTo<LEFT_SIDE>(); - break; - case SYNC_DIR_RIGHT: - dirObj.copyTo<RIGHT_SIDE>(); - break; - case SYNC_DIR_NONE: - assert(!"if nothing's todo then why arrive here?"); - break; - } } @@ -745,7 +685,7 @@ inline bool deletionImminent(const FileSystemObject& fsObj) { //test if current sync-line will result in deletion of files -> used to avoid disc space bottlenecks - const SyncOperation op = FreeFileSync::getSyncOperation(fsObj); + const SyncOperation op = fsObj.getSyncOperation(); return op == FreeFileSync::SO_DELETE_LEFT || op == FreeFileSync::SO_DELETE_RIGHT; } @@ -754,7 +694,7 @@ class RemoveInvalid { public: RemoveInvalid(HierarchyObject& hierObj) : - hierObj_(hierObj) {} + hierObj_(hierObj) {} ~RemoveInvalid() { @@ -771,24 +711,25 @@ class SyncProcess::SyncRecursively { public: SyncRecursively(const SyncProcess* const syncProc, const SyncProcess::DeletionHandling& delHandling) : - syncProc_(syncProc), - delHandling_(delHandling) {} + syncProc_(syncProc), + delHandling_(delHandling) {} void execute(HierarchyObject& hierObj) { //enforce removal of invalid entries (where both sides are empty) RemoveInvalid dummy(hierObj); //non-recursive - //synchronize folders: - for (HierarchyObject::SubDirMapping::iterator i = hierObj.subDirs.begin(); i != hierObj.subDirs.end(); ++i) + //synchronize files: + for (HierarchyObject::SubFileMapping::iterator i = hierObj.subFiles.begin(); i != hierObj.subFiles.end(); ++i) { - if (deleteOnly) //no need, to process folders more than once! + if ( ( deleteOnly && deletionImminent(*i)) || + (!deleteOnly && !deletionImminent(*i))) { while (true) { try { - syncProc_->synchronizeFolder(*i, delHandling_); + syncProc_->synchronizeFile(*i, delHandling_); break; } catch (FileError& error) @@ -799,33 +740,27 @@ public: syncProc_->statusUpdater->requestUiRefresh(true); ErrorHandler::Response rv = syncProc_->statusUpdater->reportError(error.show()); - if (rv == ErrorHandler::IGNORE_ERROR) + if ( rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) - ; //continue with loop + ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } } } - - //recursive synchronization: don't recurse into already deleted subdirectories - if (!i->isEmpty()) - execute(*i); } - - //synchronize files: - for (HierarchyObject::SubFileMapping::iterator i = hierObj.subFiles.begin(); i != hierObj.subFiles.end(); ++i) + //synchronize folders: + for (HierarchyObject::SubDirMapping::iterator i = hierObj.subDirs.begin(); i != hierObj.subDirs.end(); ++i) { - if ( ( deleteOnly && deletionImminent(*i)) || - (!deleteOnly && !deletionImminent(*i))) + if (deleteOnly) //no need, to process folders more than once! { while (true) { try { - syncProc_->synchronizeFile(*i, delHandling_); + syncProc_->synchronizeFolder(*i, delHandling_); break; } catch (FileError& error) @@ -836,15 +771,19 @@ public: syncProc_->statusUpdater->requestUiRefresh(true); ErrorHandler::Response rv = syncProc_->statusUpdater->reportError(error.show()); - if ( rv == ErrorHandler::IGNORE_ERROR) + if (rv == ErrorHandler::IGNORE_ERROR) break; else if (rv == ErrorHandler::RETRY) - ; //continue with loop + ; //continue with loop else - assert (false); + throw std::logic_error("Programming Error: Unknown return value!"); } } } + + //recursive synchronization: + //if (!i->isEmpty()) -> not necessary, deleted folders have no sub-objects at this point + execute(*i); } } @@ -854,12 +793,73 @@ private: }; +template <typename Function> +inline +void tryReportingError(StatusHandler& handler, Function cmd) +{ + while (true) + { + try + { + cmd(); + break; + } + catch (FileError& error) + { + handler.requestUiRefresh(); //may throw! + + ErrorHandler::Response rv = handler.reportError(error.show()); //may throw! + if ( rv == ErrorHandler::IGNORE_ERROR) + break; + else if (rv == ErrorHandler::RETRY) + ; //continue with loop + else + throw std::logic_error("Programming Error: Unknown return value!"); + } + } +} + + +class UpdateDatabase +{ +public: + UpdateDatabase(const BaseDirMapping& baseMap, StatusHandler& statusHandler) : + baseMap_(baseMap), + statusHandler_(statusHandler) {} + + //update sync database after synchronization is finished + void updateNow() + { + //these calls may throw! + tryReportingError(statusHandler_, boost::bind(saveToDisk, boost::cref(baseMap_), LEFT_SIDE, baseMap_.getDBFilename<LEFT_SIDE>())); + tryReportingError(statusHandler_, boost::bind(saveToDisk, boost::cref(baseMap_), RIGHT_SIDE, baseMap_.getDBFilename<RIGHT_SIDE>())); + }; + //_("You can ignore the error to skip current folder pair.")); + +private: + const BaseDirMapping& baseMap_; + StatusHandler& statusHandler_; +}; + + +//avoid data loss when source directory doesn't (temporarily?) exist anymore AND user chose to ignore errors (else we wouldn't arrive here) +bool dataLossPossible(const Zstring& dirName, const SyncStatistics& folderPairStat) +{ + return folderPairStat.getCreate() + folderPairStat.getOverwrite() + folderPairStat.getConflict() == 0 && + folderPairStat.getDelete() > 0 && //deletions only... (respect filtered items!) + !dirName.empty() && !FreeFileSync::dirExists(dirName); +} + + void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCfg>& syncConfig, FolderComparison& folderCmp) { #ifndef __WXDEBUG__ wxLogNull noWxLogs; //prevent wxWidgets logging #endif + //PERF_START; + + //inform about the total amount of data that will be processed from now on const SyncStatistics statisticsTotal(folderCmp); @@ -898,12 +898,24 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf } } + //avoid data loss when source directory doesn't (temporarily?) exist anymore AND user chose to ignore errors(else we wouldn't arrive here) + if (dataLossPossible(j->getBaseDir<LEFT_SIDE>(), statisticsFolderPair)) + { + statusUpdater->reportFatalError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(j->getBaseDir<LEFT_SIDE>()) + wxT("\"")); + return; //should be obsolete! + } + if (dataLossPossible(j->getBaseDir<RIGHT_SIDE>(), statisticsFolderPair)) + { + statusUpdater->reportFatalError(wxString(_("Source directory does not exist anymore:")) + wxT("\n\"") + zToWx(j->getBaseDir<RIGHT_SIDE>()) + wxT("\"") ); + return; //should be obsolete! + } + //check if more than 50% of total number of files/dirs are to be created/overwritten/deleted if (significantDifferenceDetected(statisticsFolderPair)) { statusUpdater->reportWarning(wxString(_("Significant difference detected:")) + wxT("\n") + - j->getBaseDir<LEFT_SIDE>() + wxT(" <-> ") + wxT("\n") + - j->getBaseDir<RIGHT_SIDE>() + wxT("\n\n") + + zToWx(j->getBaseDir<LEFT_SIDE>()) + wxT(" <-> ") + wxT("\n") + + zToWx(j->getBaseDir<RIGHT_SIDE>()) + wxT("\n\n") + _("More than 50% of the total number of files will be copied or deleted!"), m_warnings.warningSignificantDifference); } @@ -912,11 +924,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf const std::pair<wxLongLong, wxLongLong> spaceNeeded = freeDiskSpaceNeeded(*j, folderPairCfg.handleDeletion); wxLongLong freeDiskSpaceLeft; - if (wxGetDiskSpace(j->getBaseDir<LEFT_SIDE>().c_str(), NULL, &freeDiskSpaceLeft)) + if (wxGetDiskSpace(zToWx(j->getBaseDir<LEFT_SIDE>()), NULL, &freeDiskSpaceLeft)) { if (freeDiskSpaceLeft < spaceNeeded.first) statusUpdater->reportWarning(wxString(_("Not enough free disk space available in:")) + wxT("\n") + - wxT("\"") + j->getBaseDir<LEFT_SIDE>() + wxT("\"\n\n") + + wxT("\"") + zToWx(j->getBaseDir<LEFT_SIDE>()) + wxT("\"\n\n") + _("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.first) + wxT("\n") + _("Free disk space available:") + wxT(" ") + formatFilesizeToShortString(freeDiskSpaceLeft), m_warnings.warningNotEnoughDiskSpace); @@ -924,11 +936,11 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //check for sufficient free diskspace in right directory wxLongLong freeDiskSpaceRight; - if (wxGetDiskSpace(j->getBaseDir<RIGHT_SIDE>().c_str(), NULL, &freeDiskSpaceRight)) + if (wxGetDiskSpace(zToWx(j->getBaseDir<RIGHT_SIDE>()), NULL, &freeDiskSpaceRight)) { if (freeDiskSpaceRight < spaceNeeded.second) statusUpdater->reportWarning(wxString(_("Not enough free disk space available in:")) + wxT("\n") + - wxT("\"") + j->getBaseDir<RIGHT_SIDE>() + wxT("\"\n\n") + + wxT("\"") + zToWx(j->getBaseDir<RIGHT_SIDE>()) + wxT("\"\n\n") + _("Total required free disk space:") + wxT(" ") + formatFilesizeToShortString(spaceNeeded.second) + wxT("\n") + _("Free disk space available:") + wxT(" ") + formatFilesizeToShortString(freeDiskSpaceRight), m_warnings.warningNotEnoughDiskSpace); @@ -954,16 +966,27 @@ void SyncProcess::startSynchronizationProcess(const std::vector<FolderPairSyncCf //generate name of alternate deletion directory (unique for session AND folder pair) const DeletionHandling currentDelHandling(folderPairCfg.handleDeletion, folderPairCfg.custDelFolder); +//------------------------------------------------------------------------------------------ //execute synchronization recursively //loop through all files twice; reason: first delete, then copy SyncRecursively<true>( this, currentDelHandling).execute(*j); SyncRecursively<false>(this, currentDelHandling).execute(*j); +//------------------------------------------------------------------------------------------ + + //update synchronization database (automatic sync only) + if (folderPairCfg.updateSyncDB) + { + UpdateDatabase syncDB(*j, *statusUpdater); + statusUpdater->updateStatusText(wxToZ(_("Generating database..."))); + statusUpdater->forceUiRefresh(); + syncDB.updateNow(); + } } } catch (const std::exception& e) { - statusUpdater->reportFatalError(wxString::From8BitData(e.what())); + statusUpdater->reportFatalError(wxString::FromAscii(e.what())); return; //should be obsolete! } } @@ -977,8 +1000,8 @@ class WhileCopying : public FreeFileSync::CopyFileCallback //callback functional public: WhileCopying(wxLongLong& bytesTransferredLast, StatusHandler* statusHandler) : - m_bytesTransferredLast(bytesTransferredLast), - m_statusHandler(statusHandler) {} + m_bytesTransferredLast(bytesTransferredLast), + m_statusHandler(statusHandler) {} virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) { @@ -1049,22 +1072,6 @@ void SyncProcess::copyFileUpdating(const Zstring& source, const Zstring& target, //--------------------- data verification ------------------------- -struct MemoryAllocator -{ - MemoryAllocator() - { - buffer = new unsigned char[bufferSize]; - } - - ~MemoryAllocator() - { - delete [] buffer; - } - - static const unsigned int bufferSize = 512 * 1024; //512 kb seems to be the perfect buffer size - unsigned char* buffer; -}; - //callback functionality for status updates while verifying class VerifyCallback @@ -1077,29 +1084,38 @@ public: void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback* callback) // throw (FileError) { - static MemoryAllocator memory1; - static MemoryAllocator memory2; + const unsigned int BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size + static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]); + static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]); +#ifdef FFS_WIN wxFile file1(source.c_str(), wxFile::read); //don't use buffered file input for verification! +#elif defined FFS_LINUX + wxFile file1(::open(source.c_str(), O_RDONLY)); //utilize UTF-8 filename +#endif if (!file1.IsOpened()) - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + source.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(source) + wxT("\"")); - wxFile file2(target.c_str(), wxFile::read); +#ifdef FFS_WIN + wxFile file2(target.c_str(), wxFile::read); //don't use buffered file input for verification! +#elif defined FFS_LINUX + wxFile file2(::open(target.c_str(), O_RDONLY)); //utilize UTF-8 filename +#endif if (!file2.IsOpened()) //NO cleanup necessary for (wxFile) file1 - throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + target.c_str() + wxT("\"")); + throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(target) + wxT("\"")); do { - const size_t length1 = file1.Read(memory1.buffer, MemoryAllocator::bufferSize); - if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + source.c_str() + wxT("\"")); + const size_t length1 = file1.Read(memory1.get(), BUFFER_SIZE); + if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(source) + wxT("\"")); - const size_t length2 = file2.Read(memory2.buffer, MemoryAllocator::bufferSize); - if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + target.c_str() + wxT("\"")); + const size_t length2 = file2.Read(memory2.get(), BUFFER_SIZE); + if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(target) + wxT("\"")); - if (length1 != length2 || ::memcmp(memory1.buffer, memory2.buffer, length1) != 0) + if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0) { const wxString errorMsg = wxString(_("Data verification error: Source and target file have different content!")) + wxT("\n"); - throw FileError(errorMsg + wxT("\"") + source + wxT("\" -> \n\"") + target + wxT("\"")); + throw FileError(errorMsg + wxT("\"") + zToWx(source) + wxT("\" -> \n\"") + zToWx(target) + wxT("\"")); } //send progress updates @@ -1110,7 +1126,7 @@ void verifyFiles(const Zstring& source, const Zstring& target, VerifyCallback* c if (!file2.Eof()) { const wxString errorMsg = wxString(_("Data verification error: Source and target file have different content!")) + wxT("\n"); - throw FileError(errorMsg + wxT("\"") + source + wxT("\" -> \n\"") + target + wxT("\"")); + throw FileError(errorMsg + wxT("\"") + zToWx(source) + wxT("\" -> \n\"") + zToWx(target) + wxT("\"")); } } @@ -1133,7 +1149,7 @@ private: void SyncProcess::verifyFileCopy(const Zstring& source, const Zstring& target) const { Zstring statusText = txtVerifying; - statusText.Replace(wxT("%x"), target, false); + statusText.Replace(DefaultStr("%x"), target, false); statusUpdater->updateStatusText(statusText); statusUpdater->requestUiRefresh(); //trigger display refresh @@ -1154,3 +1170,9 @@ void SyncProcess::verifyFileCopy(const Zstring& source, const Zstring& target) c } } } + + + + + + diff --git a/synchronization.h b/synchronization.h index 0e54b123..95b297ce 100644 --- a/synchronization.h +++ b/synchronization.h @@ -14,123 +14,119 @@ class StatusHandler; namespace FreeFileSync { - class SyncStatistics - { - public: - SyncStatistics(const BaseDirMapping& baseDir); - SyncStatistics(const FolderComparison& folderCmp); - - int getCreate( bool inclLeft = true, bool inclRight = true) const; - int getOverwrite(bool inclLeft = true, bool inclRight = true) const; - int getDelete( bool inclLeft = true, bool inclRight = true) const; - int getConflict() const; - wxULongLong getDataToProcess() const; - int getRowCount() const; - - private: - void init(); - - void getNumbersRecursively(const HierarchyObject& hierObj); - - void getFileNumbers(const FileMapping& fileObj); - void getDirNumbers(const DirMapping& dirObj); - - int createLeft, createRight; - int overwriteLeft, overwriteRight; - int deleteLeft, deleteRight; - int conflict; - wxULongLong dataToProcess; - int rowsTotal; - }; - - bool synchronizationNeeded(const FolderComparison& folderCmp); +class SyncStatistics +{ +public: + SyncStatistics(const HierarchyObject& hierObj); + SyncStatistics(const FolderComparison& folderCmp); - SyncOperation getSyncOperation(const CompareFilesResult cmpResult, - const bool selectedForSynchronization, - const SyncDirection syncDir); //evaluate comparison result and sync direction + int getCreate( bool inclLeft = true, bool inclRight = true) const; + int getOverwrite(bool inclLeft = true, bool inclRight = true) const; + int getDelete( bool inclLeft = true, bool inclRight = true) const; + int getConflict() const; + wxULongLong getDataToProcess() const; + int getRowCount() const; +private: + void init(); - SyncOperation getSyncOperation(const FileSystemObject& fsObj); //convenience function + void getNumbersRecursively(const HierarchyObject& hierObj); + void getFileNumbers(const FileMapping& fileObj); + void getDirNumbers(const DirMapping& dirObj); - struct FolderPairSyncCfg - { - FolderPairSyncCfg(const DeletionPolicy handleDel, - const wxString& custDelDir) : - handleDeletion(handleDel), - custDelFolder(custDelDir) {} + int createLeft, createRight; + int overwriteLeft, overwriteRight; + int deleteLeft, deleteRight; + int conflict; + wxULongLong dataToProcess; + int rowsTotal; +}; - DeletionPolicy handleDeletion; - wxString custDelFolder; - }; - std::vector<FolderPairSyncCfg> extractSyncCfg(const MainConfiguration& mainCfg); +bool synchronizationNeeded(const FolderComparison& folderCmp); - //class handling synchronization process - class SyncProcess - { - public: - SyncProcess(const bool copyFileSymLinks, - const bool traverseDirSymLinks, - xmlAccess::OptionalDialogs& warnings, - const bool verifyCopiedFiles, - StatusHandler* handler); +struct FolderPairSyncCfg +{ + FolderPairSyncCfg(bool inAutomaticMode, + const DeletionPolicy handleDel, + const Zstring& custDelDir) : + updateSyncDB(inAutomaticMode), + handleDeletion(handleDel), + custDelFolder(custDelDir) {} + + bool updateSyncDB; //update database if in automatic mode + DeletionPolicy handleDeletion; + Zstring custDelFolder; +}; +std::vector<FolderPairSyncCfg> extractSyncCfg(const MainConfiguration& mainCfg); + + +//class handling synchronization process +class SyncProcess +{ +public: + SyncProcess(const bool copyFileSymLinks, + const bool traverseDirSymLinks, + xmlAccess::OptionalDialogs& warnings, + const bool verifyCopiedFiles, + StatusHandler* handler); - //CONTRACT: syncConfig must have SAME SIZE folderCmp and correspond per row! - void startSynchronizationProcess(const std::vector<FolderPairSyncCfg>& syncConfig, FolderComparison& folderCmp); + //CONTRACT: syncConfig must have SAME SIZE folderCmp and correspond per row! + void startSynchronizationProcess(const std::vector<FolderPairSyncCfg>& syncConfig, FolderComparison& folderCmp); - private: +private: template <bool deleteOnly> class SyncRecursively; - struct DeletionHandling - { - DeletionHandling(const DeletionPolicy handleDel, - const wxString& custDelFolder); + struct DeletionHandling + { + DeletionHandling(const DeletionPolicy handleDel, + const Zstring& custDelFolder); - DeletionPolicy handleDeletion; - Zstring currentDelFolder; //alternate deletion folder for current folder pair (with timestamp, ends with path separator) - //preloaded status texts: - const Zstring txtMoveFileUserDefined; - const Zstring txtMoveFolderUserDefined; - }; + DeletionPolicy handleDeletion; + Zstring currentDelFolder; //alternate deletion folder for current folder pair (with timestamp, ends with path separator) + //preloaded status texts: + const Zstring txtMoveFileUserDefined; + const Zstring txtMoveFolderUserDefined; + }; - void syncRecursively(HierarchyObject& hierObj); - void synchronizeFile(FileMapping& fileObj, const DeletionHandling& delHandling) const; - void synchronizeFolder(DirMapping& dirObj, const DeletionHandling& delHandling) const; + void syncRecursively(HierarchyObject& hierObj); + void synchronizeFile(FileMapping& fileObj, const DeletionHandling& delHandling) const; + void synchronizeFolder(DirMapping& dirObj, const DeletionHandling& delHandling) const; - template <FreeFileSync::SelectedSide side> - void removeFile(const FileMapping& fileObj, const DeletionHandling& delHandling, bool showStatusUpdate) const; + template <FreeFileSync::SelectedSide side> + void removeFile(const FileMapping& fileObj, const DeletionHandling& delHandling, bool showStatusUpdate) const; - template <FreeFileSync::SelectedSide side> - void removeFolder(const DirMapping& dirObj, const DeletionHandling& delHandling) const; + template <FreeFileSync::SelectedSide side> + void removeFolder(const DirMapping& dirObj, const DeletionHandling& delHandling) const; - void copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& sourceFileSize) const; - void verifyFileCopy(const Zstring& source, const Zstring& target) const; + void copyFileUpdating(const Zstring& source, const Zstring& target, const wxULongLong& sourceFileSize) const; + void verifyFileCopy(const Zstring& source, const Zstring& target) const; - const bool m_copyFileSymLinks; - const bool m_traverseDirSymLinks; - const bool m_verifyCopiedFiles; + const bool m_copyFileSymLinks; + const bool m_traverseDirSymLinks; + const bool m_verifyCopiedFiles; - //warnings - xmlAccess::OptionalDialogs& m_warnings; + //warnings + xmlAccess::OptionalDialogs& m_warnings; #ifdef FFS_WIN - //shadow copy buffer - std::auto_ptr<ShadowCopy> shadowCopyHandler; + //shadow copy buffer + std::auto_ptr<ShadowCopy> shadowCopyHandler; #endif - StatusHandler* const statusUpdater; - - //preload status texts - const Zstring txtCopyingFile; - const Zstring txtOverwritingFile; - const Zstring txtCreatingFolder; - const Zstring txtDeletingFile; - const Zstring txtDeletingFolder; - const Zstring txtMoveToRecycler; - const Zstring txtVerifying; - }; + StatusHandler* const statusUpdater; + + //preload status texts + const Zstring txtCopyingFile; + const Zstring txtOverwritingFile; + const Zstring txtCreatingFolder; + const Zstring txtDeletingFile; + const Zstring txtDeletingFolder; + const Zstring txtMoveToRecycler; + const Zstring txtVerifying; +}; } #endif // SYNCHRONIZATION_H_INCLUDED diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp index d053bed5..f87cbd93 100644 --- a/ui/MainDialog.cpp +++ b/ui/MainDialog.cpp @@ -11,10 +11,12 @@ #include "../comparison.h" #include "../synchronization.h" #include "../algorithm.h" +#include "util.h" #include "checkVersion.h" #include "guiStatusHandler.h" -#include "syncDialog.h" +#include "settingsDialog.h" #include "../shared/localization.h" +#include "../shared/stringConv.h" #include "smallDialogs.h" #include "../shared/dragAndDrop.h" #include "../library/filter.h" @@ -40,8 +42,8 @@ class FolderPairPanel : public FolderPairParent { public: FolderPairPanel(wxWindow* parent, MainDialog* mainDialog) : - FolderPairParent(parent), - mainDlg(mainDialog) + FolderPairParent(parent), + mainDlg(mainDialog) {} private: @@ -93,8 +95,8 @@ public: wxDirPickerCtrl* dirPicker, wxComboBox* dirName) : - DragDropOnMainDlg(dropWindow1, dropWindow2, dirPicker, dirName), - mainDlg_(mainDlg) {} + DragDropOnMainDlg(dropWindow1, dropWindow2, dirPicker, dirName), + mainDlg_(mainDlg) {} virtual bool AcceptDrop(const wxString& dropName) { @@ -172,17 +174,17 @@ private: //################################################################################################################################## MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, xmlAccess::XmlGlobalSettings& settings) : - MainDialogGenerated(frame), - globalSettings(settings), - gridDataView(new FreeFileSync::GridView()), - contextMenu(new wxMenu), //initialize right-click context menu; will be dynamically re-created on each R-mouse-click - cleanedUp(false), - lastSortColumn(-1), - lastSortGrid(NULL), + MainDialogGenerated(frame), + globalSettings(settings), + gridDataView(new FreeFileSync::GridView()), + contextMenu(new wxMenu), //initialize right-click context menu; will be dynamically re-created on each R-mouse-click + cleanedUp(false), + lastSortColumn(-1), + lastSortGrid(NULL), #ifdef FFS_WIN - updateFileIcons(new IconUpdater(m_gridLeft, m_gridRight)), + updateFileIcons(new IconUpdater(m_gridLeft, m_gridRight)), #endif - syncPreview(this) + syncPreview(this) { wxWindowUpdateLocker dummy(this); //avoid display distortion @@ -418,7 +420,7 @@ void MainDialog::setSyncDirManually(const std::set<unsigned int>& rowsToSetOnUiT FileSystemObject* fsObj = gridDataView->getObject(*i); if (fsObj) { - setSyncDirection(dir, *fsObj); //set new direction (recursively) + setSyncDirectionRec(dir, *fsObj); //set new direction (recursively) FilterProcess::setActiveStatus(true, *fsObj); //works recursively for directories } } @@ -437,7 +439,7 @@ void MainDialog::filterRangeManually(const std::set<unsigned int>& rowsToFilterO //leadingRow determines de-/selection of all other rows const FileSystemObject* fsObj = gridDataView->getObject(leadingRow); if (fsObj) - newSelection = !fsObj->selectedForSynchronization; + newSelection = !fsObj->isActive(); //if hidefiltered is active, there should be no filtered elements on screen => current element was filtered out assert(!currentCfg.hideFilteredElements || !newSelection); @@ -530,11 +532,11 @@ class ManualDeletionHandler : private wxEvtHandler, public DeleteFilesHandler { public: ManualDeletionHandler(MainDialog* main, int totalObjToDel) : - mainDlg(main), - totalObjToDelete(totalObjToDel), - abortRequested(false), - ignoreErrors(false), - deletionCount(0) + mainDlg(main), + totalObjToDelete(totalObjToDel), + abortRequested(false), + ignoreErrors(false), + deletionCount(0) { mainDlg->disableAllElements(); //disable everything except abort button mainDlg->clearStatusBar(); @@ -648,7 +650,8 @@ void MainDialog::deleteSelectedFiles() } try - { //handle errors when deleting files/folders + { + //handle errors when deleting files/folders ManualDeletionHandler statusHandler(this, totalDeleteCount); FreeFileSync::deleteFromGridAndHD(gridDataView->getDataTentative(), @@ -683,15 +686,15 @@ void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir) const FileMapping* fileObj = dynamic_cast<const FileMapping*>(&fsObj); if (fileObj != NULL) { - name = fsObj.getFullName<side>().c_str(); - dir = name.BeforeLast(globalFunctions::FILE_NAME_SEPARATOR); + name = zToWx(fsObj.getFullName<side>()); + dir = zToWx(fsObj.getFullName<side>().BeforeLast(globalFunctions::FILE_NAME_SEPARATOR)); } else { const DirMapping* dirObj = dynamic_cast<const DirMapping*>(&fsObj); if (dirObj != NULL) { - name = fsObj.getFullName<side>().c_str(); + name = zToWx(fsObj.getFullName<side>()); dir = name; } } @@ -741,9 +744,10 @@ void MainDialog::openExternalApplication(unsigned int rowNumber, bool leftSide, #endif } else - { //fallback - dir = FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue().c_str()).c_str(); - dirCo = FreeFileSync::getFormattedDirectoryName(m_directoryRight->GetValue().c_str()).c_str(); + { + //fallback + dir = zToWx(FreeFileSync::getFormattedDirectoryName(wxToZ(m_directoryLeft->GetValue()))); + dirCo = zToWx(FreeFileSync::getFormattedDirectoryName(wxToZ(m_directoryRight->GetValue()))); if (!leftSide) std::swap(dir, dirCo); @@ -784,7 +788,8 @@ void MainDialog::clearStatusBar() void MainDialog::disableAllElements() -{ //disenables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion +{ + //disenables all elements (except abort button) that might receive user input during long-running processes: comparison, deletion m_bpButtonCmpConfig-> Disable(); m_notebookBottomLeft->Disable(); m_checkBoxHideFilt-> Disable(); @@ -869,7 +874,8 @@ void MainDialog::OnResize(wxSizeEvent& event) GetPosition(&x, &y); if (width > 0 && height > 0 && x >= 0 && y >= 0) //test ALL parameters at once, since width/height are invalid if - { //the window is minimized (eg x,y == -32000; height = 28, width = 160) + { + //the window is minimized (eg x,y == -32000; height = 28, width = 160) widthNotMaximized = width; heightNotMaximized = height; @@ -997,17 +1003,17 @@ void MainDialog::onGridRightButtonEvent(wxKeyEvent& event) //temporal variables used by exclude via context menu struct SelectedExtension : public wxObject { - SelectedExtension(const wxString& ext) : extension(ext) {} + SelectedExtension(const Zstring& ext) : extension(ext) {} - wxString extension; + Zstring extension; }; struct FilterObject { - FilterObject(const wxString& relName, bool isDirectory) : - relativeName(relName), - isDir(isDirectory) {} - wxString relativeName; + FilterObject(const Zstring& relName, bool isDirectory) : + relativeName(relName), + isDir(isDirectory) {} + Zstring relativeName; bool isDir; }; @@ -1066,17 +1072,17 @@ void MainDialog::OnContextRim(wxGridEvent& event) { //CONTEXT_SYNC_DIR_LEFT wxMenuItem* menuItemSyncDirLeft = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_LEFT, _("Change direction")); - menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_LEFT)); + menuItemSyncDirLeft->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_LEFT))); contextMenu->Append(menuItemSyncDirLeft); //CONTEXT_SYNC_DIR_NONE wxMenuItem* menuItemSyncDirNone = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_NONE, _("Change direction")); - menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_NONE)); + menuItemSyncDirNone->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_NONE))); contextMenu->Append(menuItemSyncDirNone); //CONTEXT_SYNC_DIR_RIGHT wxMenuItem* menuItemSyncDirRight = new wxMenuItem(contextMenu.get(), CONTEXT_SYNC_DIR_RIGHT, _("Change direction")); - menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->getCategory(), true, SYNC_DIR_RIGHT)); + menuItemSyncDirRight->SetBitmap(getSyncOpImage(fsObj->testSyncOperation(true, SYNC_DIR_RIGHT))); contextMenu->Append(menuItemSyncDirRight); contextMenu->AppendSeparator(); @@ -1087,7 +1093,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_FILTER_TEMP if (fsObj && (selectionLeft.size() + selectionRight.size() > 0)) { - if (fsObj->selectedForSynchronization) + if (fsObj->isActive()) { wxMenuItem* menuItemExclTemp = new wxMenuItem(contextMenu.get(), CONTEXT_FILTER_TEMP, wxString(_("Exclude temporarily")) + wxT("\tSPACE")); menuItemExclTemp->SetBitmap(*GlobalResources::getInstance().bitmapCheckBoxFalse); @@ -1114,7 +1120,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) const FileSystemObject* currObj = gridDataView->getObject(*i); if (currObj && !currObj->isEmpty<LEFT_SIDE>()) exFilterCandidateObj.push_back( - FilterObject(currObj->getRelativeName<LEFT_SIDE>().c_str(), + FilterObject(currObj->getRelativeName<LEFT_SIDE>(), dynamic_cast<const DirMapping*>(currObj) != NULL)); } for (std::set<unsigned int>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i) @@ -1122,7 +1128,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) const FileSystemObject* currObj = gridDataView->getObject(*i); if (currObj && !currObj->isEmpty<RIGHT_SIDE>()) exFilterCandidateObj.push_back( - FilterObject(currObj->getRelativeName<RIGHT_SIDE>().c_str(), + FilterObject(currObj->getRelativeName<RIGHT_SIDE>(), dynamic_cast<const DirMapping*>(currObj) != NULL)); } //############################################################################################### @@ -1130,13 +1136,13 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_EXT if (exFilterCandidateObj.size() > 0 && !exFilterCandidateObj[0].isDir) { - const wxString filename = exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR); - if (filename.Find(wxChar('.')) != wxNOT_FOUND) //be careful: AfterLast will return the whole string if '.' is not found! + const Zstring filename = exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR); + if (filename.Find(wxChar('.'), false) != Zstring::npos) //be careful: AfterLast will return the whole string if '.' is not found! { - const wxString extension = filename.AfterLast(wxChar('.')); + const Zstring extension = filename.AfterLast(DefaultChar('.')); //add context menu item - wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + extension); + wxMenuItem* menuItemExclExt = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + zToWx(extension)); menuItemExclExt->SetBitmap(*GlobalResources::getInstance().bitmapFilterSmall); contextMenu->Append(menuItemExclExt); @@ -1153,7 +1159,7 @@ void MainDialog::OnContextRim(wxGridEvent& event) //CONTEXT_EXCLUDE_OBJ wxMenuItem* menuItemExclObj = NULL; if (exFilterCandidateObj.size() == 1) - menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR)); + menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + zToWx(exFilterCandidateObj[0].relativeName.AfterLast(globalFunctions::FILE_NAME_SEPARATOR))); else if (exFilterCandidateObj.size() > 1) menuItemExclObj = new wxMenuItem(contextMenu.get(), CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>")); @@ -1236,7 +1242,8 @@ void MainDialog::OnContextFilterTemp(wxCommandEvent& event) { //merge selections from left and right grid std::set<unsigned int> selection = getSelectedRows(); - filterRangeManually(selection, *selection.begin()); + if (!selection.empty()) + filterRangeManually(selection, *selection.begin()); } @@ -1245,10 +1252,10 @@ void MainDialog::OnContextExcludeExtension(wxCommandEvent& event) SelectedExtension* selExtension = dynamic_cast<SelectedExtension*>(event.m_callbackUserData); if (selExtension) { - if (!currentCfg.mainCfg.excludeFilter.IsEmpty() && !currentCfg.mainCfg.excludeFilter.EndsWith(wxT(";"))) - currentCfg.mainCfg.excludeFilter += wxT("\n"); + if (!currentCfg.mainCfg.excludeFilter.empty() && !currentCfg.mainCfg.excludeFilter.EndsWith(DefaultStr(";"))) + currentCfg.mainCfg.excludeFilter += DefaultStr("\n"); - currentCfg.mainCfg.excludeFilter += wxString(wxT("*.")) + selExtension->extension + wxT(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line + currentCfg.mainCfg.excludeFilter += Zstring(DefaultStr("*.")) + selExtension->extension + DefaultStr(";"); //';' is appended to 'mark' that next exclude extension entry won't write to new line currentCfg.mainCfg.filterIsActive = true; updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive); @@ -1275,13 +1282,13 @@ void MainDialog::OnContextExcludeObject(wxCommandEvent& event) { for (std::vector<FilterObject>::const_iterator i = objCont->selectedObjects.begin(); i != objCont->selectedObjects.end(); ++i) { - if (!currentCfg.mainCfg.excludeFilter.IsEmpty() && !currentCfg.mainCfg.excludeFilter.EndsWith(wxT("\n"))) - currentCfg.mainCfg.excludeFilter+= wxT("\n"); + if (!currentCfg.mainCfg.excludeFilter.empty() && !currentCfg.mainCfg.excludeFilter.EndsWith(DefaultStr("\n"))) + currentCfg.mainCfg.excludeFilter += DefaultStr("\n"); if (!i->isDir) - currentCfg.mainCfg.excludeFilter+= wxString(globalFunctions::FILE_NAME_SEPARATOR) + i->relativeName; + currentCfg.mainCfg.excludeFilter += Zstring() + globalFunctions::FILE_NAME_SEPARATOR + i->relativeName; else - currentCfg.mainCfg.excludeFilter+= wxString(globalFunctions::FILE_NAME_SEPARATOR) + i->relativeName + globalFunctions::FILE_NAME_SEPARATOR + wxT("*"); + currentCfg.mainCfg.excludeFilter += Zstring() + globalFunctions::FILE_NAME_SEPARATOR + i->relativeName + globalFunctions::FILE_NAME_SEPARATOR + DefaultStr("*"); } currentCfg.mainCfg.filterIsActive = true; @@ -1585,7 +1592,8 @@ void MainDialog::addFileToCfgHistory(const wxString& filename) std::vector<wxString>::const_iterator i = find_if(cfgFileNames.begin(), cfgFileNames.end(), FindDuplicates(filename)); if (i != cfgFileNames.end()) - { //if entry is in the list, then jump to element + { + //if entry is in the list, then jump to element m_choiceHistory->SetSelection(i - cfgFileNames.begin()); } else @@ -1671,11 +1679,13 @@ bool MainDialog::trySaveConfig() //return true if saved successfully { const wxString newFileName = filePicker->GetPath(); - if (FreeFileSync::fileExists(newFileName.c_str())) + if (FreeFileSync::fileExists(wxToZ(newFileName))) { - wxMessageDialog* messageDlg = new wxMessageDialog(this, wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""), _("Warning") , wxOK | wxCANCEL); + QuestionDlg* messageDlg = new QuestionDlg(this, + QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL, + wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")); - if (messageDlg->ShowModal() != wxID_OK) + if (messageDlg->ShowModal() != QuestionDlg::BUTTON_YES) return trySaveConfig(); //retry } @@ -1735,7 +1745,7 @@ bool MainDialog::saveOldConfig() //return false on user abort QuestionDlg* notifyChangeDlg = new QuestionDlg(this, QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_NO | QuestionDlg::BUTTON_CANCEL, _("Save changes to current configuration?"), - dontShowAgain); + &dontShowAgain); switch (notifyChangeDlg->ShowModal()) { @@ -1772,12 +1782,14 @@ void MainDialog::OnCfgHistoryKeyEvent(wxKeyEvent& event) { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_DELETE || keyCode == WXK_NUMPAD_DELETE) - { //try to delete the currently selected config history item + { + //try to delete the currently selected config history item const int selectedItem = m_choiceHistory->GetCurrentSelection(); if ( 0 <= selectedItem && selectedItem < int(m_choiceHistory->GetCount()) && selectedItem < int(cfgFileNames.size())) - { //delete selected row + { + //delete selected row cfgFileNames.erase(cfgFileNames.begin() + selectedItem); m_choiceHistory->Delete(selectedItem); } @@ -1871,7 +1883,7 @@ void MainDialog::OnSetSyncDirection(FFSSyncDirectionEvent& event) FileSystemObject* fsObj = gridDataView->getObject(i); if (fsObj) { - setSyncDirection(event.direction, *fsObj); //set new direction (recursively) + setSyncDirectionRec(event.direction, *fsObj); //set new direction (recursively) FilterProcess::setActiveStatus(true, *fsObj); //works recursively for directories } } @@ -1987,8 +1999,8 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf //read main folder pair - const wxString mainFolderLeft = currentCfg.mainCfg.mainFolderPair.leftDirectory.c_str(); - const wxString mainFolderRight = currentCfg.mainCfg.mainFolderPair.rightDirectory.c_str(); + const wxString mainFolderLeft = zToWx(currentCfg.mainCfg.mainFolderPair.leftDirectory); + const wxString mainFolderRight = zToWx(currentCfg.mainCfg.mainFolderPair.rightDirectory); FreeFileSync::setDirectoryName(mainFolderLeft, m_directoryLeft, m_dirPickerLeft); FreeFileSync::setDirectoryName(mainFolderRight, m_directoryRight, m_dirPickerRight); @@ -2020,8 +2032,8 @@ void MainDialog::setCurrentConfiguration(const xmlAccess::XmlGuiConfig& newGuiCf inline FolderPairEnh getEnahncedPair(const FolderPairPanel* panel) { - return FolderPairEnh(panel->m_directoryLeft->GetValue().c_str(), - panel->m_directoryRight->GetValue().c_str(), + return FolderPairEnh(wxToZ(panel->m_directoryLeft->GetValue()), + wxToZ(panel->m_directoryRight->GetValue()), panel->altSyncConfig, panel->altFilter); } @@ -2034,8 +2046,8 @@ xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const //load settings whose ownership lies not in currentCfg: //main folder pair - guiCfg.mainCfg.mainFolderPair.leftDirectory = m_directoryLeft->GetValue().c_str(); - guiCfg.mainCfg.mainFolderPair.rightDirectory = m_directoryRight->GetValue().c_str(); + guiCfg.mainCfg.mainFolderPair.leftDirectory = wxToZ(m_directoryLeft->GetValue()); + guiCfg.mainCfg.mainFolderPair.rightDirectory = wxToZ(m_directoryRight->GetValue()); //add additional pairs guiCfg.mainCfg.additionalPairs.clear(); @@ -2052,9 +2064,9 @@ xmlAccess::XmlGuiConfig MainDialog::getCurrentConfiguration() const const wxString& MainDialog::lastConfigFileName() { - static wxString instance = FreeFileSync::getConfigDir().EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR)) ? + static wxString instance = FreeFileSync::getConfigDir().EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR)) ? FreeFileSync::getConfigDir() + wxT("LastRun.ffs_gui") : - FreeFileSync::getConfigDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("LastRun.ffs_gui"); + FreeFileSync::getConfigDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("LastRun.ffs_gui"); return instance; } @@ -2081,7 +2093,8 @@ void MainDialog::refreshGridAfterFilterChange(const int delay) void MainDialog::OnFilterButton(wxCommandEvent &event) -{ //toggle filter on/off +{ + //toggle filter on/off currentCfg.mainCfg.filterIsActive = !currentCfg.mainCfg.filterIsActive; //make sure, button-appearance and "filterIsActive" are in sync. updateFilterButton(m_bpButtonFilter, currentCfg.mainCfg.filterIsActive); @@ -2091,7 +2104,8 @@ void MainDialog::OnFilterButton(wxCommandEvent &event) void MainDialog::OnHideFilteredButton(wxCommandEvent &event) -{ //toggle showing filtered rows +{ + //toggle showing filtered rows currentCfg.hideFilteredElements = !currentCfg.hideFilteredElements; //make sure, checkbox and "hideFiltered" are in sync m_checkBoxHideFilt->SetValue(currentCfg.hideFilteredElements); @@ -2109,7 +2123,8 @@ void MainDialog::OnConfigureFilter(wxHyperlinkEvent &event) FilterDlg* filterDlg = new FilterDlg(this, currentCfg.mainCfg.includeFilter, currentCfg.mainCfg.excludeFilter); if (filterDlg->ShowModal() == FilterDlg::BUTTON_APPLY) { - if (currentCfg.mainCfg.includeFilter == wxT("*") && currentCfg.mainCfg.excludeFilter.empty()) //default + if (currentCfg.mainCfg.includeFilter == defaultIncludeFilter() && + currentCfg.mainCfg.excludeFilter == defaultExcludeFilter()) //default updateFilterConfig(false); //re-apply filter (without changing active-status) else updateFilterConfig(true); //activate(and apply) filter @@ -2352,7 +2367,8 @@ void MainDialog::OnCompare(wxCommandEvent &event) bool aborted = false; try - { //class handling status display and error messages + { + //class handling status display and error messages CompareStatusHandler statusHandler(this); //begin comparison @@ -2378,12 +2394,14 @@ void MainDialog::OnCompare(wxCommandEvent &event) } if (aborted) - { //disable the sync button + { + //disable the sync button syncPreview.enableSynchronization(false); m_buttonCompare->SetFocus(); } else - { //once compare is finished enable the sync button + { + //once compare is finished enable the sync button syncPreview.enableSynchronization(true); m_buttonStartSync->SetFocus(); @@ -2579,7 +2597,8 @@ void MainDialog::OnStartSync(wxCommandEvent& event) synchronization.startSynchronizationProcess(syncProcessCfg, dataToSync); } catch (AbortThisProcess&) - { //do NOT disable the sync button: user might want to try to sync the REMAINING rows + { + //do NOT disable the sync button: user might want to try to sync the REMAINING rows } //enableSynchronization(false); //remove rows that empty: just a beautification, invalid rows shouldn't cause issues @@ -2777,7 +2796,7 @@ void MainDialog::OnSwapSides(wxCommandEvent& event) m_bpButtonSyncDirOverwRight->setActive(tmp); //swap grid information - FreeFileSync::swapGrids2(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + FreeFileSync::swapGrids(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); updateGuiGrid(); event.Skip(); } @@ -3067,7 +3086,33 @@ void MainDialog::updateSyncConfig() m_staticTextSyncVariant->SetLabel(wxString(wxT("(")) + getCurrentConfiguration().mainCfg.getSyncVariantName() + wxT(")")); bSizer6->Layout(); //adapt layout for variant text - FreeFileSync::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative()); + + class RedetermineCallback : public DeterminationProblem + { + public: + RedetermineCallback(bool& warningSyncDatabase, wxWindow* parent) : + warningSyncDatabase_(warningSyncDatabase), + parent_(parent) {} + + virtual void reportWarning(const wxString& text) + { + if (warningSyncDatabase_) + { + bool dontWarnAgain = false; + WarningDlg* warningDlg = new WarningDlg(parent_, //show popup and ask user how to handle warning + WarningDlg::BUTTON_IGNORE, + text, + dontWarnAgain); + if (warningDlg->ShowModal() == WarningDlg::BUTTON_IGNORE) + warningSyncDatabase_ = !dontWarnAgain; + } + } + private: + bool& warningSyncDatabase_; + wxWindow* parent_; + } redetCallback(globalSettings.optDialogs.warningSyncDatabase, this); + + FreeFileSync::redetermineSyncDirection(getCurrentConfiguration().mainCfg, gridDataView->getDataTentative(), &redetCallback); updateGuiGrid(); } @@ -3134,8 +3179,8 @@ void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainDialog::OnRemoveFolderPair), NULL, this); //insert directory names - FreeFileSync::setDirectoryName(i->leftDirectory.c_str(), newPair->m_directoryLeft, newPair->m_dirPickerLeft); - FreeFileSync::setDirectoryName(i->rightDirectory.c_str(), newPair->m_directoryRight, newPair->m_dirPickerRight); + FreeFileSync::setDirectoryName(zToWx(i->leftDirectory), newPair->m_directoryLeft, newPair->m_dirPickerLeft); + FreeFileSync::setDirectoryName(zToWx(i->rightDirectory), newPair->m_directoryRight, newPair->m_dirPickerRight); //set alternate configuration newPair->altSyncConfig = i->altSyncConfig; @@ -3216,11 +3261,13 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) if (filePicker->ShowModal() == wxID_OK) { const wxString newFileName = filePicker->GetPath(); - if (FreeFileSync::fileExists(newFileName.c_str())) + if (FreeFileSync::fileExists(wxToZ(newFileName))) { - wxMessageDialog* messageDlg = new wxMessageDialog(this, wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""), _("Warning") , wxOK | wxCANCEL); + QuestionDlg* messageDlg = new QuestionDlg(this, + QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL, + wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")); - if (messageDlg->ShowModal() != wxID_OK) + if (messageDlg->ShowModal() != QuestionDlg::BUTTON_YES) { OnMenuExportFileList(event); //retry return; @@ -3407,9 +3454,9 @@ void MainDialog::OnMenuLanguageSwitch(wxCommandEvent& event) //######################################################################################################### MainDialog::SyncPreview::SyncPreview(MainDialog* mainDlg) : - mainDlg_(mainDlg), - syncPreviewEnabled(false), - synchronizationEnabled(false) {} + mainDlg_(mainDlg), + syncPreviewEnabled(false), + synchronizationEnabled(false) {} bool MainDialog::SyncPreview::previewIsEnabled() const diff --git a/ui/MainDialog.h b/ui/MainDialog.h index a4c1d897..30f018ad 100644 --- a/ui/MainDialog.h +++ b/ui/MainDialog.h @@ -28,8 +28,8 @@ class FolderPairPanel; namespace FreeFileSync { - class CustomLocale; - class GridView; +class CustomLocale; +class GridView; } diff --git a/ui/SmallDialogs.cpp b/ui/SmallDialogs.cpp index 39f805ba..e66be93d 100644 --- a/ui/SmallDialogs.cpp +++ b/ui/SmallDialogs.cpp @@ -1,6 +1,8 @@ #include "smallDialogs.h" #include "../library/resources.h" #include "../algorithm.h" +#include "../shared/stringConv.h" +#include "util.h" #include "../synchronization.h" #include <wx/msgdlg.h> #include "../library/customGrid.h" @@ -127,18 +129,18 @@ void HelpDlg::OnOK(wxCommandEvent& event) //######################################################################################## -FilterDlg::FilterDlg(wxWindow* window, wxString& filterIncl, wxString& filterExcl) : - FilterDlgGenerated(window), - includeFilter(filterIncl), - excludeFilter(filterExcl) +FilterDlg::FilterDlg(wxWindow* window, Zstring& filterIncl, Zstring& filterExcl) : + FilterDlgGenerated(window), + includeFilter(filterIncl), + excludeFilter(filterExcl) { m_bitmap8->SetBitmap(*GlobalResources::getInstance().bitmapInclude); m_bitmap9->SetBitmap(*GlobalResources::getInstance().bitmapExclude); m_bitmap26->SetBitmap(*GlobalResources::getInstance().bitmapFilter); m_bpButtonHelp->SetBitmapLabel(*GlobalResources::getInstance().bitmapHelp); - m_textCtrlInclude->SetValue(includeFilter); - m_textCtrlExclude->SetValue(excludeFilter); + m_textCtrlInclude->SetValue(zToWx(includeFilter)); + m_textCtrlExclude->SetValue(zToWx(excludeFilter)); m_panel13->Hide(); m_button10->SetFocus(); @@ -160,8 +162,8 @@ void FilterDlg::OnHelp(wxCommandEvent& event) void FilterDlg::OnDefault(wxCommandEvent& event) { - m_textCtrlInclude->SetValue(wxT("*")); - m_textCtrlExclude->SetValue(wxEmptyString); + m_textCtrlInclude->SetValue(zToWx(defaultIncludeFilter())); + m_textCtrlExclude->SetValue(zToWx(defaultExcludeFilter())); //changes to mainDialog are only committed when the OK button is pressed event.Skip(); @@ -171,8 +173,8 @@ void FilterDlg::OnDefault(wxCommandEvent& event) void FilterDlg::OnApply(wxCommandEvent& event) { //only if user presses ApplyFilter, he wants the changes to be committed - includeFilter = m_textCtrlInclude->GetValue(); - excludeFilter = m_textCtrlExclude->GetValue(); + includeFilter = wxToZ(m_textCtrlInclude->GetValue()); + excludeFilter = wxToZ(m_textCtrlExclude->GetValue()); //when leaving dialog: filter and redraw grid, if filter is active EndModal(BUTTON_APPLY); @@ -198,12 +200,12 @@ DeleteDialog::DeleteDialog(wxWindow* main, bool& deleteOnBothSides, bool& useRecycleBin, int& totalDeleteCount) : - DeleteDlgGenerated(main), - rowsToDeleteOnLeft(rowsOnLeft), - rowsToDeleteOnRight(rowsOnRight), - m_deleteOnBothSides(deleteOnBothSides), - m_useRecycleBin(useRecycleBin), - totalDelCount(totalDeleteCount) + DeleteDlgGenerated(main), + rowsToDeleteOnLeft(rowsOnLeft), + rowsToDeleteOnRight(rowsOnRight), + m_deleteOnBothSides(deleteOnBothSides), + m_useRecycleBin(useRecycleBin), + totalDelCount(totalDeleteCount) { m_checkBoxDeleteBothSides->SetValue(deleteOnBothSides); m_checkBoxUseRecycler->SetValue(useRecycleBin); @@ -279,8 +281,8 @@ void DeleteDialog::OnUseRecycler(wxCommandEvent& event) ErrorDlg::ErrorDlg(wxWindow* parentWindow, const int activeButtons, const wxString messageText, bool& ignoreNextErrors) : - ErrorDlgGenerated(parentWindow), - ignoreErrors(ignoreNextErrors) + ErrorDlgGenerated(parentWindow), + ignoreErrors(ignoreNextErrors) { m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapError); m_textCtrl8->SetValue(messageText); @@ -340,8 +342,8 @@ void ErrorDlg::OnAbort(wxCommandEvent& event) WarningDlg::WarningDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool& dontShowDlgAgain) : - WarningDlgGenerated(parentWindow), - dontShowAgain(dontShowDlgAgain) + WarningDlgGenerated(parentWindow), + dontShowAgain(dontShowDlgAgain) { m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapWarning); m_textCtrl8->SetValue(messageText); @@ -389,13 +391,16 @@ void WarningDlg::OnAbort(wxCommandEvent& event) //######################################################################################## -QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool& dontShowDlgAgain) : - QuestionDlgGenerated(parentWindow), - dontShowAgain(dontShowDlgAgain) +QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool* dontShowDlgAgain) : + QuestionDlgGenerated(parentWindow), + dontShowAgain(dontShowDlgAgain) { m_bitmap10->SetBitmap(*GlobalResources::getInstance().bitmapQuestion); m_textCtrl8->SetValue(messageText); - m_checkBoxDontAskAgain->SetValue(dontShowAgain); + if (dontShowAgain) + m_checkBoxDontAskAgain->SetValue(*dontShowAgain); + else + m_checkBoxDontAskAgain->Hide(); if (~activeButtons & BUTTON_YES) m_buttonYes->Hide(); @@ -421,27 +426,31 @@ QuestionDlg::QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxStri void QuestionDlg::OnClose(wxCloseEvent& event) { - dontShowAgain = m_checkBoxDontAskAgain->GetValue(); + if (dontShowAgain) + *dontShowAgain = m_checkBoxDontAskAgain->GetValue(); EndModal(BUTTON_CANCEL); } void QuestionDlg::OnCancel(wxCommandEvent& event) { - dontShowAgain = m_checkBoxDontAskAgain->GetValue(); + if (dontShowAgain) + *dontShowAgain = m_checkBoxDontAskAgain->GetValue(); EndModal(BUTTON_CANCEL); } void QuestionDlg::OnYes(wxCommandEvent& event) { - dontShowAgain = m_checkBoxDontAskAgain->GetValue(); + if (dontShowAgain) + *dontShowAgain = m_checkBoxDontAskAgain->GetValue(); EndModal(BUTTON_YES); } void QuestionDlg::OnNo(wxCommandEvent& event) { - dontShowAgain = m_checkBoxDontAskAgain->GetValue(); + if (dontShowAgain) + *dontShowAgain = m_checkBoxDontAskAgain->GetValue(); EndModal(BUTTON_NO); } @@ -449,9 +458,9 @@ void QuestionDlg::OnNo(wxCommandEvent& event) CustomizeColsDlg::CustomizeColsDlg(wxWindow* window, xmlAccess::ColumnAttributes& attr, bool& showFileIcons) : - CustomizeColsDlgGenerated(window), - output(attr), - m_showFileIcons(showFileIcons) + CustomizeColsDlgGenerated(window), + output(attr), + m_showFileIcons(showFileIcons) { m_bpButton29->SetBitmapLabel(*GlobalResources::getInstance().bitmapMoveUp); m_bpButton30->SetBitmapLabel(*GlobalResources::getInstance().bitmapMoveDown); @@ -566,8 +575,8 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parentWindow, const wxString& variantName, const FreeFileSync::SyncStatistics& statistics, bool& dontShowAgain) : - SyncPreviewDlgGenerated(parentWindow), - m_dontShowAgain(dontShowAgain) + SyncPreviewDlgGenerated(parentWindow), + m_dontShowAgain(dontShowAgain) { using FreeFileSync::includeNumberSeparator; using globalFunctions::numberToWxString; @@ -619,8 +628,8 @@ void SyncPreviewDlg::OnStartSync(wxCommandEvent& event) //######################################################################################## CompareCfgDialog::CompareCfgDialog(wxWindow* parentWindow, const wxPoint& position, CompareVariant& cmpVar) : - CmpCfgDlgGenerated(parentWindow), - m_cmpVar(cmpVar) + CmpCfgDlgGenerated(parentWindow), + m_cmpVar(cmpVar) { //move dialog up so that compare-config button and first config-variant are on same level Move(wxPoint(position.x, std::max(0, position.y - (m_buttonTimeSize->GetScreenPosition() - GetScreenPosition()).y))); @@ -676,8 +685,8 @@ void CompareCfgDialog::OnShowHelp(wxCommandEvent& event) //######################################################################################## GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings& globalSettings) : - GlobalSettingsDlgGenerated(window), - settings(globalSettings) + GlobalSettingsDlgGenerated(window), + settings(globalSettings) { m_bitmapSettings->SetBitmap(*GlobalResources::getInstance().bitmapSettings); m_buttonResetDialogs->setBitmapFront(*GlobalResources::getInstance().bitmapWarningSmall, 5); @@ -716,8 +725,11 @@ void GlobalSettingsDlg::OnOkay(wxCommandEvent& event) void GlobalSettingsDlg::OnResetDialogs(wxCommandEvent& event) { - wxMessageDialog* messageDlg = new wxMessageDialog(this, _("Re-enable all hidden dialogs?"), _("Warning") , wxOK | wxCANCEL); - if (messageDlg->ShowModal() == wxID_OK) + QuestionDlg* messageDlg = new QuestionDlg(this, + QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL, + _("Re-enable all hidden dialogs?")); + + if (messageDlg->ShowModal() == QuestionDlg::BUTTON_YES) settings.optDialogs.resetDialogs(); } @@ -776,7 +788,12 @@ void GlobalSettingsDlg::OnAddRow(wxCommandEvent& event) { wxWindowUpdateLocker dummy(this); //avoid display distortion - m_gridCustomCommand->AppendRows(); + const int selectedRow = m_gridCustomCommand->GetGridCursorRow(); + if (0 <= selectedRow && selectedRow < m_gridCustomCommand->GetNumberRows()) + m_gridCustomCommand->InsertRows(selectedRow); + else + m_gridCustomCommand->AppendRows(); + Fit(); } @@ -787,7 +804,12 @@ void GlobalSettingsDlg::OnRemoveRow(wxCommandEvent& event) { wxWindowUpdateLocker dummy(this); //avoid display distortion - m_gridCustomCommand->DeleteRows(m_gridCustomCommand->GetNumberRows() - 1); + const int selectedRow = m_gridCustomCommand->GetGridCursorRow(); + if (0 <= selectedRow && selectedRow < m_gridCustomCommand->GetNumberRows()) + m_gridCustomCommand->DeleteRows(selectedRow); + else + m_gridCustomCommand->DeleteRows(m_gridCustomCommand->GetNumberRows() - 1); + Fit(); } } @@ -795,16 +817,16 @@ void GlobalSettingsDlg::OnRemoveRow(wxCommandEvent& event) //######################################################################################## CompareStatus::CompareStatus(wxWindow* parentWindow) : - CompareStatusGenerated(parentWindow), - scannedObjects(0), - totalObjects(0), - totalData(0), - currentObjects(0), - currentData(0), - scalingFactor(0), - statistics(NULL), - lastStatCallSpeed(-1000000), //some big number - lastStatCallRemTime(-1000000) + CompareStatusGenerated(parentWindow), + scannedObjects(0), + totalObjects(0), + totalData(0), + currentObjects(0), + currentData(0), + scalingFactor(0), + statistics(NULL), + lastStatCallSpeed(-1000000), //some big number + lastStatCallRemTime(-1000000) { init(); } @@ -892,7 +914,7 @@ void CompareStatus::updateStatusPanelNow() bool screenChanged = false; //avoid screen flicker by calling layout() only if necessary //remove linebreaks from currentStatusText - wxString formattedStatusText = currentStatusText.c_str(); + wxString formattedStatusText = zToWx(currentStatusText); for (wxString::iterator i = formattedStatusText.begin(); i != formattedStatusText.end(); ++i) if (*i == wxChar('\n')) *i = wxChar(' '); @@ -960,20 +982,20 @@ void CompareStatus::updateStatusPanelNow() //######################################################################################## SyncStatus::SyncStatus(StatusHandler* updater, wxWindow* parentWindow) : - SyncStatusDlgGenerated(parentWindow), - currentStatusHandler(updater), - windowToDis(parentWindow), - currentProcessIsRunning(true), - totalObjects(0), - totalData(0), - currentObjects(0), - currentData(0), - scalingFactor(0), - processPaused(false), - currentStatus(SyncStatus::ABORTED), - statistics(NULL), - lastStatCallSpeed(-1000000), //some big number - lastStatCallRemTime(-1000000) + SyncStatusDlgGenerated(parentWindow), + currentStatusHandler(updater), + windowToDis(parentWindow), + currentProcessIsRunning(true), + totalObjects(0), + totalData(0), + currentObjects(0), + currentData(0), + scalingFactor(0), + processPaused(false), + currentStatus(SyncStatus::ABORTED), + statistics(NULL), + lastStatCallSpeed(-1000000), //some big number + lastStatCallRemTime(-1000000) { m_animationControl1->SetAnimation(*GlobalResources::getInstance().animationSync); m_animationControl1->Play(); @@ -1050,8 +1072,9 @@ void SyncStatus::updateStatusDialogNow() m_gauge1->SetValue(globalFunctions::round(currentData.ToDouble() * scalingFactor)); //status text - if (m_textCtrlInfo->GetValue() != wxString(currentStatusText.c_str()) && (screenChanged = true)) //avoid screen flicker - m_textCtrlInfo->SetValue(currentStatusText.c_str()); + const wxString statusTxt = zToWx(currentStatusText); + if (m_textCtrlInfo->GetValue() != statusTxt && (screenChanged = true)) //avoid screen flicker + m_textCtrlInfo->SetValue(statusTxt); //remaining objects const wxString remainingObjTmp = globalFunctions::numberToWxString(totalObjects - currentObjects); @@ -1157,8 +1180,9 @@ void SyncStatus::setCurrentStatus(SyncStatusID id) } -void SyncStatus::processHasFinished(SyncStatusID id) //essential to call this in StatusHandler derived class destructor -{ //at the LATEST(!) to prevent access to currentStatusHandler +void SyncStatus::processHasFinished(SyncStatusID id, const wxString& finalMessage) //essential to call this in StatusHandler derived class destructor +{ + //at the LATEST(!) to prevent access to currentStatusHandler currentProcessIsRunning = false; //enable okay and close events; may be set in this method ONLY setCurrentStatus(id); @@ -1177,6 +1201,7 @@ void SyncStatus::processHasFinished(SyncStatusID id) //essential to call this in bSizerRemTime->Show(false); updateStatusDialogNow(); //keep this sequence to avoid display distortion, if e.g. only 1 item is sync'ed + m_textCtrlInfo->SetValue(finalMessage); Layout(); // } @@ -1230,7 +1255,7 @@ void SyncStatus::OnAbort(wxCommandEvent& event) m_buttonPause->Disable(); m_buttonPause->Hide(); - setStatusText_NoUpdate(_("Abort requested: Waiting for current operation to finish...")); + setStatusText_NoUpdate(wxToZ(_("Abort requested: Waiting for current operation to finish..."))); //no Layout() or UI-update here to avoid cascaded Yield()-call currentStatusHandler->requestAbortion(); diff --git a/ui/SmallDialogs.h b/ui/SmallDialogs.h index 6e9d0414..3a07167a 100644 --- a/ui/SmallDialogs.h +++ b/ui/SmallDialogs.h @@ -12,7 +12,7 @@ class StatusHandler; namespace FreeFileSync { - class SyncStatistics; +class SyncStatistics; } @@ -43,7 +43,7 @@ private: class FilterDlg : public FilterDlgGenerated { public: - FilterDlg(wxWindow* window, wxString& filterIncl, wxString& filterExcl); + FilterDlg(wxWindow* window, Zstring& filterIncl, Zstring& filterExcl); ~FilterDlg() {} enum @@ -58,8 +58,8 @@ private: void OnCancel(wxCommandEvent& event); void OnClose(wxCloseEvent& event); - wxString& includeFilter; - wxString& excludeFilter; + Zstring& includeFilter; + Zstring& excludeFilter; }; @@ -147,7 +147,7 @@ private: class QuestionDlg : public QuestionDlgGenerated { public: - QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool& dontShowAgain); + QuestionDlg(wxWindow* parentWindow, int activeButtons, const wxString messageText, bool* dontShowAgain = NULL); enum { @@ -162,7 +162,7 @@ private: void OnYes(wxCommandEvent& event); void OnNo(wxCommandEvent& event); - bool& dontShowAgain; + bool* dontShowAgain; //optional }; @@ -318,7 +318,7 @@ public: void updateStatusDialogNow(); void setCurrentStatus(SyncStatusID id); - void processHasFinished(SyncStatusID id); //essential to call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater + void processHasFinished(SyncStatusID id, const wxString& finalMessage); //essential to call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater private: void OnOkay(wxCommandEvent& event); diff --git a/ui/appMain.h b/ui/appMain.h new file mode 100644 index 00000000..2922d093 --- /dev/null +++ b/ui/appMain.h @@ -0,0 +1,20 @@ +#ifndef APPMAIN_H_INCLUDED +#define APPMAIN_H_INCLUDED + +#include <wx/app.h> + +namespace FreeFileSync +{ +class AppMainWindow +{ +public: + static void setMainWindow(wxWindow* window); + static bool mainWindowActive(); + +private: + static bool mainWndAct; +}; +} + + +#endif // APPMAIN_H_INCLUDED diff --git a/ui/batchStatusHandler.cpp b/ui/batchStatusHandler.cpp index 4abc49eb..76fe4a75 100644 --- a/ui/batchStatusHandler.cpp +++ b/ui/batchStatusHandler.cpp @@ -7,8 +7,12 @@ #include "../shared/systemConstants.h" #include "../shared/standardPaths.h" #include "../shared/fileHandling.h" +#include "../shared/stringConv.h" #include "../library/resources.h" #include "../shared/globalFunctions.h" +#include "../shared/appMain.h" + +using namespace FreeFileSync; class LogFile @@ -18,10 +22,10 @@ public: { //create logfile directory const wxString logfileDir = logfileDirectory.empty() ? FreeFileSync::getDefaultLogDirectory() : logfileDirectory; - if (!FreeFileSync::dirExists(logfileDir)) + if (!FreeFileSync::dirExists(wxToZ(logfileDir))) try { - FreeFileSync::createDirectory(logfileDir.c_str()); //create recursively if necessary + FreeFileSync::createDirectory(wxToZ(logfileDir)); //create recursively if necessary } catch (FreeFileSync::FileError&) { @@ -121,12 +125,12 @@ class FfsTrayIcon : public wxTaskBarIcon { public: FfsTrayIcon(StatusHandler* statusHandler) : - m_statusHandler(statusHandler), - processPaused(false), - percentage(_("%x Percent")), - currentProcess(StatusHandler::PROCESS_NONE), - totalObjects(0), - currentObjects(0) + m_statusHandler(statusHandler), + processPaused(false), + percentage(_("%x Percent")), + currentProcess(StatusHandler::PROCESS_NONE), + totalObjects(0), + currentObjects(0) { running.reset(new wxIcon(*GlobalResources::getInstance().programIcon)); paused.reset(new wxIcon); @@ -260,17 +264,16 @@ private: //############################################################################################################################## BatchStatusHandlerSilent::BatchStatusHandlerSilent(const xmlAccess::OnError handleError, const wxString& logfileDirectory, int& returnVal) : - m_handleError(xmlAccess::ON_ERROR_POPUP), - currentProcess(StatusHandler::PROCESS_NONE), - returnValue(returnVal), - trayIcon(new FfsTrayIcon(this)), - m_log(new LogFile(logfileDirectory)) + m_handleError(handleError), + currentProcess(StatusHandler::PROCESS_NONE), + returnValue(returnVal), + trayIcon(new FfsTrayIcon(this)), + m_log(new LogFile(logfileDirectory)) { - setErrorStrategy(handleError); - //test if log was instantiated successfully if (!m_log->isOkay()) - { //handle error: file load + { + //handle error: file load wxMessageBox(_("Unable to create logfile!"), _("Error"), wxOK | wxICON_ERROR); returnValue = -7; throw FreeFileSync::AbortThisProcess(); @@ -305,7 +308,7 @@ void BatchStatusHandlerSilent::updateStatusText(const Zstring& text) case StatusHandler::PROCESS_COMPARING_CONTENT: break; case StatusHandler::PROCESS_SYNCHRONIZING: - m_log->logInfo(text.c_str()); + m_log->logInfo(zToWx(text)); break; case StatusHandler::PROCESS_NONE: assert(false); @@ -449,12 +452,6 @@ void BatchStatusHandlerSilent::addFinalInfo(const wxString& infoMessage) } -void BatchStatusHandlerSilent::setErrorStrategy(xmlAccess::OnError handleError) -{ - m_handleError = handleError; -} - - void BatchStatusHandlerSilent::forceUiRefresh() { trayIcon->updateSysTray(); //needed by sys-tray icon only @@ -471,14 +468,31 @@ void BatchStatusHandlerSilent::abortThisProcess() //used by sys-tray menu BatchStatusHandlerGui::BatchStatusHandlerGui(const xmlAccess::OnError handleError, int& returnVal) : - showPopups(true), - currentProcess(StatusHandler::PROCESS_NONE), - returnValue(returnVal) + showPopups(true), + currentProcess(StatusHandler::PROCESS_NONE), + returnValue(returnVal) { - setErrorStrategy(handleError); + switch (handleError) + { + case xmlAccess::ON_ERROR_POPUP: + showPopups = true; + break; + + case xmlAccess::ON_ERROR_EXIT: //doesn't make much sense for "batch gui"-mode + showPopups = true; + break; + + case xmlAccess::ON_ERROR_IGNORE: + showPopups = false; + break; + } + syncStatusFrame = new SyncStatus(this, NULL); syncStatusFrame->Show(); + + //notify about (logical) application main window + FreeFileSync::AppMainWindow::setMainWindow(syncStatusFrame); } @@ -513,21 +527,18 @@ BatchStatusHandlerGui::~BatchStatusHandlerGui() { returnValue = -4; finalMessage += _("Synchronization aborted!"); - syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::ABORTED); //enable okay and close events + syncStatusFrame->processHasFinished(SyncStatus::ABORTED, finalMessage); //enable okay and close events } else if (errorLog.errorsTotal()) { returnValue = -5; finalMessage += _("Synchronization completed with errors!"); - syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR, finalMessage); } else { finalMessage += _("Synchronization completed successfully!"); - syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS, finalMessage); } } @@ -679,22 +690,3 @@ void BatchStatusHandlerGui::addFinalInfo(const wxString& infoMessage) { finalInfo = infoMessage; } - - -void BatchStatusHandlerGui::setErrorStrategy(xmlAccess::OnError handleError) //change error handling during process -{ - switch (handleError) - { - case xmlAccess::ON_ERROR_POPUP: - showPopups = true; - break; - - case xmlAccess::ON_ERROR_EXIT: //doesn't make much sense for "batch gui"-mode - showPopups = true; - break; - - case xmlAccess::ON_ERROR_IGNORE: - showPopups = false; - break; - } -} diff --git a/ui/batchStatusHandler.h b/ui/batchStatusHandler.h index 811ab63c..a075d7d7 100644 --- a/ui/batchStatusHandler.h +++ b/ui/batchStatusHandler.h @@ -15,7 +15,6 @@ class BatchStatusHandler : public StatusHandler { public: virtual void addFinalInfo(const wxString& infoMessage) = 0; -virtual void setErrorStrategy(xmlAccess::OnError handleError) = 0; //change error handling during process }; @@ -36,8 +35,6 @@ public: virtual void reportWarning(const wxString& warningMessage, bool& warningActive); virtual void addFinalInfo(const wxString& infoMessage); -virtual void setErrorStrategy(xmlAccess::OnError handleError); //change error handling during process - private: virtual void abortThisProcess(); @@ -67,8 +64,6 @@ public: virtual void reportWarning(const wxString& warningMessage, bool& warningActive); virtual void addFinalInfo(const wxString& infoMessage); -virtual void setErrorStrategy(xmlAccess::OnError handleError); //change error handling during process - private: virtual void abortThisProcess(); diff --git a/ui/checkVersion.cpp b/ui/checkVersion.cpp index 41677094..2fb57ec6 100644 --- a/ui/checkVersion.cpp +++ b/ui/checkVersion.cpp @@ -13,8 +13,8 @@ class CloseConnectionOnExit { public: CloseConnectionOnExit(wxInputStream* httpStream, wxHTTP& webAccess) : - m_httpStream(httpStream), - m_webAccess(webAccess) {} + m_httpStream(httpStream), + m_webAccess(webAccess) {} ~CloseConnectionOnExit() { diff --git a/ui/checkVersion.h b/ui/checkVersion.h index e59235f4..b7f7f2ee 100644 --- a/ui/checkVersion.h +++ b/ui/checkVersion.h @@ -4,9 +4,9 @@ namespace FreeFileSync { - void checkForUpdateNow(); +void checkForUpdateNow(); - void checkForUpdatePeriodically(long& lastUpdateCheck); +void checkForUpdatePeriodically(long& lastUpdateCheck); } #endif // UPDATEVERSION_H_INCLUDED diff --git a/ui/folderPair.h b/ui/folderPair.h index f2b57ea7..91eb556d 100644 --- a/ui/folderPair.h +++ b/ui/folderPair.h @@ -5,142 +5,143 @@ #include "../shared/dragAndDrop.h" #include "../library/resources.h" #include "smallDialogs.h" -#include "syncDialog.h" +#include "settingsDialog.h" namespace FreeFileSync { - //basic functionality for changing alternate folder pair configuration: adaptable to generated gui class +//basic functionality for changing alternate folder pair configuration: adaptable to generated gui class - template <class GuiPanel> - class FolderPairPanelBasic : public GuiPanel +template <class GuiPanel> +class FolderPairPanelBasic : public GuiPanel +{ + using GuiPanel::m_bpButtonAltSyncCfg; + using GuiPanel::m_bpButtonAltFilter; + +public: + FolderPairPanelBasic(wxWindow* parent) : + GuiPanel(parent), + dragDropOnLeft(new DragDropOnDlg( GuiPanel::m_panelLeft, GuiPanel::m_dirPickerLeft, GuiPanel::m_directoryLeft)), + dragDropOnRight(new DragDropOnDlg(GuiPanel::m_panelRight, GuiPanel::m_dirPickerRight, GuiPanel::m_directoryRight)) { - using GuiPanel::m_bpButtonAltSyncCfg; - using GuiPanel::m_bpButtonAltFilter; - - public: - FolderPairPanelBasic(wxWindow* parent) : - GuiPanel(parent), - dragDropOnLeft(new DragDropOnDlg(GuiPanel::m_panelLeft, GuiPanel::m_dirPickerLeft, GuiPanel::m_directoryLeft)), - dragDropOnRight(new DragDropOnDlg(GuiPanel::m_panelRight, GuiPanel::m_dirPickerRight, GuiPanel::m_directoryRight)) - { - //register events for removal of alternate configuration - m_bpButtonAltFilter->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfgRemove), NULL, this); - m_bpButtonAltSyncCfg->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemove), NULL, this); + //register events for removal of alternate configuration + m_bpButtonAltFilter->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfgRemove), NULL, this); + m_bpButtonAltSyncCfg->Connect(wxEVT_RIGHT_DOWN, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemove), NULL, this); - m_bpButtonAltSyncCfg->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfg), NULL, this); - m_bpButtonAltFilter-> Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfg), NULL, this); + m_bpButtonAltSyncCfg->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfg), NULL, this); + m_bpButtonAltFilter-> Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfg), NULL, this); - GuiPanel::m_bpButtonRemovePair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair); - } + GuiPanel::m_bpButtonRemovePair->SetBitmapLabel(*GlobalResources::getInstance().bitmapRemoveFolderPair); + } - //alternate configuration attached to it - boost::shared_ptr<const FreeFileSync::AlternateSyncConfig> altSyncConfig; //optional - boost::shared_ptr<const FreeFileSync::AlternateFilter> altFilter; //optional + //alternate configuration attached to it + boost::shared_ptr<const FreeFileSync::AlternateSyncConfig> altSyncConfig; //optional + boost::shared_ptr<const FreeFileSync::AlternateFilter> altFilter; //optional - void updateAltButtonColor() - { - if (altSyncConfig.get()) - m_bpButtonAltSyncCfg->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCfgSmall); - else - m_bpButtonAltSyncCfg->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCfgSmallGrey); + void updateAltButtonColor() + { + if (altSyncConfig.get()) + m_bpButtonAltSyncCfg->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCfgSmall); + else + m_bpButtonAltSyncCfg->SetBitmapLabel(*GlobalResources::getInstance().bitmapSyncCfgSmallGrey); + + if (altFilter.get()) + m_bpButtonAltFilter->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterSmall); + else + m_bpButtonAltFilter->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterSmallGrey); + } + +protected: + virtual void OnAltFilterCfgRemoveConfirm(wxCommandEvent& event) + { + altFilter.reset(); + updateAltButtonColor(); + } - if (altFilter.get()) - m_bpButtonAltFilter->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterSmall); - else - m_bpButtonAltFilter->SetBitmapLabel(*GlobalResources::getInstance().bitmapFilterSmallGrey); - } + virtual void OnAltSyncCfgRemoveConfirm(wxCommandEvent& event) + { + altSyncConfig.reset(); + updateAltButtonColor(); + } - protected: - virtual void OnAltFilterCfgRemoveConfirm(wxCommandEvent& event) - { - altFilter.reset(); - updateAltButtonColor(); - } - virtual void OnAltSyncCfgRemoveConfirm(wxCommandEvent& event) - { - altSyncConfig.reset(); - updateAltButtonColor(); - } +private: + void OnAltFilterCfgRemove(wxCommandEvent& event) + { + contextMenu.reset(new wxMenu); //re-create context menu + contextMenu->Append(wxID_ANY, _("Remove alternate settings")); + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfgRemoveConfirm), NULL, this); + GuiPanel::PopupMenu(contextMenu.get()); //show context menu + } + void OnAltSyncCfgRemove(wxCommandEvent& event) + { + contextMenu.reset(new wxMenu); //re-create context menu + contextMenu->Append(wxID_ANY, _("Remove alternate settings")); + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); + GuiPanel::PopupMenu(contextMenu.get()); //show context menu + } - private: - void OnAltFilterCfgRemove(wxCommandEvent& event) - { - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(wxID_ANY, _("Remove alternate settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltFilterCfgRemoveConfirm), NULL, this); - GuiPanel::PopupMenu(contextMenu.get()); //show context menu - } + virtual MainConfiguration getMainConfig() const = 0; + virtual wxWindow* getParentWindow() = 0; - void OnAltSyncCfgRemove(wxCommandEvent& event) + virtual void OnAltSyncCfgChange() {}; + + void OnAltSyncCfg(wxCommandEvent& event) + { + const MainConfiguration& mainCfg = getMainConfig(); + + AlternateSyncConfig altSyncCfg = altSyncConfig.get() ? + *altSyncConfig : + AlternateSyncConfig(mainCfg.syncConfiguration, + mainCfg.handleDeletion, + mainCfg.customDeletionDirectory); + SyncCfgDialog* syncDlg = new SyncCfgDialog(getParentWindow(), + mainCfg.compareVar, + altSyncCfg.syncConfiguration, + altSyncCfg.handleDeletion, + altSyncCfg.customDeletionDirectory, + NULL); + if (syncDlg->ShowModal() == SyncCfgDialog::BUTTON_APPLY) { - contextMenu.reset(new wxMenu); //re-create context menu - contextMenu->Append(wxID_ANY, _("Remove alternate settings")); - contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(FolderPairPanelBasic::OnAltSyncCfgRemoveConfirm), NULL, this); - GuiPanel::PopupMenu(contextMenu.get()); //show context menu - } + altSyncConfig.reset(new AlternateSyncConfig(altSyncCfg)); + updateAltButtonColor(); - virtual MainConfiguration getMainConfig() const = 0; - virtual wxWindow* getParentWindow() = 0; + OnAltSyncCfgChange(); + } + } - virtual void OnAltSyncCfgChange() {}; + virtual void OnAltFilterCfgChange(bool defaultValueSet) {}; - void OnAltSyncCfg(wxCommandEvent& event) - { - const MainConfiguration& mainCfg = getMainConfig(); - - AlternateSyncConfig altSyncCfg = altSyncConfig.get() ? - *altSyncConfig : - AlternateSyncConfig(mainCfg.syncConfiguration, - mainCfg.handleDeletion, - mainCfg.customDeletionDirectory); - SyncCfgDialog* syncDlg = new SyncCfgDialog(getParentWindow(), - mainCfg.compareVar, - altSyncCfg.syncConfiguration, - altSyncCfg.handleDeletion, - altSyncCfg.customDeletionDirectory, - NULL); - if (syncDlg->ShowModal() == SyncCfgDialog::BUTTON_APPLY) - { - altSyncConfig.reset(new AlternateSyncConfig(altSyncCfg)); - updateAltButtonColor(); - - OnAltSyncCfgChange(); - } - } + void OnAltFilterCfg(wxCommandEvent& event) + { + const MainConfiguration& mainCfg = getMainConfig(); - virtual void OnAltFilterCfgChange(bool defaultValueSet) {}; + AlternateFilter altFilt = altFilter.get() ? + *altFilter : + AlternateFilter(mainCfg.includeFilter, mainCfg.excludeFilter); - void OnAltFilterCfg(wxCommandEvent& event) + FilterDlg* filterDlg = new FilterDlg(getParentWindow(), altFilt.includeFilter, altFilt.excludeFilter); + if (filterDlg->ShowModal() == FilterDlg::BUTTON_APPLY) { - const MainConfiguration& mainCfg = getMainConfig(); - - AlternateFilter altFilt = altFilter.get() ? - *altFilter : - AlternateFilter(mainCfg.includeFilter, mainCfg.excludeFilter); - - FilterDlg* filterDlg = new FilterDlg(getParentWindow(), altFilt.includeFilter, altFilt.excludeFilter); - if (filterDlg->ShowModal() == FilterDlg::BUTTON_APPLY) - { - altFilter.reset(new AlternateFilter(altFilt)); - updateAltButtonColor(); - - if (altFilt.includeFilter == wxT("*") && altFilt.excludeFilter.empty()) //default - OnAltFilterCfgChange(true); - else - OnAltFilterCfgChange(false); - } + altFilter.reset(new AlternateFilter(altFilt)); + updateAltButtonColor(); + + if ( altFilt.includeFilter == defaultIncludeFilter() && + altFilt.excludeFilter == defaultExcludeFilter()) //default + OnAltFilterCfgChange(true); + else + OnAltFilterCfgChange(false); } + } - std::auto_ptr<wxMenu> contextMenu; + std::auto_ptr<wxMenu> contextMenu; - //support for drag and drop - std::auto_ptr<DragDropOnDlg> dragDropOnLeft; - std::auto_ptr<DragDropOnDlg> dragDropOnRight; - }; + //support for drag and drop + std::auto_ptr<DragDropOnDlg> dragDropOnLeft; + std::auto_ptr<DragDropOnDlg> dragDropOnRight; +}; } diff --git a/ui/gridView.cpp b/ui/gridView.cpp index 9d9e9a1c..8a3929fb 100644 --- a/ui/gridView.cpp +++ b/ui/gridView.cpp @@ -7,18 +7,18 @@ using namespace FreeFileSync; GridView::StatusCmpResult::StatusCmpResult() : - existsLeftOnly(false), - existsRightOnly(false), - existsLeftNewer(false), - existsRightNewer(false), - existsDifferent(false), - existsEqual(false), - existsConflict(false), + existsLeftOnly(false), + existsRightOnly(false), + existsLeftNewer(false), + existsRightNewer(false), + existsDifferent(false), + existsEqual(false), + existsConflict(false), - filesOnLeftView(0), - foldersOnLeftView(0), - filesOnRightView(0), - foldersOnRightView(0) {} + filesOnLeftView(0), + foldersOnLeftView(0), + filesOnRightView(0), + foldersOnRightView(0) {} GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps sortedRef to viewRef @@ -40,7 +40,7 @@ GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps so if (fsObj) { //hide filtered row, if corresponding option is set - if (hideFiltered && !fsObj->selectedForSynchronization) + if (hideFiltered && !fsObj->isActive()) continue; switch (fsObj->getCategory()) @@ -112,19 +112,19 @@ GridView::StatusCmpResult GridView::updateCmpResult(bool hideFiltered, //maps so GridView::StatusSyncPreview::StatusSyncPreview() : - existsSyncCreateLeft(false), - existsSyncCreateRight(false), - existsSyncDeleteLeft(false), - existsSyncDeleteRight(false), - existsSyncDirLeft(false), - existsSyncDirRight(false), - existsSyncDirNone(false), - existsConflict(false), + existsSyncCreateLeft(false), + existsSyncCreateRight(false), + existsSyncDeleteLeft(false), + existsSyncDeleteRight(false), + existsSyncDirLeft(false), + existsSyncDirRight(false), + existsSyncDirNone(false), + existsConflict(false), - filesOnLeftView(0), - foldersOnLeftView(0), - filesOnRightView(0), - foldersOnRightView(0) {} + filesOnLeftView(0), + foldersOnLeftView(0), + filesOnRightView(0), + foldersOnRightView(0) {} GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //maps sortedRef to viewRef @@ -154,11 +154,11 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map continue; //hide filtered row, if corresponding option is set - if (hideFiltered && !fsObj->selectedForSynchronization) + if (hideFiltered && !fsObj->isActive()) continue; - switch (FreeFileSync::getSyncOperation(*fsObj)) //evaluate comparison result and sync direction + switch (fsObj->getSyncOperation()) //evaluate comparison result and sync direction { case SO_CREATE_NEW_LEFT: output.existsSyncCreateLeft = true; @@ -274,8 +274,8 @@ class GridView::SerializeHierarchy { public: SerializeHierarchy(std::vector<GridView::RefIndex>& sortedRef, unsigned int index) : - index_(index), - sortedRef_(sortedRef) {} + index_(index), + sortedRef_(sortedRef) {} void execute(const HierarchyObject& hierObj) { diff --git a/ui/gridView.h b/ui/gridView.h index c7728b06..de9b1caa 100644 --- a/ui/gridView.h +++ b/ui/gridView.h @@ -6,155 +6,155 @@ namespace FreeFileSync { - //gui view of FolderComparison - class GridView +//gui view of FolderComparison +class GridView +{ +public: + //direct data access via row number + const FileSystemObject* getObject(unsigned int row) const; //returns NULL if object is not found; logarithmic complexity + FileSystemObject* getObject(unsigned int row); // + unsigned int rowsOnView() const; //only the currently visible elements + unsigned int rowsTotal() const; //total number of rows available + + //get references to FileSystemObject: no NULL-check needed! Everything's bound. + void getAllFileRef(const std::set<unsigned int>& guiRows, std::vector<FileSystemObject*>& output); + + struct StatusCmpResult { - public: - //direct data access via row number - const FileSystemObject* getObject(unsigned int row) const; //returns NULL if object is not found; logarithmic complexity - FileSystemObject* getObject(unsigned int row); // - unsigned int rowsOnView() const; //only the currently visible elements - unsigned int rowsTotal() const; //total number of rows available - - //get references to FileSystemObject: no NULL-check needed! Everything's bound. - void getAllFileRef(const std::set<unsigned int>& guiRows, std::vector<FileSystemObject*>& output); - - struct StatusCmpResult - { - StatusCmpResult(); - - bool existsLeftOnly; - bool existsRightOnly; - bool existsLeftNewer; - bool existsRightNewer; - bool existsDifferent; - bool existsEqual; - bool existsConflict; - - unsigned int filesOnLeftView; - unsigned int foldersOnLeftView; - unsigned int filesOnRightView; - unsigned int foldersOnRightView; - - wxULongLong filesizeLeftView; - wxULongLong filesizeRightView; - }; - - //comparison results view - StatusCmpResult updateCmpResult(bool hideFiltered, - bool leftOnlyFilesActive, - bool rightOnlyFilesActive, - bool leftNewerFilesActive, - bool rightNewerFilesActive, - bool differentFilesActive, - bool equalFilesActive, + StatusCmpResult(); + + bool existsLeftOnly; + bool existsRightOnly; + bool existsLeftNewer; + bool existsRightNewer; + bool existsDifferent; + bool existsEqual; + bool existsConflict; + + unsigned int filesOnLeftView; + unsigned int foldersOnLeftView; + unsigned int filesOnRightView; + unsigned int foldersOnRightView; + + wxULongLong filesizeLeftView; + wxULongLong filesizeRightView; + }; + + //comparison results view + StatusCmpResult updateCmpResult(bool hideFiltered, + bool leftOnlyFilesActive, + bool rightOnlyFilesActive, + bool leftNewerFilesActive, + bool rightNewerFilesActive, + bool differentFilesActive, + bool equalFilesActive, + bool conflictFilesActive); + + struct StatusSyncPreview + { + StatusSyncPreview(); + + bool existsSyncCreateLeft; + bool existsSyncCreateRight; + bool existsSyncDeleteLeft; + bool existsSyncDeleteRight; + bool existsSyncDirLeft; + bool existsSyncDirRight; + bool existsSyncDirNone; + bool existsConflict; + + unsigned int filesOnLeftView; + unsigned int foldersOnLeftView; + unsigned int filesOnRightView; + unsigned int foldersOnRightView; + + wxULongLong filesizeLeftView; + wxULongLong filesizeRightView; + }; + + //synchronization preview + StatusSyncPreview updateSyncPreview(bool hideFiltered, + bool syncCreateLeftActive, + bool syncCreateRightActive, + bool syncDeleteLeftActive, + bool syncDeleteRightActive, + bool syncDirOverwLeftActive, + bool syncDirOverwRightActive, + bool syncDirNoneActive, bool conflictFilesActive); - struct StatusSyncPreview - { - StatusSyncPreview(); - - bool existsSyncCreateLeft; - bool existsSyncCreateRight; - bool existsSyncDeleteLeft; - bool existsSyncDeleteRight; - bool existsSyncDirLeft; - bool existsSyncDirRight; - bool existsSyncDirNone; - bool existsConflict; - - unsigned int filesOnLeftView; - unsigned int foldersOnLeftView; - unsigned int filesOnRightView; - unsigned int foldersOnRightView; - - wxULongLong filesizeLeftView; - wxULongLong filesizeRightView; - }; - - //synchronization preview - StatusSyncPreview updateSyncPreview(bool hideFiltered, - bool syncCreateLeftActive, - bool syncCreateRightActive, - bool syncDeleteLeftActive, - bool syncDeleteRightActive, - bool syncDirOverwLeftActive, - bool syncDirOverwRightActive, - bool syncDirNoneActive, - bool conflictFilesActive); - - - - FolderComparison& getDataTentative(); //get data for operation that does NOT add or reorder rows! (deletion is okay) - void setData(FolderComparison& newData); //set data, taking ownership: warning std::swap() is used!!! - void removeInvalidRows(); //remove rows that have been deleted meanwhile: call after manual deletion and synchronization! - void clearAllRows(); //clears everything - - //sorting... - enum SortType - { - SORT_BY_REL_NAME, - SORT_BY_FILENAME, - SORT_BY_FILESIZE, - SORT_BY_DATE, - SORT_BY_CMP_RESULT, - SORT_BY_DIRECTORY, - SORT_BY_SYNC_DIRECTION - }; - - void sortView(const SortType type, const bool onLeft, const bool ascending); //always call this method for sorting, never sort externally! - - private: - class SerializeHierarchy; - - struct RefIndex - { - RefIndex(unsigned int folderInd, FileSystemObject::ObjectID id) : - folderIndex(folderInd), - objId(id) {} - unsigned int folderIndex; - FileSystemObject::ObjectID objId; - }; - - FileSystemObject* getReferencedRow(const RefIndex ref); //returns NULL if not found - const FileSystemObject* getReferencedRow(const RefIndex ref) const; //returns NULL if not found - bool isInvalidRow(const RefIndex& ref) const; - - - std::vector<RefIndex> viewRef; //partial view on sortedRef - // | - // | (update...) - // \|/ - std::vector<RefIndex> sortedRef; //equivalent to folerCmp, but may be sorted - // | - // | (setData) - // \|/ - FolderComparison folderCmp; //actual comparison data: owned by GridView! - - - //sorting classes - template <bool ascending> - class SortByDirectory; - - template <bool ascending, SelectedSide side> - class SortByRelName; - - template <bool ascending, SelectedSide side> - class SortByFileName; - - template <bool ascending, SelectedSide side> - class SortByFileSize; - - template <bool ascending, SelectedSide side> - class SortByDate; - - template <bool ascending> - class SortByCmpResult; - - template <bool ascending> - class SortBySyncDirection; + + + FolderComparison& getDataTentative(); //get data for operation that does NOT add or reorder rows! (deletion is okay) + void setData(FolderComparison& newData); //set data, taking ownership: warning std::swap() is used!!! + void removeInvalidRows(); //remove rows that have been deleted meanwhile: call after manual deletion and synchronization! + void clearAllRows(); //clears everything + + //sorting... + enum SortType + { + SORT_BY_REL_NAME, + SORT_BY_FILENAME, + SORT_BY_FILESIZE, + SORT_BY_DATE, + SORT_BY_CMP_RESULT, + SORT_BY_DIRECTORY, + SORT_BY_SYNC_DIRECTION }; + void sortView(const SortType type, const bool onLeft, const bool ascending); //always call this method for sorting, never sort externally! + +private: + class SerializeHierarchy; + + struct RefIndex + { + RefIndex(unsigned int folderInd, HierarchyObject::ObjectID id) : + folderIndex(folderInd), + objId(id) {} + unsigned int folderIndex; + HierarchyObject::ObjectID objId; + }; + + FileSystemObject* getReferencedRow(const RefIndex ref); //returns NULL if not found + const FileSystemObject* getReferencedRow(const RefIndex ref) const; //returns NULL if not found + bool isInvalidRow(const RefIndex& ref) const; + + + std::vector<RefIndex> viewRef; //partial view on sortedRef + // | + // | (update...) + // \|/ + std::vector<RefIndex> sortedRef; //equivalent to folerCmp, but may be sorted + // | + // | (setData) + // \|/ + FolderComparison folderCmp; //actual comparison data: owned by GridView! + + + //sorting classes + template <bool ascending> + class SortByDirectory; + + template <bool ascending, SelectedSide side> + class SortByRelName; + + template <bool ascending, SelectedSide side> + class SortByFileName; + + template <bool ascending, SelectedSide side> + class SortByFileSize; + + template <bool ascending, SelectedSide side> + class SortByDate; + + template <bool ascending> + class SortByCmpResult; + + template <bool ascending> + class SortBySyncDirection; +}; + @@ -167,56 +167,56 @@ namespace FreeFileSync //############################################################################ //inline implementation - inline - const FileSystemObject* GridView::getObject(unsigned int row) const - { - if (row < rowsOnView()) - return getReferencedRow(viewRef[row]); - else - return NULL; - } - - inline - FileSystemObject* GridView::getObject(unsigned int row) - { - //code re-use of const method: see Meyers Effective C++ - return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getObject(row)); - } +inline +const FileSystemObject* GridView::getObject(unsigned int row) const +{ + if (row < rowsOnView()) + return getReferencedRow(viewRef[row]); + else + return NULL; +} +inline +FileSystemObject* GridView::getObject(unsigned int row) +{ + //code re-use of const method: see Meyers Effective C++ + return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getObject(row)); +} - inline - unsigned int GridView::rowsOnView() const - { - return viewRef.size(); - } +inline +unsigned int GridView::rowsOnView() const +{ + return viewRef.size(); +} - inline - FolderComparison& GridView::getDataTentative() - { - return folderCmp; - } - inline - unsigned int GridView::rowsTotal() const //total number of rows available - { - return sortedRef.size(); - } +inline +FolderComparison& GridView::getDataTentative() +{ + return folderCmp; +} +inline +unsigned int GridView::rowsTotal() const //total number of rows available +{ + return sortedRef.size(); +} - inline - const FreeFileSync::FileSystemObject* GridView::getReferencedRow(const RefIndex ref) const - { - return folderCmp[ref.folderIndex].retrieveById(ref.objId); - } +inline +const FreeFileSync::FileSystemObject* GridView::getReferencedRow(const RefIndex ref) const +{ + return folderCmp[ref.folderIndex].retrieveById(ref.objId); +} - inline - FreeFileSync::FileSystemObject* GridView::getReferencedRow(const RefIndex ref) - { - //code re-use of const method: see Meyers Effective C++ - return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getReferencedRow(ref)); - } + +inline +FreeFileSync::FileSystemObject* GridView::getReferencedRow(const RefIndex ref) +{ + //code re-use of const method: see Meyers Effective C++ + return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getReferencedRow(ref)); +} } diff --git a/ui/guiGenerated.cpp b/ui/guiGenerated.cpp index 61fc95d3..9a9cb63b 100644 --- a/ui/guiGenerated.cpp +++ b/ui/guiGenerated.cpp @@ -15,882 +15,882 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 640,400 ), wxDefaultSize ); - - m_menubar1 = new wxMenuBar( 0 ); - m_menuFile = new wxMenu(); - m_menuItem10 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("1. &Compare") ) + wxT('\t') + wxT("ALT-C"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem10 ); - - m_menuItem11 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("2. &Synchronize...") ) + wxT('\t') + wxT("ALT-S"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem11 ); - - m_menuFile->AppendSeparator(); - - m_menuItemSwitchView = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("S&witch view") ) + wxT('\t') + wxT("ALT-W"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSwitchView ); - - m_menuFile->AppendSeparator(); - - m_menuItemNew = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("&New") ) + wxT('\t') + wxT("CTRL-N"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemNew ); - - m_menuItemSave = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("S&ave configuration") ) + wxT('\t') + wxT("CTRL-S"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemSave ); - - m_menuItemLoad = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("&Load configuration") ) + wxT('\t') + wxT("CTRL-L"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItemLoad ); - - m_menuFile->AppendSeparator(); - - wxMenuItem* m_menuItem4; - m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("&Quit") ) + wxT('\t') + wxT("CTRL-Q"), wxEmptyString, wxITEM_NORMAL ); - m_menuFile->Append( m_menuItem4 ); - - m_menubar1->Append( m_menuFile, _("&File") ); - - m_menuAdvanced = new wxMenu(); - m_menuLanguages = new wxMenu(); - m_menuAdvanced->Append( -1, _("&Language"), m_menuLanguages ); - - m_menuAdvanced->AppendSeparator(); - - m_menuItemGlobSett = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Global settings") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuAdvanced->Append( m_menuItemGlobSett ); - - m_menuItem7 = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Create batch job") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuAdvanced->Append( m_menuItem7 ); - - wxMenuItem* m_menuItem5; - m_menuItem5 = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Export file list") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuAdvanced->Append( m_menuItem5 ); - - m_menubar1->Append( m_menuAdvanced, _("&Advanced") ); - - m_menuHelp = new wxMenu(); - wxMenuItem* m_menuItemCheckVer; - m_menuItemCheckVer = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for new version") ) , wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemCheckVer ); - - m_menuHelp->AppendSeparator(); - - m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About...") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL ); - m_menuHelp->Append( m_menuItemAbout ); - - m_menubar1->Append( m_menuHelp, _("&Help") ); - - this->SetMenuBar( m_menubar1 ); - - bSizer1 = new wxBoxSizer( wxVERTICAL ); - - m_panel71 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER|wxTAB_TRAVERSAL ); - bSizer6 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer6->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxFlexGridSizer* fgSizer121; - fgSizer121 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer121->SetFlexibleDirection( wxBOTH ); - fgSizer121->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticTextCmpVariant = new wxStaticText( m_panel71, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextCmpVariant->Wrap( -1 ); - m_staticTextCmpVariant->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - m_staticTextCmpVariant->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - fgSizer121->Add( m_staticTextCmpVariant, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - fgSizer121->Add( 0, 0, 1, 0, 5 ); - - wxBoxSizer* bSizer30; - bSizer30 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonCompare = new wxButtonWithImage( m_panel71, wxID_OK, _("Compare"), wxDefaultPosition, wxSize( 180,42 ), 0 ); - m_buttonCompare->SetDefault(); - m_buttonCompare->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); - m_buttonCompare->SetToolTip( _("Compare both sides") ); - - bSizer30->Add( m_buttonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonAbort = new wxButton( m_panel71, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( 180,42 ), 0 ); - m_buttonAbort->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Tahoma") ) ); - m_buttonAbort->Enable( false ); - m_buttonAbort->Hide(); - - bSizer30->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - fgSizer121->Add( bSizer30, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonCmpConfig = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,42 ), wxBU_AUTODRAW ); - m_bpButtonCmpConfig->SetToolTip( _("Comparison settings") ); - - m_bpButtonCmpConfig->SetToolTip( _("Comparison settings") ); - - fgSizer121->Add( m_bpButtonCmpConfig, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 3 ); - - bSizer6->Add( fgSizer121, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - - - bSizer6->Add( 0, 0, 1, 0, 5 ); - - wxFlexGridSizer* fgSizer12; - fgSizer12 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer12->SetFlexibleDirection( wxBOTH ); - fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer12->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticTextSyncVariant = new wxStaticText( m_panel71, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSyncVariant->Wrap( -1 ); - m_staticTextSyncVariant->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - m_staticTextSyncVariant->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); - - fgSizer12->Add( m_staticTextSyncVariant, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_bpButtonSyncConfig = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,42 ), wxBU_AUTODRAW ); - m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") ); - - m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") ); - - fgSizer12->Add( m_bpButtonSyncConfig, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); - - m_buttonStartSync = new wxButtonWithImage( m_panel71, wxID_ANY, _("Synchronize..."), wxDefaultPosition, wxSize( -1,42 ), 0 ); - m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); - m_buttonStartSync->SetToolTip( _("Start synchronization") ); - - fgSizer12->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer6->Add( fgSizer12, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - - - bSizer6->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel71->SetSizer( bSizer6 ); - m_panel71->Layout(); - bSizer6->Fit( m_panel71 ); - bSizer1->Add( m_panel71, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - wxBoxSizer* bSizer91; - bSizer91 = new wxBoxSizer( wxHORIZONTAL ); - - m_panelTopLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer92; - bSizer92 = new wxBoxSizer( wxVERTICAL ); - - sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_panelTopLeft, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); - - m_directoryLeft = new wxComboBox( m_panelTopLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - sbSizer2->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerLeft = new wxDirPickerCtrl( m_panelTopLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLeft->SetToolTip( _("Select a folder") ); - - sbSizer2->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer92->Add( sbSizer2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_panelTopLeft->SetSizer( bSizer92 ); - m_panelTopLeft->Layout(); - bSizer92->Fit( m_panelTopLeft ); - bSizer91->Add( m_panelTopLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelTopMiddle = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer93; - bSizer93 = new wxBoxSizer( wxVERTICAL ); - - - bSizer93->Add( 0, 3, 0, 0, 5 ); - - bSizerMiddle = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonSwapSides = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - m_bpButtonSwapSides->SetToolTip( _("Swap sides") ); - - m_bpButtonSwapSides->SetToolTip( _("Swap sides") ); - - bSizerMiddle->Add( m_bpButtonSwapSides, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer93->Add( bSizerMiddle, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_panelTopMiddle->SetSizer( bSizer93 ); - m_panelTopMiddle->Layout(); - bSizer93->Fit( m_panelTopMiddle ); - bSizer91->Add( m_panelTopMiddle, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelTopRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer94; - bSizer94 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer77; - bSizer77 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticBoxSizer* sbSizer3; - sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelTopRight, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); - - m_bpButtonAddPair = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - - sbSizer3->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3 ); - - m_directoryRight = new wxComboBox( m_panelTopRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); - sbSizer3->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerRight = new wxDirPickerCtrl( m_panelTopRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerRight->SetToolTip( _("Select a folder") ); - - sbSizer3->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer77->Add( sbSizer3, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 3 ); - - bSizer94->Add( bSizer77, 0, wxEXPAND|wxLEFT, 3 ); - - m_panelTopRight->SetSizer( bSizer94 ); - m_panelTopRight->Layout(); - bSizer94->Fit( m_panelTopRight ); - bSizer91->Add( m_panelTopRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer1->Add( bSizer91, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_scrolledWindowFolderPairs = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHSCROLL|wxVSCROLL ); - m_scrolledWindowFolderPairs->SetScrollRate( 5, 5 ); - m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1,0 ) ); - - bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); - - m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs ); - m_scrolledWindowFolderPairs->Layout(); - bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs ); - bSizer1->Add( m_scrolledWindowFolderPairs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer2; - bSizer2 = new wxBoxSizer( wxHORIZONTAL ); - - m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxVERTICAL ); - - m_gridLeft = new CustomGridLeft( m_panelLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - - // Grid - m_gridLeft->CreateGrid( 15, 4 ); - m_gridLeft->EnableEditing( false ); - m_gridLeft->EnableGridLines( true ); - m_gridLeft->EnableDragGridSize( true ); - m_gridLeft->SetMargins( 0, 0 ); - - // Columns - m_gridLeft->EnableDragColMove( false ); - m_gridLeft->EnableDragColSize( true ); - m_gridLeft->SetColLabelSize( 20 ); - m_gridLeft->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); - - // Rows - m_gridLeft->EnableDragRowSize( false ); - m_gridLeft->SetRowLabelSize( 38 ); - m_gridLeft->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Label Appearance - - // Cell Defaults - m_gridLeft->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); - bSizer7->Add( m_gridLeft, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); - - m_panelLeft->SetSizer( bSizer7 ); - m_panelLeft->Layout(); - bSizer7->Fit( m_panelLeft ); - bSizer2->Add( m_panelLeft, 1, wxEXPAND, 5 ); - - m_panelMiddle = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer18; - bSizer18 = new wxBoxSizer( wxVERTICAL ); - - m_gridMiddle = new CustomGridMiddle( m_panelMiddle, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - - // Grid - m_gridMiddle->CreateGrid( 15, 1 ); - m_gridMiddle->EnableEditing( false ); - m_gridMiddle->EnableGridLines( true ); - m_gridMiddle->EnableDragGridSize( false ); - m_gridMiddle->SetMargins( 0, 0 ); - - // Columns - m_gridMiddle->SetColSize( 0, 60 ); - m_gridMiddle->EnableDragColMove( false ); - m_gridMiddle->EnableDragColSize( false ); - m_gridMiddle->SetColLabelSize( 20 ); - m_gridMiddle->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Rows - m_gridMiddle->EnableDragRowSize( false ); - m_gridMiddle->SetRowLabelSize( 0 ); - m_gridMiddle->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Label Appearance - - // Cell Defaults - m_gridMiddle->SetDefaultCellFont( wxFont( 12, 74, 90, 92, false, wxT("Arial") ) ); - m_gridMiddle->SetDefaultCellAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - bSizer18->Add( m_gridMiddle, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - m_panelMiddle->SetSizer( bSizer18 ); - m_panelMiddle->Layout(); - bSizer18->Fit( m_panelMiddle ); - bSizer2->Add( m_panelMiddle, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer10; - bSizer10 = new wxBoxSizer( wxVERTICAL ); - - m_gridRight = new CustomGridRight( m_panelRight, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - - // Grid - m_gridRight->CreateGrid( 15, 4 ); - m_gridRight->EnableEditing( false ); - m_gridRight->EnableGridLines( true ); - m_gridRight->EnableDragGridSize( true ); - m_gridRight->SetMargins( 0, 0 ); - - // Columns - m_gridRight->EnableDragColMove( false ); - m_gridRight->EnableDragColSize( true ); - m_gridRight->SetColLabelSize( 20 ); - m_gridRight->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); - - // Rows - m_gridRight->EnableDragRowSize( false ); - m_gridRight->SetRowLabelSize( 38 ); - m_gridRight->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Label Appearance - - // Cell Defaults - m_gridRight->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); - bSizer10->Add( m_gridRight, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); - - m_panelRight->SetSizer( bSizer10 ); - m_panelRight->Layout(); - bSizer10->Fit( m_panelRight ); - bSizer2->Add( m_panelRight, 1, wxEXPAND, 5 ); - - bSizer1->Add( bSizer2, 1, wxEXPAND, 5 ); - - wxPanel* m_panelBottom; - m_panelBottom = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - bSizer3 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer120; - bSizer120 = new wxBoxSizer( wxVERTICAL ); - - m_notebookBottomLeft = new wxNotebook( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panel30 = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer139; - bSizer139 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonSave = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButtonSave->SetToolTip( _("Save current configuration to file") ); - - m_bpButtonSave->SetToolTip( _("Save current configuration to file") ); - - bSizer139->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLoad = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButtonLoad->SetToolTip( _("Load configuration from file") ); - - m_bpButtonLoad->SetToolTip( _("Load configuration from file") ); - - bSizer139->Add( m_bpButtonLoad, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - wxArrayString m_choiceHistoryChoices; - m_choiceHistory = new wxChoice( m_panel30, wxID_ANY, wxDefaultPosition, wxSize( 170,-1 ), m_choiceHistoryChoices, 0 ); - m_choiceHistory->SetSelection( 0 ); - m_choiceHistory->SetToolTip( _("Load configuration history (press DEL to delete items)") ); - - bSizer139->Add( m_choiceHistory, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel30->SetSizer( bSizer139 ); - m_panel30->Layout(); - bSizer139->Fit( m_panel30 ); - m_notebookBottomLeft->AddPage( m_panel30, _("Configuration"), true ); - m_panelFilter = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer140; - bSizer140 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonFilter = new wxBitmapButton( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); - bSizer140->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - wxBoxSizer* bSizer23; - bSizer23 = new wxBoxSizer( wxVERTICAL ); - - m_hyperlinkCfgFilter = new wxHyperlinkCtrl( m_panelFilter, wxID_ANY, _("Configure filter..."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - - m_hyperlinkCfgFilter->SetNormalColour( wxColour( 0, 0, 255 ) ); - m_hyperlinkCfgFilter->SetVisitedColour( wxColour( 0, 0, 255 ) ); - bSizer23->Add( m_hyperlinkCfgFilter, 0, wxALL, 5 ); - - m_checkBoxHideFilt = new wxCheckBox( m_panelFilter, wxID_ANY, _("Hide filtered items"), wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxHideFilt->SetToolTip( _("Choose to hide filtered files/directories from list") ); - - bSizer23->Add( m_checkBoxHideFilt, 0, 0, 5 ); - - bSizer140->Add( bSizer23, 0, 0, 5 ); - - m_panelFilter->SetSizer( bSizer140 ); - m_panelFilter->Layout(); - bSizer140->Fit( m_panelFilter ); - m_notebookBottomLeft->AddPage( m_panelFilter, _("Filter files"), false ); - - bSizer120->Add( m_notebookBottomLeft, 0, wxALL, 5 ); - - bSizer3->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 ); - - m_panel112 = new wxPanel( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer64; - bSizer64 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer31; - sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( m_panel112, wxID_ANY, _("Filter view") ), wxHORIZONTAL ); - - sbSizer31->SetMinSize( wxSize( 100,-1 ) ); - - sbSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonLeftOnly = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLeftNewer = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonEqual = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonEqual, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonDifferent = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonRightNewer = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonRightOnly = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncCreateLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncCreateLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncDirOverwLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncDirOverwLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncDeleteLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncDeleteLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncDirNone = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncDirNone, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncDeleteRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncDeleteRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncDirOverwRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncDirOverwRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonSyncCreateRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonSyncCreateRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonConflict = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - sbSizer31->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - - sbSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer64->Add( sbSizer31, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_panel112->SetSizer( bSizer64 ); - m_panel112->Layout(); - bSizer64->Fit( m_panel112 ); - bSizer3->Add( m_panel112, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizerBottomRight = new wxBoxSizer( wxHORIZONTAL ); - - - bSizerBottomRight->Add( 5, 0, 1, 0, 5 ); - - m_panelSyncPreview = new wxPanel( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer121; - bSizer121 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer161; - sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( m_panelSyncPreview, wxID_ANY, _("Statistics") ), wxHORIZONTAL ); - - wxFlexGridSizer* fgSizer5; - fgSizer5 = new wxFlexGridSizer( 2, 2, 0, 5 ); - fgSizer5->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_bitmapCreate = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreate->SetToolTip( _("Number of files and directories that will be created") ); - - fgSizer5->Add( m_bitmapCreate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlCreate = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlCreate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlCreate->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlCreate->SetToolTip( _("Number of files and directories that will be created") ); - - fgSizer5->Add( m_textCtrlCreate, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapDelete = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDelete->SetToolTip( _("Number of files and directories that will be deleted") ); - - fgSizer5->Add( m_bitmapDelete, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlDelete = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlDelete->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlDelete->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlDelete->SetToolTip( _("Number of files and directories that will be deleted") ); - - fgSizer5->Add( m_textCtrlDelete, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer161->Add( fgSizer5, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - wxFlexGridSizer* fgSizer6; - fgSizer6 = new wxFlexGridSizer( 2, 2, 0, 5 ); - fgSizer6->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_bitmapUpdate = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdate->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer6->Add( m_bitmapUpdate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlUpdate = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlUpdate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlUpdate->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlUpdate->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer6->Add( m_textCtrlUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapData = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total amount of data that will be transferred") ); - - fgSizer6->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlData = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlData->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlData->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlData->SetToolTip( _("Total amount of data that will be transferred") ); - - fgSizer6->Add( m_textCtrlData, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer161->Add( fgSizer6, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - bSizer121->Add( sbSizer161, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelSyncPreview->SetSizer( bSizer121 ); - m_panelSyncPreview->Layout(); - bSizer121->Fit( m_panelSyncPreview ); - bSizerBottomRight->Add( m_panelSyncPreview, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButton10 = new wxBitmapButton( m_panelBottom, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 50,50 ), wxBU_AUTODRAW ); - m_bpButton10->SetToolTip( _("Quit") ); - - m_bpButton10->SetToolTip( _("Quit") ); - - bSizerBottomRight->Add( m_bpButton10, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 ); - - bSizer3->Add( bSizerBottomRight, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); - - m_panelBottom->SetSizer( bSizer3 ); - m_panelBottom->Layout(); - bSizer3->Fit( m_panelBottom ); - bSizer1->Add( m_panelBottom, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_panel7 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer451; - bSizer451 = new wxBoxSizer( wxHORIZONTAL ); - - bSizer451->SetMinSize( wxSize( -1,22 ) ); - wxBoxSizer* bSizer53; - bSizer53 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextStatusLeft = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusLeft->Wrap( -1 ); - m_staticTextStatusLeft->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer53->Add( m_staticTextStatusLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer451->Add( bSizer53, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticline9 = new wxStaticLine( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer451->Add( m_staticline9, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxEXPAND, 2 ); - - - bSizer451->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextStatusMiddle = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusMiddle->Wrap( -1 ); - m_staticTextStatusMiddle->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer451->Add( m_staticTextStatusMiddle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer451->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticline10 = new wxStaticLine( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer451->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP, 2 ); - - wxBoxSizer* bSizer52; - bSizer52 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextStatusRight = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatusRight->Wrap( -1 ); - m_staticTextStatusRight->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer52->Add( m_staticTextStatusRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer50; - bSizer50 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer50->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmap15 = new wxStaticBitmap( m_panel7, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 10,10 ), 0 ); - bSizer50->Add( m_bitmap15, 0, wxALIGN_BOTTOM, 2 ); - - bSizer52->Add( bSizer50, 1, wxALIGN_BOTTOM|wxEXPAND, 5 ); - - bSizer451->Add( bSizer52, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel7->SetSizer( bSizer451 ); - m_panel7->Layout(); - bSizer451->Fit( m_panel7 ); - bSizer1->Add( m_panel7, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - this->SetSizer( bSizer1 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) ); - this->Connect( m_menuItem10->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) ); - this->Connect( m_menuItem11->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) ); - this->Connect( m_menuItemSwitchView->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ) ); - this->Connect( m_menuItemNew->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnNewConfig ) ); - this->Connect( m_menuItemSave->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ) ); - this->Connect( m_menuItemLoad->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ) ); - this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) ); - this->Connect( m_menuItemGlobSett->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); - this->Connect( m_menuItem7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); - this->Connect( m_menuItem5->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); - this->Connect( m_menuItemCheckVer->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) ); - this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); - m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); - m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this ); - m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this ); - m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this ); - m_directoryLeft->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); - m_dirPickerLeft->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); - m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this ); - m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this ); - m_directoryRight->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); - m_dirPickerRight->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); - m_gridLeft->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this ); - m_gridLeft->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); - m_gridLeft->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); - m_gridLeft->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this ); - m_gridMiddle->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this ); - m_gridMiddle->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this ); - m_gridMiddle->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this ); - m_gridRight->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this ); - m_gridRight->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); - m_gridRight->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); - m_gridRight->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this ); - m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this ); - m_bpButtonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this ); - m_choiceHistory->Connect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this ); - m_choiceHistory->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this ); - m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this ); - m_hyperlinkCfgFilter->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this ); - m_checkBoxHideFilt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this ); - m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this ); - m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this ); - m_bpButtonEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this ); - m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnDifferentFiles ), NULL, this ); - m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightNewerFiles ), NULL, this ); - m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightOnlyFiles ), NULL, this ); - m_bpButtonSyncCreateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateLeft ), NULL, this ); - m_bpButtonSyncDirOverwLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirLeft ), NULL, this ); - m_bpButtonSyncDeleteLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteLeft ), NULL, this ); - m_bpButtonSyncDirNone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirNone ), NULL, this ); - m_bpButtonSyncDeleteRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteRight ), NULL, this ); - m_bpButtonSyncDirOverwRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirRight ), NULL, this ); - m_bpButtonSyncCreateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateRight ), NULL, this ); - m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConflictFiles ), NULL, this ); - m_bpButton10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnQuit ), NULL, this ); + this->SetSizeHints( wxSize( 640,400 ), wxDefaultSize ); + + m_menubar1 = new wxMenuBar( 0 ); + m_menuFile = new wxMenu(); + m_menuItem10 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("1. &Compare") ) + wxT('\t') + wxT("ALT-C"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItem10 ); + + m_menuItem11 = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("2. &Synchronize...") ) + wxT('\t') + wxT("ALT-S"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItem11 ); + + m_menuFile->AppendSeparator(); + + m_menuItemSwitchView = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("S&witch view") ) + wxT('\t') + wxT("ALT-W"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemSwitchView ); + + m_menuFile->AppendSeparator(); + + m_menuItemNew = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("&New") ) + wxT('\t') + wxT("CTRL-N"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemNew ); + + m_menuItemSave = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("S&ave configuration") ) + wxT('\t') + wxT("CTRL-S"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemSave ); + + m_menuItemLoad = new wxMenuItem( m_menuFile, wxID_ANY, wxString( _("&Load configuration") ) + wxT('\t') + wxT("CTRL-L"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItemLoad ); + + m_menuFile->AppendSeparator(); + + wxMenuItem* m_menuItem4; + m_menuItem4 = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("&Quit") ) + wxT('\t') + wxT("CTRL-Q"), wxEmptyString, wxITEM_NORMAL ); + m_menuFile->Append( m_menuItem4 ); + + m_menubar1->Append( m_menuFile, _("&File") ); + + m_menuAdvanced = new wxMenu(); + m_menuLanguages = new wxMenu(); + m_menuAdvanced->Append( -1, _("&Language"), m_menuLanguages ); + + m_menuAdvanced->AppendSeparator(); + + m_menuItemGlobSett = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Global settings") ) , wxEmptyString, wxITEM_NORMAL ); + m_menuAdvanced->Append( m_menuItemGlobSett ); + + m_menuItem7 = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Create batch job") ) , wxEmptyString, wxITEM_NORMAL ); + m_menuAdvanced->Append( m_menuItem7 ); + + wxMenuItem* m_menuItem5; + m_menuItem5 = new wxMenuItem( m_menuAdvanced, wxID_ANY, wxString( _("&Export file list") ) , wxEmptyString, wxITEM_NORMAL ); + m_menuAdvanced->Append( m_menuItem5 ); + + m_menubar1->Append( m_menuAdvanced, _("&Advanced") ); + + m_menuHelp = new wxMenu(); + wxMenuItem* m_menuItemCheckVer; + m_menuItemCheckVer = new wxMenuItem( m_menuHelp, wxID_ANY, wxString( _("&Check for new version") ) , wxEmptyString, wxITEM_NORMAL ); + m_menuHelp->Append( m_menuItemCheckVer ); + + m_menuHelp->AppendSeparator(); + + m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About...") ) + wxT('\t') + wxT("F1"), wxEmptyString, wxITEM_NORMAL ); + m_menuHelp->Append( m_menuItemAbout ); + + m_menubar1->Append( m_menuHelp, _("&Help") ); + + this->SetMenuBar( m_menubar1 ); + + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + m_panel71 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER|wxTAB_TRAVERSAL ); + bSizer6 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer6->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxFlexGridSizer* fgSizer121; + fgSizer121 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer121->SetFlexibleDirection( wxBOTH ); + fgSizer121->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticTextCmpVariant = new wxStaticText( m_panel71, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCmpVariant->Wrap( -1 ); + m_staticTextCmpVariant->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + m_staticTextCmpVariant->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + + fgSizer121->Add( m_staticTextCmpVariant, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); + + + fgSizer121->Add( 0, 0, 1, 0, 5 ); + + wxBoxSizer* bSizer30; + bSizer30 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonCompare = new wxButtonWithImage( m_panel71, wxID_OK, _("Compare"), wxDefaultPosition, wxSize( 180,42 ), 0 ); + m_buttonCompare->SetDefault(); + m_buttonCompare->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + m_buttonCompare->SetToolTip( _("Compare both sides") ); + + bSizer30->Add( m_buttonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonAbort = new wxButton( m_panel71, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( 180,42 ), 0 ); + m_buttonAbort->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Tahoma") ) ); + m_buttonAbort->Enable( false ); + m_buttonAbort->Hide(); + + bSizer30->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + fgSizer121->Add( bSizer30, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonCmpConfig = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,42 ), wxBU_AUTODRAW ); + m_bpButtonCmpConfig->SetToolTip( _("Comparison settings") ); + + m_bpButtonCmpConfig->SetToolTip( _("Comparison settings") ); + + fgSizer121->Add( m_bpButtonCmpConfig, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 3 ); + + bSizer6->Add( fgSizer121, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); + + + bSizer6->Add( 0, 0, 1, 0, 5 ); + + wxFlexGridSizer* fgSizer12; + fgSizer12 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer12->SetFlexibleDirection( wxBOTH ); + fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer12->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticTextSyncVariant = new wxStaticText( m_panel71, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSyncVariant->Wrap( -1 ); + m_staticTextSyncVariant->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + m_staticTextSyncVariant->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) ); + + fgSizer12->Add( m_staticTextSyncVariant, 1, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_bpButtonSyncConfig = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,42 ), wxBU_AUTODRAW ); + m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") ); + + m_bpButtonSyncConfig->SetToolTip( _("Synchronization settings") ); + + fgSizer12->Add( m_bpButtonSyncConfig, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 ); + + m_buttonStartSync = new wxButtonWithImage( m_panel71, wxID_ANY, _("Synchronize..."), wxDefaultPosition, wxSize( -1,42 ), 0 ); + m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + m_buttonStartSync->SetToolTip( _("Start synchronization") ); + + fgSizer12->Add( m_buttonStartSync, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer6->Add( fgSizer12, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); + + + bSizer6->Add( 15, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel71->SetSizer( bSizer6 ); + m_panel71->Layout(); + bSizer6->Fit( m_panel71 ); + bSizer1->Add( m_panel71, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + wxBoxSizer* bSizer91; + bSizer91 = new wxBoxSizer( wxHORIZONTAL ); + + m_panelTopLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer92; + bSizer92 = new wxBoxSizer( wxVERTICAL ); + + sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_panelTopLeft, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + + m_directoryLeft = new wxComboBox( m_panelTopLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + sbSizer2->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLeft = new wxDirPickerCtrl( m_panelTopLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLeft->SetToolTip( _("Select a folder") ); + + sbSizer2->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer92->Add( sbSizer2, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_panelTopLeft->SetSizer( bSizer92 ); + m_panelTopLeft->Layout(); + bSizer92->Fit( m_panelTopLeft ); + bSizer91->Add( m_panelTopLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelTopMiddle = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer93; + bSizer93 = new wxBoxSizer( wxVERTICAL ); + + + bSizer93->Add( 0, 3, 0, 0, 5 ); + + bSizerMiddle = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButtonSwapSides = new wxBitmapButton( m_panelTopMiddle, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + m_bpButtonSwapSides->SetToolTip( _("Swap sides") ); + + m_bpButtonSwapSides->SetToolTip( _("Swap sides") ); + + bSizerMiddle->Add( m_bpButtonSwapSides, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer93->Add( bSizerMiddle, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_panelTopMiddle->SetSizer( bSizer93 ); + m_panelTopMiddle->Layout(); + bSizer93->Fit( m_panelTopMiddle ); + bSizer91->Add( m_panelTopMiddle, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_panelTopRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer94; + bSizer94 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer77; + bSizer77 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelTopRight, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + + m_bpButtonAddPair = new wxBitmapButton( m_panelTopRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); + + m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); + + sbSizer3->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3 ); + + m_directoryRight = new wxComboBox( m_panelTopRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + sbSizer3->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerRight = new wxDirPickerCtrl( m_panelTopRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerRight->SetToolTip( _("Select a folder") ); + + sbSizer3->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer77->Add( sbSizer3, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 3 ); + + bSizer94->Add( bSizer77, 0, wxEXPAND|wxLEFT, 3 ); + + m_panelTopRight->SetSizer( bSizer94 ); + m_panelTopRight->Layout(); + bSizer94->Fit( m_panelTopRight ); + bSizer91->Add( m_panelTopRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer1->Add( bSizer91, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_scrolledWindowFolderPairs = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxHSCROLL|wxVSCROLL ); + m_scrolledWindowFolderPairs->SetScrollRate( 5, 5 ); + m_scrolledWindowFolderPairs->SetMinSize( wxSize( -1,0 ) ); + + bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); + + m_scrolledWindowFolderPairs->SetSizer( bSizerAddFolderPairs ); + m_scrolledWindowFolderPairs->Layout(); + bSizerAddFolderPairs->Fit( m_scrolledWindowFolderPairs ); + bSizer1->Add( m_scrolledWindowFolderPairs, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + m_gridLeft = new CustomGridLeft( m_panelLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_gridLeft->CreateGrid( 15, 4 ); + m_gridLeft->EnableEditing( false ); + m_gridLeft->EnableGridLines( true ); + m_gridLeft->EnableDragGridSize( true ); + m_gridLeft->SetMargins( 0, 0 ); + + // Columns + m_gridLeft->EnableDragColMove( false ); + m_gridLeft->EnableDragColSize( true ); + m_gridLeft->SetColLabelSize( 20 ); + m_gridLeft->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + + // Rows + m_gridLeft->EnableDragRowSize( false ); + m_gridLeft->SetRowLabelSize( 38 ); + m_gridLeft->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_gridLeft->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + bSizer7->Add( m_gridLeft, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); + + m_panelLeft->SetSizer( bSizer7 ); + m_panelLeft->Layout(); + bSizer7->Fit( m_panelLeft ); + bSizer2->Add( m_panelLeft, 1, wxEXPAND, 5 ); + + m_panelMiddle = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer18; + bSizer18 = new wxBoxSizer( wxVERTICAL ); + + m_gridMiddle = new CustomGridMiddle( m_panelMiddle, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_gridMiddle->CreateGrid( 15, 1 ); + m_gridMiddle->EnableEditing( false ); + m_gridMiddle->EnableGridLines( true ); + m_gridMiddle->EnableDragGridSize( false ); + m_gridMiddle->SetMargins( 0, 0 ); + + // Columns + m_gridMiddle->SetColSize( 0, 60 ); + m_gridMiddle->EnableDragColMove( false ); + m_gridMiddle->EnableDragColSize( false ); + m_gridMiddle->SetColLabelSize( 20 ); + m_gridMiddle->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_gridMiddle->EnableDragRowSize( false ); + m_gridMiddle->SetRowLabelSize( 0 ); + m_gridMiddle->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_gridMiddle->SetDefaultCellFont( wxFont( 12, 74, 90, 92, false, wxT("Arial") ) ); + m_gridMiddle->SetDefaultCellAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + bSizer18->Add( m_gridMiddle, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_panelMiddle->SetSizer( bSizer18 ); + m_panelMiddle->Layout(); + bSizer18->Fit( m_panelMiddle ); + bSizer2->Add( m_panelMiddle, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer10; + bSizer10 = new wxBoxSizer( wxVERTICAL ); + + m_gridRight = new CustomGridRight( m_panelRight, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_gridRight->CreateGrid( 15, 4 ); + m_gridRight->EnableEditing( false ); + m_gridRight->EnableGridLines( true ); + m_gridRight->EnableDragGridSize( true ); + m_gridRight->SetMargins( 0, 0 ); + + // Columns + m_gridRight->EnableDragColMove( false ); + m_gridRight->EnableDragColSize( true ); + m_gridRight->SetColLabelSize( 20 ); + m_gridRight->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + + // Rows + m_gridRight->EnableDragRowSize( false ); + m_gridRight->SetRowLabelSize( 38 ); + m_gridRight->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_gridRight->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + bSizer10->Add( m_gridRight, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5 ); + + m_panelRight->SetSizer( bSizer10 ); + m_panelRight->Layout(); + bSizer10->Fit( m_panelRight ); + bSizer2->Add( m_panelRight, 1, wxEXPAND, 5 ); + + bSizer1->Add( bSizer2, 1, wxEXPAND, 5 ); + + wxPanel* m_panelBottom; + m_panelBottom = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + bSizer3 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer120; + bSizer120 = new wxBoxSizer( wxVERTICAL ); + + m_notebookBottomLeft = new wxNotebook( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panel30 = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer139; + bSizer139 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButtonSave = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButtonSave->SetToolTip( _("Save current configuration to file") ); + + m_bpButtonSave->SetToolTip( _("Save current configuration to file") ); + + bSizer139->Add( m_bpButtonSave, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonLoad = new wxBitmapButton( m_panel30, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButtonLoad->SetToolTip( _("Load configuration from file") ); + + m_bpButtonLoad->SetToolTip( _("Load configuration from file") ); + + bSizer139->Add( m_bpButtonLoad, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + wxArrayString m_choiceHistoryChoices; + m_choiceHistory = new wxChoice( m_panel30, wxID_ANY, wxDefaultPosition, wxSize( 170,-1 ), m_choiceHistoryChoices, 0 ); + m_choiceHistory->SetSelection( 0 ); + m_choiceHistory->SetToolTip( _("Load configuration history (press DEL to delete items)") ); + + bSizer139->Add( m_choiceHistory, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel30->SetSizer( bSizer139 ); + m_panel30->Layout(); + bSizer139->Fit( m_panel30 ); + m_notebookBottomLeft->AddPage( m_panel30, _("Configuration"), true ); + m_panelFilter = new wxPanel( m_notebookBottomLeft, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer140; + bSizer140 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButtonFilter = new wxBitmapButton( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); + bSizer140->Add( m_bpButtonFilter, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + wxBoxSizer* bSizer23; + bSizer23 = new wxBoxSizer( wxVERTICAL ); + + m_hyperlinkCfgFilter = new wxHyperlinkCtrl( m_panelFilter, wxID_ANY, _("Configure filter..."), wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + + m_hyperlinkCfgFilter->SetNormalColour( wxColour( 0, 0, 255 ) ); + m_hyperlinkCfgFilter->SetVisitedColour( wxColour( 0, 0, 255 ) ); + bSizer23->Add( m_hyperlinkCfgFilter, 0, wxALL, 5 ); + + m_checkBoxHideFilt = new wxCheckBox( m_panelFilter, wxID_ANY, _("Hide filtered items"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxHideFilt->SetToolTip( _("Choose to hide filtered files/directories from list") ); + + bSizer23->Add( m_checkBoxHideFilt, 0, 0, 5 ); + + bSizer140->Add( bSizer23, 0, 0, 5 ); + + m_panelFilter->SetSizer( bSizer140 ); + m_panelFilter->Layout(); + bSizer140->Fit( m_panelFilter ); + m_notebookBottomLeft->AddPage( m_panelFilter, _("Filter files"), false ); + + bSizer120->Add( m_notebookBottomLeft, 0, wxALL, 5 ); + + bSizer3->Add( bSizer120, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 ); + + m_panel112 = new wxPanel( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer64; + bSizer64 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer31; + sbSizer31 = new wxStaticBoxSizer( new wxStaticBox( m_panel112, wxID_ANY, _("Filter view") ), wxHORIZONTAL ); + + sbSizer31->SetMinSize( wxSize( 100,-1 ) ); + + sbSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_bpButtonLeftOnly = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonLeftNewer = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonEqual = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonEqual, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonDifferent = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonRightNewer = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonRightOnly = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncCreateLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncCreateLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncDirOverwLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncDirOverwLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncDeleteLeft = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncDeleteLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncDirNone = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncDirNone, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncDeleteRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncDeleteRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncDirOverwRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncDirOverwRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonSyncCreateRight = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonSyncCreateRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonConflict = new ToggleButton( m_panel112, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + sbSizer31->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + + sbSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer64->Add( sbSizer31, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_panel112->SetSizer( bSizer64 ); + m_panel112->Layout(); + bSizer64->Fit( m_panel112 ); + bSizer3->Add( m_panel112, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + bSizerBottomRight = new wxBoxSizer( wxHORIZONTAL ); + + + bSizerBottomRight->Add( 5, 0, 1, 0, 5 ); + + m_panelSyncPreview = new wxPanel( m_panelBottom, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer121; + bSizer121 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer161; + sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( m_panelSyncPreview, wxID_ANY, _("Statistics") ), wxHORIZONTAL ); + + wxFlexGridSizer* fgSizer5; + fgSizer5 = new wxFlexGridSizer( 2, 2, 0, 5 ); + fgSizer5->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_bitmapCreate = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreate->SetToolTip( _("Number of files and directories that will be created") ); + + fgSizer5->Add( m_bitmapCreate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlCreate = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlCreate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlCreate->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlCreate->SetToolTip( _("Number of files and directories that will be created") ); + + fgSizer5->Add( m_textCtrlCreate, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmapDelete = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDelete->SetToolTip( _("Number of files and directories that will be deleted") ); + + fgSizer5->Add( m_bitmapDelete, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlDelete = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlDelete->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlDelete->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlDelete->SetToolTip( _("Number of files and directories that will be deleted") ); + + fgSizer5->Add( m_textCtrlDelete, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer161->Add( fgSizer5, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + wxFlexGridSizer* fgSizer6; + fgSizer6 = new wxFlexGridSizer( 2, 2, 0, 5 ); + fgSizer6->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_bitmapUpdate = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdate->SetToolTip( _("Number of files that will be overwritten") ); + + fgSizer6->Add( m_bitmapUpdate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlUpdate = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlUpdate->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlUpdate->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlUpdate->SetToolTip( _("Number of files that will be overwritten") ); + + fgSizer6->Add( m_textCtrlUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmapData = new wxStaticBitmap( m_panelSyncPreview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapData->SetToolTip( _("Total amount of data that will be transferred") ); + + fgSizer6->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlData = new wxTextCtrl( m_panelSyncPreview, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlData->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlData->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlData->SetToolTip( _("Total amount of data that will be transferred") ); + + fgSizer6->Add( m_textCtrlData, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer161->Add( fgSizer6, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + bSizer121->Add( sbSizer161, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelSyncPreview->SetSizer( bSizer121 ); + m_panelSyncPreview->Layout(); + bSizer121->Fit( m_panelSyncPreview ); + bSizerBottomRight->Add( m_panelSyncPreview, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButton10 = new wxBitmapButton( m_panelBottom, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 50,50 ), wxBU_AUTODRAW ); + m_bpButton10->SetToolTip( _("Quit") ); + + m_bpButton10->SetToolTip( _("Quit") ); + + bSizerBottomRight->Add( m_bpButton10, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT, 5 ); + + bSizer3->Add( bSizerBottomRight, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 ); + + m_panelBottom->SetSizer( bSizer3 ); + m_panelBottom->Layout(); + bSizer3->Fit( m_panelBottom ); + bSizer1->Add( m_panelBottom, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_panel7 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer451; + bSizer451 = new wxBoxSizer( wxHORIZONTAL ); + + bSizer451->SetMinSize( wxSize( -1,22 ) ); + wxBoxSizer* bSizer53; + bSizer53 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextStatusLeft = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusLeft->Wrap( -1 ); + m_staticTextStatusLeft->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer53->Add( m_staticTextStatusLeft, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer53->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer451->Add( bSizer53, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticline9 = new wxStaticLine( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer451->Add( m_staticline9, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxEXPAND, 2 ); + + + bSizer451->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextStatusMiddle = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusMiddle->Wrap( -1 ); + m_staticTextStatusMiddle->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer451->Add( m_staticTextStatusMiddle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer451->Add( 26, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticline10 = new wxStaticLine( m_panel7, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer451->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP, 2 ); + + wxBoxSizer* bSizer52; + bSizer52 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer52->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextStatusRight = new wxStaticText( m_panel7, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatusRight->Wrap( -1 ); + m_staticTextStatusRight->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer52->Add( m_staticTextStatusRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer50; + bSizer50 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer50->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmap15 = new wxStaticBitmap( m_panel7, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 10,10 ), 0 ); + bSizer50->Add( m_bitmap15, 0, wxALIGN_BOTTOM, 2 ); + + bSizer52->Add( bSizer50, 1, wxALIGN_BOTTOM|wxEXPAND, 5 ); + + bSizer451->Add( bSizer52, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel7->SetSizer( bSizer451 ); + m_panel7->Layout(); + bSizer451->Fit( m_panel7 ); + bSizer1->Add( m_panel7, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + this->SetSizer( bSizer1 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) ); + this->Connect( m_menuItem10->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) ); + this->Connect( m_menuItem11->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) ); + this->Connect( m_menuItemSwitchView->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ) ); + this->Connect( m_menuItemNew->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnNewConfig ) ); + this->Connect( m_menuItemSave->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ) ); + this->Connect( m_menuItemLoad->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ) ); + this->Connect( m_menuItem4->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) ); + this->Connect( m_menuItemGlobSett->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); + this->Connect( m_menuItem7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); + this->Connect( m_menuItem5->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); + this->Connect( m_menuItemCheckVer->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) ); + this->Connect( m_menuItemAbout->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); + m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); + m_bpButtonCmpConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this ); + m_bpButtonSyncConfig->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this ); + m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this ); + m_directoryLeft->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); + m_dirPickerLeft->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); + m_bpButtonSwapSides->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this ); + m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this ); + m_directoryRight->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); + m_dirPickerRight->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); + m_gridLeft->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this ); + m_gridLeft->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); + m_gridLeft->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); + m_gridLeft->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this ); + m_gridMiddle->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this ); + m_gridMiddle->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this ); + m_gridMiddle->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this ); + m_gridRight->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this ); + m_gridRight->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); + m_gridRight->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); + m_gridRight->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this ); + m_bpButtonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this ); + m_bpButtonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this ); + m_choiceHistory->Connect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this ); + m_choiceHistory->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this ); + m_bpButtonFilter->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this ); + m_hyperlinkCfgFilter->Connect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this ); + m_checkBoxHideFilt->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this ); + m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this ); + m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this ); + m_bpButtonEqual->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this ); + m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnDifferentFiles ), NULL, this ); + m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightNewerFiles ), NULL, this ); + m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightOnlyFiles ), NULL, this ); + m_bpButtonSyncCreateLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateLeft ), NULL, this ); + m_bpButtonSyncDirOverwLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirLeft ), NULL, this ); + m_bpButtonSyncDeleteLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteLeft ), NULL, this ); + m_bpButtonSyncDirNone->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirNone ), NULL, this ); + m_bpButtonSyncDeleteRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteRight ), NULL, this ); + m_bpButtonSyncDirOverwRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirRight ), NULL, this ); + m_bpButtonSyncCreateRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateRight ), NULL, this ); + m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConflictFiles ), NULL, this ); + m_bpButton10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnQuit ), NULL, this ); } MainDialogGenerated::~MainDialogGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnNewConfig ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); - m_buttonCompare->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); - m_bpButtonCmpConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this ); - m_bpButtonSyncConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this ); - m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this ); - m_directoryLeft->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); - m_dirPickerLeft->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); - m_bpButtonSwapSides->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this ); - m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this ); - m_directoryRight->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); - m_dirPickerRight->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); - m_gridLeft->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this ); - m_gridLeft->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); - m_gridLeft->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); - m_gridLeft->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this ); - m_gridMiddle->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this ); - m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this ); - m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this ); - m_gridRight->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this ); - m_gridRight->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); - m_gridRight->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); - m_gridRight->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this ); - m_bpButtonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this ); - m_bpButtonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this ); - m_choiceHistory->Disconnect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this ); - m_choiceHistory->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this ); - m_bpButtonFilter->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this ); - m_hyperlinkCfgFilter->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this ); - m_checkBoxHideFilt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this ); - m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this ); - m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this ); - m_bpButtonEqual->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this ); - m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnDifferentFiles ), NULL, this ); - m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightNewerFiles ), NULL, this ); - m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightOnlyFiles ), NULL, this ); - m_bpButtonSyncCreateLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateLeft ), NULL, this ); - m_bpButtonSyncDirOverwLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirLeft ), NULL, this ); - m_bpButtonSyncDeleteLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteLeft ), NULL, this ); - m_bpButtonSyncDirNone->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirNone ), NULL, this ); - m_bpButtonSyncDeleteRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteRight ), NULL, this ); - m_bpButtonSyncDirOverwRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirRight ), NULL, this ); - m_bpButtonSyncCreateRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateRight ), NULL, this ); - m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConflictFiles ), NULL, this ); - m_bpButton10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnQuit ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainDialogGenerated::OnClose ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompare ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSwitchView ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnNewConfig ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuQuit ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuCheckVersion ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); + m_buttonCompare->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); + m_bpButtonCmpConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCmpSettings ), NULL, this ); + m_bpButtonSyncConfig->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncSettings ), NULL, this ); + m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnStartSync ), NULL, this ); + m_directoryLeft->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); + m_dirPickerLeft->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); + m_bpButtonSwapSides->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapSides ), NULL, this ); + m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAddFolderPair ), NULL, this ); + m_directoryRight->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( MainDialogGenerated::OnFolderHistoryKeyEvent ), NULL, this ); + m_dirPickerRight->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); + m_gridLeft->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnLeftGridDoubleClick ), NULL, this ); + m_gridLeft->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); + m_gridLeft->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); + m_gridLeft->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelLeft ), NULL, this ); + m_gridMiddle->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddle ), NULL, this ); + m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), NULL, this ); + m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextMiddleLabel ), NULL, this ); + m_gridRight->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( MainDialogGenerated::OnRightGridDoubleClick ), NULL, this ); + m_gridRight->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRim ), NULL, this ); + m_gridRight->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); + m_gridRight->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnContextRimLabelRight ), NULL, this ); + m_bpButtonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSaveConfig ), NULL, this ); + m_bpButtonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLoadConfig ), NULL, this ); + m_choiceHistory->Disconnect( wxEVT_CHAR, wxKeyEventHandler( MainDialogGenerated::OnCfgHistoryKeyEvent ), NULL, this ); + m_choiceHistory->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnLoadFromHistory ), NULL, this ); + m_bpButtonFilter->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnFilterButton ), NULL, this ); + m_hyperlinkCfgFilter->Disconnect( wxEVT_COMMAND_HYPERLINK, wxHyperlinkEventHandler( MainDialogGenerated::OnConfigureFilter ), NULL, this ); + m_checkBoxHideFilt->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnHideFilteredButton ), NULL, this ); + m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftOnlyFiles ), NULL, this ); + m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnLeftNewerFiles ), NULL, this ); + m_bpButtonEqual->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnEqualFiles ), NULL, this ); + m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnDifferentFiles ), NULL, this ); + m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightNewerFiles ), NULL, this ); + m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnRightOnlyFiles ), NULL, this ); + m_bpButtonSyncCreateLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateLeft ), NULL, this ); + m_bpButtonSyncDirOverwLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirLeft ), NULL, this ); + m_bpButtonSyncDeleteLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteLeft ), NULL, this ); + m_bpButtonSyncDirNone->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirNone ), NULL, this ); + m_bpButtonSyncDeleteRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDeleteRight ), NULL, this ); + m_bpButtonSyncDirOverwRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncDirRight ), NULL, this ); + m_bpButtonSyncCreateRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSyncCreateRight ), NULL, this ); + m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnConflictFiles ), NULL, this ); + m_bpButton10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnQuit ), NULL, this ); } FolderPairGenerated::FolderPairGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) { - wxBoxSizer* bSizer74; - bSizer74 = new wxBoxSizer( wxHORIZONTAL ); - - m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer134->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLeft->SetToolTip( _("Select a folder") ); - - bSizer134->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_panelLeft->SetSizer( bSizer134 ); - m_panelLeft->Layout(); - bSizer134->Fit( m_panelLeft ); - bSizer74->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel20->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_APPWORKSPACE ) ); - - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxHORIZONTAL ); - - m_panel21 = new wxPanel( m_panel20, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_panel21->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); - - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer96->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bpButtonAltFilter = new wxBitmapButton( m_panel21, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); - m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); - - m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); - - bSizer96->Add( m_bpButtonAltFilter, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonAltSyncCfg = new wxBitmapButton( m_panel21, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); - m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); - - m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); - - bSizer96->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer96->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_panel21->SetSizer( bSizer96 ); - m_panel21->Layout(); - bSizer96->Fit( m_panel21 ); - bSizer95->Add( m_panel21, 0, wxRIGHT|wxLEFT|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel20->SetSizer( bSizer95 ); - m_panel20->Layout(); - bSizer95->Fit( m_panel20 ); - bSizer74->Add( m_panel20, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer135; - bSizer135 = new wxBoxSizer( wxHORIZONTAL ); - - m_bpButtonRemovePair = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - bSizer135->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer135->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerRight->SetToolTip( _("Select a folder") ); - - bSizer135->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_panelRight->SetSizer( bSizer135 ); - m_panelRight->Layout(); - bSizer135->Fit( m_panelRight ); - bSizer74->Add( m_panelRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - this->SetSizer( bSizer74 ); - this->Layout(); - bSizer74->Fit( this ); + wxBoxSizer* bSizer74; + bSizer74 = new wxBoxSizer( wxHORIZONTAL ); + + m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer134->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLeft->SetToolTip( _("Select a folder") ); + + bSizer134->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panelLeft->SetSizer( bSizer134 ); + m_panelLeft->Layout(); + bSizer134->Fit( m_panelLeft ); + bSizer74->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel20 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel20->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_APPWORKSPACE ) ); + + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxHORIZONTAL ); + + m_panel21 = new wxPanel( m_panel20, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_panel21->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_MENU ) ); + + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer96->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_bpButtonAltFilter = new wxBitmapButton( m_panel21, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); + m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); + + m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); + + bSizer96->Add( m_bpButtonAltFilter, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonAltSyncCfg = new wxBitmapButton( m_panel21, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); + m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); + + m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); + + bSizer96->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer96->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_panel21->SetSizer( bSizer96 ); + m_panel21->Layout(); + bSizer96->Fit( m_panel21 ); + bSizer95->Add( m_panel21, 0, wxRIGHT|wxLEFT|wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel20->SetSizer( bSizer95 ); + m_panel20->Layout(); + bSizer95->Fit( m_panel20 ); + bSizer74->Add( m_panel20, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer135; + bSizer135 = new wxBoxSizer( wxHORIZONTAL ); + + m_bpButtonRemovePair = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + + bSizer135->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer135->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerRight->SetToolTip( _("Select a folder") ); + + bSizer135->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panelRight->SetSizer( bSizer135 ); + m_panelRight->Layout(); + bSizer135->Fit( m_panelRight ); + bSizer74->Add( m_panelRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + this->SetSizer( bSizer74 ); + this->Layout(); + bSizer74->Fit( this ); } FolderPairGenerated::~FolderPairGenerated() @@ -899,121 +899,121 @@ FolderPairGenerated::~FolderPairGenerated() BatchFolderPairGenerated::BatchFolderPairGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) { - wxBoxSizer* bSizer142; - bSizer142 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer140; - bSizer140 = new wxBoxSizer( wxHORIZONTAL ); - - m_panel32 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER ); - wxBoxSizer* bSizer147; - bSizer147 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer136; - bSizer136 = new wxBoxSizer( wxVERTICAL ); - - m_bpButtonRemovePair = new wxBitmapButton( m_panel32, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); - - bSizer136->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer147->Add( bSizer136, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer143; - bSizer143 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer145; - bSizer145 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText53 = new wxStaticText( m_panel32, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText53->Wrap( -1 ); - m_staticText53->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer145->Add( m_staticText53, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer143->Add( bSizer145, 1, 0, 5 ); - - wxBoxSizer* bSizer146; - bSizer146 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText541 = new wxStaticText( m_panel32, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText541->Wrap( -1 ); - m_staticText541->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer146->Add( m_staticText541, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer143->Add( bSizer146, 1, 0, 5 ); - - bSizer147->Add( bSizer143, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_panel32->SetSizer( bSizer147 ); - m_panel32->Layout(); - bSizer147->Fit( m_panel32 ); - bSizer140->Add( m_panel32, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer144; - bSizer144 = new wxBoxSizer( wxVERTICAL ); - - m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer114; - bSizer114 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer114->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLeft->SetToolTip( _("Select a folder") ); - - bSizer114->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonAltSyncCfg = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); - m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); - - m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); - - bSizer114->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelLeft->SetSizer( bSizer114 ); - m_panelLeft->Layout(); - bSizer114->Fit( m_panelLeft ); - bSizer144->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer115; - bSizer115 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer115->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerRight->SetToolTip( _("Select a folder") ); - - bSizer115->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonAltFilter = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); - m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); - - m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); - - bSizer115->Add( m_bpButtonAltFilter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelRight->SetSizer( bSizer115 ); - m_panelRight->Layout(); - bSizer115->Fit( m_panelRight ); - bSizer144->Add( m_panelRight, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer140->Add( bSizer144, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer142->Add( bSizer140, 0, wxEXPAND, 5 ); - - - bSizer142->Add( 0, 5, 0, 0, 5 ); - - this->SetSizer( bSizer142 ); - this->Layout(); - bSizer142->Fit( this ); + wxBoxSizer* bSizer142; + bSizer142 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer140; + bSizer140 = new wxBoxSizer( wxHORIZONTAL ); + + m_panel32 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER ); + wxBoxSizer* bSizer147; + bSizer147 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer136; + bSizer136 = new wxBoxSizer( wxVERTICAL ); + + m_bpButtonRemovePair = new wxBitmapButton( m_panel32, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + + m_bpButtonRemovePair->SetToolTip( _("Remove folder pair") ); + + bSizer136->Add( m_bpButtonRemovePair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer147->Add( bSizer136, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer143; + bSizer143 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer145; + bSizer145 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText53 = new wxStaticText( m_panel32, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText53->Wrap( -1 ); + m_staticText53->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer145->Add( m_staticText53, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer143->Add( bSizer145, 1, 0, 5 ); + + wxBoxSizer* bSizer146; + bSizer146 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText541 = new wxStaticText( m_panel32, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText541->Wrap( -1 ); + m_staticText541->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer146->Add( m_staticText541, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer143->Add( bSizer146, 1, 0, 5 ); + + bSizer147->Add( bSizer143, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_panel32->SetSizer( bSizer147 ); + m_panel32->Layout(); + bSizer147->Fit( m_panel32 ); + bSizer140->Add( m_panel32, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer144; + bSizer144 = new wxBoxSizer( wxVERTICAL ); + + m_panelLeft = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer114; + bSizer114 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer114->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLeft->SetToolTip( _("Select a folder") ); + + bSizer114->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonAltSyncCfg = new wxBitmapButton( m_panelLeft, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); + m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); + + m_bpButtonAltSyncCfg->SetToolTip( _("Select alternate synchronization settings") ); + + bSizer114->Add( m_bpButtonAltSyncCfg, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelLeft->SetSizer( bSizer114 ); + m_panelLeft->Layout(); + bSizer114->Fit( m_panelLeft ); + bSizer144->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer115; + bSizer115 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer115->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerRight->SetToolTip( _("Select a folder") ); + + bSizer115->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonAltFilter = new wxBitmapButton( m_panelRight, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 20,20 ), wxBU_AUTODRAW ); + m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); + + m_bpButtonAltFilter->SetToolTip( _("Select alternate filter settings") ); + + bSizer115->Add( m_bpButtonAltFilter, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelRight->SetSizer( bSizer115 ); + m_panelRight->Layout(); + bSizer115->Fit( m_panelRight ); + bSizer144->Add( m_panelRight, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer140->Add( bSizer144, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer142->Add( bSizer140, 0, wxEXPAND, 5 ); + + + bSizer142->Add( 0, 5, 0, 0, 5 ); + + this->SetSizer( bSizer142 ); + this->Layout(); + bSizer142->Fit( this ); } BatchFolderPairGenerated::~BatchFolderPairGenerated() @@ -1022,710 +1022,723 @@ BatchFolderPairGenerated::~BatchFolderPairGenerated() BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer54; - bSizer54 = new wxBoxSizer( wxVERTICAL ); - - bSizer69 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer87; - bSizer87 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap27 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer87->Add( m_bitmap27, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxVERTICAL ); - - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Batch job"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText56->Wrap( -1 ); - m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer72->Add( m_staticText56, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_panel8->SetSizer( bSizer72 ); - m_panel8->Layout(); - bSizer72->Fit( m_panel8 ); - bSizer87->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer87->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); - - m_staticText54 = new wxStaticText( this, wxID_ANY, _("Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText54->Wrap( 520 ); - m_staticText54->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Tahoma") ) ); - - bSizer69->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - - bSizer69->Add( 0, 5, 0, 0, 5 ); - - m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP, 5 ); - - m_staticText531 = new wxStaticText( this, wxID_ANY, _("Configuration overview:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText531->Wrap( -1 ); - m_staticText531->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); - - bSizer69->Add( m_staticText531, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_notebookSettings = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_panelOverview = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer67; - bSizer67 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer120; - bSizer120 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer100; - bSizer100 = new wxBoxSizer( wxVERTICAL ); - - m_scrolledWindow6 = new wxScrolledWindow( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_scrolledWindow6->SetScrollRate( 5, 5 ); - wxBoxSizer* bSizer141; - bSizer141 = new wxBoxSizer( wxVERTICAL ); - - sbSizerMainPair = new wxBoxSizer( wxHORIZONTAL ); - - m_panelMainPair = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER ); - wxBoxSizer* bSizer147; - bSizer147 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer1361; - bSizer1361 = new wxBoxSizer( wxVERTICAL ); - - m_bpButtonAddPair = new wxBitmapButton( m_panelMainPair, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - - m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); - - bSizer1361->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3 ); - - bSizer147->Add( bSizer1361, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer143; - bSizer143 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer145; - bSizer145 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText532 = new wxStaticText( m_panelMainPair, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText532->Wrap( -1 ); - m_staticText532->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer145->Add( m_staticText532, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer143->Add( bSizer145, 1, 0, 5 ); - - wxBoxSizer* bSizer146; - bSizer146 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText5411 = new wxStaticText( m_panelMainPair, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText5411->Wrap( -1 ); - m_staticText5411->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer146->Add( m_staticText5411, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer143->Add( bSizer146, 1, 0, 5 ); - - bSizer147->Add( bSizer143, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - m_panelMainPair->SetSizer( bSizer147 ); - m_panelMainPair->Layout(); - bSizer147->Fit( m_panelMainPair ); - sbSizerMainPair->Add( m_panelMainPair, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxVERTICAL ); - - m_panelLeft = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1141; - bSizer1141 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1141->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLeft->SetToolTip( _("Select a folder") ); - - bSizer1141->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelLeft->SetSizer( bSizer1141 ); - m_panelLeft->Layout(); - bSizer1141->Fit( m_panelLeft ); - bSizer158->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_panelRight = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer115; - bSizer115 = new wxBoxSizer( wxHORIZONTAL ); - - m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer115->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerRight->SetToolTip( _("Select a folder") ); - - bSizer115->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelRight->SetSizer( bSizer115 ); - m_panelRight->Layout(); - bSizer115->Fit( m_panelRight ); - bSizer158->Add( m_panelRight, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizerMainPair->Add( bSizer158, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); - - bSizer141->Add( sbSizerMainPair, 0, wxEXPAND, 5 ); - - bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); - - bSizer141->Add( bSizerAddFolderPairs, 0, wxEXPAND, 5 ); - - m_scrolledWindow6->SetSizer( bSizer141 ); - m_scrolledWindow6->Layout(); - bSizer141->Fit( m_scrolledWindow6 ); - bSizer100->Add( m_scrolledWindow6, 0, wxEXPAND, 5 ); - - - bSizer100->Add( 0, 10, 0, 0, 5 ); - - wxFlexGridSizer* fgSizer15; - fgSizer15 = new wxFlexGridSizer( 2, 2, 10, 10 ); - fgSizer15->SetFlexibleDirection( wxBOTH ); - fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - wxStaticBoxSizer* sbSizer6; - sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Compare by...") ), wxVERTICAL ); - - m_radioBtnSizeDate = new wxRadioButton( m_panelOverview, wxID_ANY, _("File size and date"), wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtnSizeDate->SetValue( true ); - m_radioBtnSizeDate->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); - - sbSizer6->Add( m_radioBtnSizeDate, 0, 0, 5 ); - - m_radioBtnContent = new wxRadioButton( m_panelOverview, wxID_ANY, _("File content"), wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtnContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); - - sbSizer6->Add( m_radioBtnContent, 0, wxTOP, 5 ); - - fgSizer15->Add( sbSizer6, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer24; - sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_checkBoxFilter = new wxCheckBox( m_panelOverview, wxID_ANY, _("Filter files"), wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxFilter->SetToolTip( _("Enable filter to exclude files from synchronization") ); - - sbSizer24->Add( m_checkBoxFilter, 0, wxALL, 5 ); - - m_checkBoxSilent = new wxCheckBox( m_panelOverview, wxID_ANY, _("Silent mode"), wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxSilent->SetToolTip( _("Do not display visual status information but write to a logfile instead") ); - - sbSizer24->Add( m_checkBoxSilent, 0, wxALL, 5 ); - - - sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); - - fgSizer15->Add( sbSizer24, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - wxStaticBoxSizer* sbSizer25; - sbSizer25 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); - - wxArrayString m_choiceHandleErrorChoices; - m_choiceHandleError = new wxChoice( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleErrorChoices, 0 ); - m_choiceHandleError->SetSelection( 0 ); - sbSizer25->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - fgSizer15->Add( sbSizer25, 0, wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer23; - sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Deletion handling") ), wxVERTICAL ); - - wxArrayString m_choiceHandleDeletionChoices; - m_choiceHandleDeletion = new wxChoice( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleDeletionChoices, 0 ); - m_choiceHandleDeletion->SetSelection( 0 ); - sbSizer23->Add( m_choiceHandleDeletion, 0, wxBOTTOM, 5 ); - - m_panelCustomDeletionDir = new wxPanel( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1151; - bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); - - m_textCtrlCustomDelFolder = new wxTextCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RIGHT ); - m_textCtrlCustomDelFolder->SetMinSize( wxSize( 160,-1 ) ); - - bSizer1151->Add( m_textCtrlCustomDelFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerCustomDelFolder = new wxDirPickerCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1151->Add( m_dirPickerCustomDelFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelCustomDeletionDir->SetSizer( bSizer1151 ); - m_panelCustomDeletionDir->Layout(); - bSizer1151->Fit( m_panelCustomDeletionDir ); - sbSizer23->Add( m_panelCustomDeletionDir, 0, 0, 5 ); - - fgSizer15->Add( sbSizer23, 0, wxEXPAND, 5 ); - - bSizer100->Add( fgSizer15, 0, 0, 5 ); - - bSizer120->Add( bSizer100, 1, 0, 5 ); - - - bSizer120->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxStaticBoxSizer* sbSizer61; - sbSizer61 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Configuration") ), wxVERTICAL ); - - wxGridSizer* gSizer3; - gSizer3 = new wxGridSizer( 1, 2, 0, 5 ); - - m_staticText21 = new wxStaticText( m_panelOverview, wxID_ANY, _("Result"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText21->Wrap( -1 ); - m_staticText21->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - gSizer3->Add( m_staticText21, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText31 = new wxStaticText( m_panelOverview, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText31->Wrap( -1 ); - m_staticText31->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - gSizer3->Add( m_staticText31, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer61->Add( gSizer3, 0, wxEXPAND, 5 ); - - m_staticline3 = new wxStaticLine( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - sbSizer61->Add( m_staticline3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer121; - bSizer121 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer122; - bSizer122 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftOnly = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftOnly->SetToolTip( _("Files/folders that exist on left side only") ); - - bSizer122->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer122->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLeftOnly = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer122->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer122, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer123; - bSizer123 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightOnly = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightOnly->SetToolTip( _("Files/folders that exist on right side only") ); - - bSizer123->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer123->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightOnly = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer123->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer123, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer124; - bSizer124 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftNewer = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftNewer->SetToolTip( _("Files that exist on both sides, left one is newer") ); - - bSizer124->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer124->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonLeftNewer = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer124->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer124, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer125; - bSizer125 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightNewer = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightNewer->SetToolTip( _("Files that exist on both sides, right one is newer") ); - - bSizer125->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer125->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightNewer = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer125->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer125, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer126; - bSizer126 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapDifferent = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapDifferent->SetToolTip( _("Files that exist on both sides and have different content") ); - - bSizer126->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer126->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonDifferent = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer126->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer126, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer127; - bSizer127 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapConflict = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapConflict->SetToolTip( _("Conflicts/files that cannot be categorized") ); - - bSizer127->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer127->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonConflict = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer127->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer127, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - sbSizer61->Add( bSizer121, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer120->Add( sbSizer61, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer67->Add( bSizer120, 1, wxALL, 10 ); - - m_panelOverview->SetSizer( bSizer67 ); - m_panelOverview->Layout(); - bSizer67->Fit( m_panelOverview ); - m_notebookSettings->AddPage( m_panelOverview, _("Overview"), true ); - m_panelFilter = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer114; - bSizer114 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer8; - sbSizer8 = new wxStaticBoxSizer( new wxStaticBox( m_panelFilter, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer3; - fgSizer3 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer3->AddGrowableCol( 1 ); - fgSizer3->AddGrowableRow( 1 ); - fgSizer3->SetFlexibleDirection( wxBOTH ); - fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText15 = new wxStaticText( m_panelFilter, wxID_ANY, _("Include"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText15->Wrap( -1 ); - m_staticText15->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer3->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_bitmap8 = new wxStaticBitmap( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - m_bitmap8->SetToolTip( _("Include") ); - - fgSizer3->Add( m_bitmap8, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlInclude = new wxTextCtrl( m_panelFilter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - fgSizer3->Add( m_textCtrlInclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer8->Add( fgSizer3, 1, wxEXPAND, 5 ); - - wxFlexGridSizer* fgSizer4; - fgSizer4 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer4->AddGrowableCol( 1 ); - fgSizer4->AddGrowableRow( 1 ); - fgSizer4->SetFlexibleDirection( wxBOTH ); - fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText16 = new wxStaticText( m_panelFilter, wxID_ANY, _("Exclude"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText16->Wrap( -1 ); - m_staticText16->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer4->Add( m_staticText16, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_bitmap9 = new wxStaticBitmap( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - m_bitmap9->SetToolTip( _("Exclude") ); - - fgSizer4->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlExclude = new wxTextCtrl( m_panelFilter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - fgSizer4->Add( m_textCtrlExclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer8->Add( fgSizer4, 1, wxEXPAND, 5 ); - - bSizer114->Add( sbSizer8, 1, wxALL|wxEXPAND, 10 ); - - m_panelFilter->SetSizer( bSizer114 ); - m_panelFilter->Layout(); - bSizer114->Fit( m_panelFilter ); - m_notebookSettings->AddPage( m_panelFilter, _("Filter"), false ); - m_panelLogging = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer117; - bSizer117 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer119; - bSizer119 = new wxBoxSizer( wxVERTICAL ); - - m_staticText120 = new wxStaticText( m_panelLogging, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText120->Wrap( -1 ); - bSizer119->Add( m_staticText120, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxStaticBoxSizer* sbSizer251; - sbSizer251 = new wxStaticBoxSizer( new wxStaticBox( m_panelLogging, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); - - m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer251->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerLogfileDir = new wxDirPickerCtrl( m_panelLogging, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); - - sbSizer251->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer119->Add( sbSizer251, 1, wxEXPAND, 5 ); - - bSizer117->Add( bSizer119, 0, wxEXPAND|wxALL, 10 ); - - m_panelLogging->SetSizer( bSizer117 ); - m_panelLogging->Layout(); - bSizer117->Fit( m_panelLogging ); - m_notebookSettings->AddPage( m_panelLogging, _("Logging"), false ); - - bSizer69->Add( m_notebookSettings, 1, wxEXPAND, 5 ); - - wxBoxSizer* bSizer68; - bSizer68 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonSave = new wxButton( this, wxID_SAVE, _("&Save"), wxDefaultPosition, wxSize( 120,35 ), 0 ); - m_buttonSave->SetDefault(); - m_buttonSave->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer68->Add( m_buttonSave, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonLoad = new wxButton( this, wxID_OPEN, _("&Load"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonLoad->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer68->Add( m_buttonLoad, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button6->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer68->Add( m_button6, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer69->Add( bSizer68, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer54->Add( bSizer69, 1, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5 ); - - this->SetSizer( bSizer54 ); - this->Layout(); - bSizer54->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::OnClose ) ); - m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); - m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); - m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); - m_checkBoxFilter->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckFilter ), NULL, this ); - m_checkBoxSilent->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckLogging ), NULL, this ); - m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); - m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeDeletionHandling ), NULL, this ); - m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExLeftSideOnly ), NULL, this ); - m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExRightSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); - m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); - m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); - m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnConflict ), NULL, this ); - m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); - m_buttonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLoadBatchJob ), NULL, this ); - m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer54; + bSizer54 = new wxBoxSizer( wxVERTICAL ); + + bSizer69 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer87; + bSizer87 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap27 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); + bSizer87->Add( m_bitmap27, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxVERTICAL ); + + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Batch job"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56->Wrap( -1 ); + m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer72->Add( m_staticText56, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_panel8->SetSizer( bSizer72 ); + m_panel8->Layout(); + bSizer72->Fit( m_panel8 ); + bSizer87->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer87->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer69->Add( bSizer87, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer69->Add( 0, 5, 0, 0, 5 ); + + m_staticText54 = new wxStaticText( this, wxID_ANY, _("Assemble a batch file for automated synchronization. To start in batch mode simply pass the name of the file to the FreeFileSync executable: FreeFileSync.exe <batchfile>. This can also be scheduled in your operating system's task planner."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText54->Wrap( 520 ); + m_staticText54->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Tahoma") ) ); + + bSizer69->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + + bSizer69->Add( 0, 5, 0, 0, 5 ); + + m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP, 5 ); + + m_staticText531 = new wxStaticText( this, wxID_ANY, _("Configuration overview:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText531->Wrap( -1 ); + m_staticText531->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); + + bSizer69->Add( m_staticText531, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_notebookSettings = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_panelOverview = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer67; + bSizer67 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer120; + bSizer120 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer100; + bSizer100 = new wxBoxSizer( wxVERTICAL ); + + m_scrolledWindow6 = new wxScrolledWindow( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_scrolledWindow6->SetScrollRate( 5, 5 ); + wxBoxSizer* bSizer141; + bSizer141 = new wxBoxSizer( wxVERTICAL ); + + sbSizerMainPair = new wxBoxSizer( wxHORIZONTAL ); + + m_panelMainPair = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER ); + wxBoxSizer* bSizer147; + bSizer147 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer1361; + bSizer1361 = new wxBoxSizer( wxVERTICAL ); + + m_bpButtonAddPair = new wxBitmapButton( m_panelMainPair, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); + + m_bpButtonAddPair->SetToolTip( _("Add folder pair") ); + + bSizer1361->Add( m_bpButtonAddPair, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 3 ); + + bSizer147->Add( bSizer1361, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer143; + bSizer143 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer145; + bSizer145 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText532 = new wxStaticText( m_panelMainPair, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText532->Wrap( -1 ); + m_staticText532->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer145->Add( m_staticText532, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer143->Add( bSizer145, 1, 0, 5 ); + + wxBoxSizer* bSizer146; + bSizer146 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText5411 = new wxStaticText( m_panelMainPair, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText5411->Wrap( -1 ); + m_staticText5411->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer146->Add( m_staticText5411, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer143->Add( bSizer146, 1, 0, 5 ); + + bSizer147->Add( bSizer143, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + m_panelMainPair->SetSizer( bSizer147 ); + m_panelMainPair->Layout(); + bSizer147->Fit( m_panelMainPair ); + sbSizerMainPair->Add( m_panelMainPair, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer158; + bSizer158 = new wxBoxSizer( wxVERTICAL ); + + m_panelLeft = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1141; + bSizer1141 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryLeft = new wxTextCtrl( m_panelLeft, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1141->Add( m_directoryLeft, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLeft = new wxDirPickerCtrl( m_panelLeft, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLeft->SetToolTip( _("Select a folder") ); + + bSizer1141->Add( m_dirPickerLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelLeft->SetSizer( bSizer1141 ); + m_panelLeft->Layout(); + bSizer1141->Fit( m_panelLeft ); + bSizer158->Add( m_panelLeft, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_panelRight = new wxPanel( m_scrolledWindow6, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer115; + bSizer115 = new wxBoxSizer( wxHORIZONTAL ); + + m_directoryRight = new wxTextCtrl( m_panelRight, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer115->Add( m_directoryRight, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerRight = new wxDirPickerCtrl( m_panelRight, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerRight->SetToolTip( _("Select a folder") ); + + bSizer115->Add( m_dirPickerRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelRight->SetSizer( bSizer115 ); + m_panelRight->Layout(); + bSizer115->Fit( m_panelRight ); + bSizer158->Add( m_panelRight, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerMainPair->Add( bSizer158, 1, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 ); + + bSizer141->Add( sbSizerMainPair, 0, wxEXPAND, 5 ); + + bSizerAddFolderPairs = new wxBoxSizer( wxVERTICAL ); + + bSizer141->Add( bSizerAddFolderPairs, 0, wxEXPAND, 5 ); + + m_scrolledWindow6->SetSizer( bSizer141 ); + m_scrolledWindow6->Layout(); + bSizer141->Fit( m_scrolledWindow6 ); + bSizer100->Add( m_scrolledWindow6, 0, wxEXPAND, 5 ); + + + bSizer100->Add( 0, 10, 0, 0, 5 ); + + wxFlexGridSizer* fgSizer15; + fgSizer15 = new wxFlexGridSizer( 2, 2, 10, 10 ); + fgSizer15->SetFlexibleDirection( wxBOTH ); + fgSizer15->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + wxStaticBoxSizer* sbSizer6; + sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Compare by...") ), wxVERTICAL ); + + + sbSizer6->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_radioBtnSizeDate = new wxRadioButton( m_panelOverview, wxID_ANY, _("File size and date"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnSizeDate->SetValue( true ); + m_radioBtnSizeDate->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); + + sbSizer6->Add( m_radioBtnSizeDate, 0, 0, 5 ); + + m_radioBtnContent = new wxRadioButton( m_panelOverview, wxID_ANY, _("File content"), wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); + + sbSizer6->Add( m_radioBtnContent, 0, wxTOP, 5 ); + + + sbSizer6->Add( 0, 0, 1, wxEXPAND, 5 ); + + fgSizer15->Add( sbSizer6, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer24; + sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + + sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_checkBoxAutomatic = new wxCheckBox( m_panelOverview, wxID_ANY, _("Automatic mode"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxAutomatic->SetToolTip( _("Synchronize both sides using a database. Deletions are detected automatically.") ); + + sbSizer24->Add( m_checkBoxAutomatic, 0, wxALL, 5 ); + + m_checkBoxFilter = new wxCheckBox( m_panelOverview, wxID_ANY, _("Filter files"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxFilter->SetToolTip( _("Enable filter to exclude files from synchronization") ); + + sbSizer24->Add( m_checkBoxFilter, 0, wxALL, 5 ); + + m_checkBoxSilent = new wxCheckBox( m_panelOverview, wxID_ANY, _("Silent mode"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxSilent->SetToolTip( _("Do not display visual status information but write to a logfile instead") ); + + sbSizer24->Add( m_checkBoxSilent, 0, wxALL, 5 ); + + + sbSizer24->Add( 0, 0, 1, wxEXPAND, 5 ); + + fgSizer15->Add( sbSizer24, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + wxStaticBoxSizer* sbSizer25; + sbSizer25 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); + + wxArrayString m_choiceHandleErrorChoices; + m_choiceHandleError = new wxChoice( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleErrorChoices, 0 ); + m_choiceHandleError->SetSelection( 0 ); + sbSizer25->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + fgSizer15->Add( sbSizer25, 0, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer23; + sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Deletion handling") ), wxVERTICAL ); + + wxArrayString m_choiceHandleDeletionChoices; + m_choiceHandleDeletion = new wxChoice( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleDeletionChoices, 0 ); + m_choiceHandleDeletion->SetSelection( 0 ); + sbSizer23->Add( m_choiceHandleDeletion, 0, wxBOTTOM, 5 ); + + m_panelCustomDeletionDir = new wxPanel( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1151; + bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); + + m_textCtrlCustomDelFolder = new wxTextCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RIGHT ); + m_textCtrlCustomDelFolder->SetMinSize( wxSize( 160,-1 ) ); + + bSizer1151->Add( m_textCtrlCustomDelFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerCustomDelFolder = new wxDirPickerCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1151->Add( m_dirPickerCustomDelFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelCustomDeletionDir->SetSizer( bSizer1151 ); + m_panelCustomDeletionDir->Layout(); + bSizer1151->Fit( m_panelCustomDeletionDir ); + sbSizer23->Add( m_panelCustomDeletionDir, 0, 0, 5 ); + + fgSizer15->Add( sbSizer23, 0, wxEXPAND, 5 ); + + bSizer100->Add( fgSizer15, 0, 0, 5 ); + + bSizer120->Add( bSizer100, 1, 0, 5 ); + + + bSizer120->Add( 10, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerSyncDirections = new wxStaticBoxSizer( new wxStaticBox( m_panelOverview, wxID_ANY, _("Configuration") ), wxVERTICAL ); + + wxGridSizer* gSizer3; + gSizer3 = new wxGridSizer( 1, 2, 0, 5 ); + + m_staticText21 = new wxStaticText( m_panelOverview, wxID_ANY, _("Category"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText21->Wrap( -1 ); + m_staticText21->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + gSizer3->Add( m_staticText21, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText31 = new wxStaticText( m_panelOverview, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText31->Wrap( -1 ); + m_staticText31->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + gSizer3->Add( m_staticText31, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerSyncDirections->Add( gSizer3, 0, wxEXPAND, 5 ); + + m_staticline3 = new wxStaticLine( m_panelOverview, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sbSizerSyncDirections->Add( m_staticline3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer121; + bSizer121 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer122; + bSizer122 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeftOnly = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapLeftOnly->SetToolTip( _("Files/folders that exist on left side only") ); + + bSizer122->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer122->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonLeftOnly = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer122->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer122, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer123; + bSizer123 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapRightOnly = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapRightOnly->SetToolTip( _("Files/folders that exist on right side only") ); + + bSizer123->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer123->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonRightOnly = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer123->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer123, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer124; + bSizer124 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeftNewer = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapLeftNewer->SetToolTip( _("Files that exist on both sides, left one is newer") ); + + bSizer124->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer124->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonLeftNewer = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer124->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer124, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer125; + bSizer125 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapRightNewer = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapRightNewer->SetToolTip( _("Files that exist on both sides, right one is newer") ); + + bSizer125->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer125->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonRightNewer = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer125->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer125, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer126; + bSizer126 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapDifferent = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapDifferent->SetToolTip( _("Files that exist on both sides and have different content") ); + + bSizer126->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer126->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonDifferent = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer126->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer126, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer127; + bSizer127 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapConflict = new wxStaticBitmap( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapConflict->SetToolTip( _("Conflicts/files that cannot be categorized") ); + + bSizer127->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer127->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonConflict = new wxBitmapButton( m_panelOverview, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer127->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer127, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + sbSizerSyncDirections->Add( bSizer121, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer120->Add( sbSizerSyncDirections, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer67->Add( bSizer120, 1, wxALL, 10 ); + + m_panelOverview->SetSizer( bSizer67 ); + m_panelOverview->Layout(); + bSizer67->Fit( m_panelOverview ); + m_notebookSettings->AddPage( m_panelOverview, _("Overview"), true ); + m_panelFilter = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer114; + bSizer114 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer8; + sbSizer8 = new wxStaticBoxSizer( new wxStaticBox( m_panelFilter, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer3; + fgSizer3 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer3->AddGrowableCol( 1 ); + fgSizer3->AddGrowableRow( 1 ); + fgSizer3->SetFlexibleDirection( wxBOTH ); + fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText15 = new wxStaticText( m_panelFilter, wxID_ANY, _("Include"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15->Wrap( -1 ); + m_staticText15->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer3->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap8 = new wxStaticBitmap( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + m_bitmap8->SetToolTip( _("Include") ); + + fgSizer3->Add( m_bitmap8, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlInclude = new wxTextCtrl( m_panelFilter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); + fgSizer3->Add( m_textCtrlInclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer8->Add( fgSizer3, 1, wxEXPAND, 5 ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer4->AddGrowableCol( 1 ); + fgSizer4->AddGrowableRow( 1 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText16 = new wxStaticText( m_panelFilter, wxID_ANY, _("Exclude"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText16->Wrap( -1 ); + m_staticText16->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer4->Add( m_staticText16, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap9 = new wxStaticBitmap( m_panelFilter, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + m_bitmap9->SetToolTip( _("Exclude") ); + + fgSizer4->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlExclude = new wxTextCtrl( m_panelFilter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); + fgSizer4->Add( m_textCtrlExclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer8->Add( fgSizer4, 1, wxEXPAND, 5 ); + + bSizer114->Add( sbSizer8, 1, wxALL|wxEXPAND, 10 ); + + m_panelFilter->SetSizer( bSizer114 ); + m_panelFilter->Layout(); + bSizer114->Fit( m_panelFilter ); + m_notebookSettings->AddPage( m_panelFilter, _("Filter"), false ); + m_panelLogging = new wxPanel( m_notebookSettings, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer117; + bSizer117 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer119; + bSizer119 = new wxBoxSizer( wxVERTICAL ); + + m_staticText120 = new wxStaticText( m_panelLogging, wxID_ANY, _("Select logfile directory:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText120->Wrap( -1 ); + bSizer119->Add( m_staticText120, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxStaticBoxSizer* sbSizer251; + sbSizer251 = new wxStaticBoxSizer( new wxStaticBox( m_panelLogging, wxID_ANY, _("Drag && drop") ), wxHORIZONTAL ); + + m_textCtrlLogfileDir = new wxTextCtrl( m_panelLogging, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + sbSizer251->Add( m_textCtrlLogfileDir, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerLogfileDir = new wxDirPickerCtrl( m_panelLogging, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + m_dirPickerLogfileDir->SetToolTip( _("Select a folder") ); + + sbSizer251->Add( m_dirPickerLogfileDir, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer119->Add( sbSizer251, 1, wxEXPAND, 5 ); + + bSizer117->Add( bSizer119, 0, wxEXPAND|wxALL, 10 ); + + m_panelLogging->SetSizer( bSizer117 ); + m_panelLogging->Layout(); + bSizer117->Fit( m_panelLogging ); + m_notebookSettings->AddPage( m_panelLogging, _("Logging"), false ); + + bSizer69->Add( m_notebookSettings, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizer68; + bSizer68 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonSave = new wxButton( this, wxID_SAVE, _("&Save"), wxDefaultPosition, wxSize( 120,35 ), 0 ); + m_buttonSave->SetDefault(); + m_buttonSave->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer68->Add( m_buttonSave, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonLoad = new wxButton( this, wxID_OPEN, _("&Load"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonLoad->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer68->Add( m_buttonLoad, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button6->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer68->Add( m_button6, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer69->Add( bSizer68, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer54->Add( bSizer69, 1, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 5 ); + + this->SetSizer( bSizer54 ); + this->Layout(); + bSizer54->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::OnClose ) ); + m_bpButtonAddPair->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); + m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); + m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); + m_checkBoxAutomatic->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckAutomatic ), NULL, this ); + m_checkBoxFilter->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckFilter ), NULL, this ); + m_checkBoxSilent->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); + m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); + m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeDeletionHandling ), NULL, this ); + m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); + m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); + m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); + m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnConflict ), NULL, this ); + m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); + m_buttonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLoadBatchJob ), NULL, this ); + m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); } BatchDlgGenerated::~BatchDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::OnClose ) ); - m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); - m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); - m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); - m_checkBoxFilter->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckFilter ), NULL, this ); - m_checkBoxSilent->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckLogging ), NULL, this ); - m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); - m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeDeletionHandling ), NULL, this ); - m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExLeftSideOnly ), NULL, this ); - m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExRightSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); - m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); - m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); - m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnConflict ), NULL, this ); - m_buttonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); - m_buttonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLoadBatchJob ), NULL, this ); - m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( BatchDlgGenerated::OnClose ) ); + m_bpButtonAddPair->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnAddFolderPair ), NULL, this ); + m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); + m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeCompareVar ), NULL, this ); + m_checkBoxAutomatic->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckAutomatic ), NULL, this ); + m_checkBoxFilter->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckFilter ), NULL, this ); + m_checkBoxSilent->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCheckSilent ), NULL, this ); + m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeErrorHandling ), NULL, this ); + m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( BatchDlgGenerated::OnChangeDeletionHandling ), NULL, this ); + m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); + m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); + m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); + m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnConflict ), NULL, this ); + m_buttonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); + m_buttonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLoadBatchJob ), NULL, this ); + m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); } CompareStatusGenerated::CompareStatusGenerated( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style ) { - wxBoxSizer* bSizer40; - bSizer40 = new wxBoxSizer( wxVERTICAL ); - - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticBoxSizer* sbSizer10; - sbSizer10 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); - - wxBoxSizer* bSizer118; - bSizer118 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText321 = new wxStaticText( this, wxID_ANY, _("Files/folders scanned:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText321->Wrap( -1 ); - m_staticText321->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Arial") ) ); - - bSizer118->Add( m_staticText321, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 5 ); - - m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextScanned->Wrap( -1 ); - m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer118->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - sbSizer10->Add( bSizer118, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer42->Add( sbSizer10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - sbSizer13 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Comparing content") ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer12; - fgSizer12 = new wxFlexGridSizer( 2, 4, 3, 5 ); - fgSizer12->SetFlexibleDirection( wxBOTH ); - fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticText46 = new wxStaticText( this, wxID_ANY, _("Files remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText46->Wrap( -1 ); - m_staticText46->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextFilesRemaining->Wrap( -1 ); - m_staticTextFilesRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 ); - - m_staticText32 = new wxStaticText( this, wxID_ANY, _("Data remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText32->Wrap( -1 ); - m_staticText32->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticText32, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataRemaining->Wrap( -1 ); - m_staticTextDataRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 ); - - m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText104->Wrap( -1 ); - m_staticText104->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSpeed->Wrap( -1 ); - m_staticTextSpeed->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM, 5 ); - - m_staticText103 = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText103->Wrap( -1 ); - m_staticText103->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticText103, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemaining->Wrap( -1 ); - m_staticTextTimeRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer12->Add( m_staticTextTimeRemaining, 0, wxALIGN_BOTTOM, 5 ); - - sbSizer13->Add( fgSizer12, 1, wxEXPAND, 5 ); - - bSizer42->Add( sbSizer13, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer131; - sbSizer131 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); - - wxBoxSizer* bSizer117; - bSizer117 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText37->Wrap( -1 ); - m_staticText37->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Arial") ) ); - - bSizer117->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer117->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); - - sbSizer131->Add( bSizer117, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer42->Add( sbSizer131, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); - - wxBoxSizer* bSizer48; - bSizer48 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText30->Wrap( -1 ); - m_staticText30->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); - m_textCtrlStatus->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer40->Add( bSizer48, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); - bSizer40->Add( m_gauge2, 0, wxALL|wxEXPAND, 5 ); - - this->SetSizer( bSizer40 ); - this->Layout(); - bSizer40->Fit( this ); + wxBoxSizer* bSizer40; + bSizer40 = new wxBoxSizer( wxVERTICAL ); + + bSizer42 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbSizer10; + sbSizer10 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); + + wxBoxSizer* bSizer118; + bSizer118 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText321 = new wxStaticText( this, wxID_ANY, _("Files/folders found:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText321->Wrap( -1 ); + m_staticText321->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Arial") ) ); + + bSizer118->Add( m_staticText321, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_BOTTOM, 5 ); + + m_staticTextScanned = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextScanned->Wrap( -1 ); + m_staticTextScanned->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer118->Add( m_staticTextScanned, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); + + sbSizer10->Add( bSizer118, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer42->Add( sbSizer10, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + sbSizer13 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Comparing content") ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer12; + fgSizer12 = new wxFlexGridSizer( 2, 4, 3, 5 ); + fgSizer12->SetFlexibleDirection( wxBOTH ); + fgSizer12->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText46 = new wxStaticText( this, wxID_ANY, _("Files remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText46->Wrap( -1 ); + m_staticText46->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticText46, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextFilesRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextFilesRemaining->Wrap( -1 ); + m_staticTextFilesRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticTextFilesRemaining, 0, wxALIGN_BOTTOM, 5 ); + + m_staticText32 = new wxStaticText( this, wxID_ANY, _("Data remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText32->Wrap( -1 ); + m_staticText32->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticText32, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDataRemaining->Wrap( -1 ); + m_staticTextDataRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticTextDataRemaining, 0, wxALIGN_BOTTOM, 5 ); + + m_staticText104 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText104->Wrap( -1 ); + m_staticText104->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticText104, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSpeed->Wrap( -1 ); + m_staticTextSpeed->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticTextSpeed, 0, wxALIGN_BOTTOM, 5 ); + + m_staticText103 = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText103->Wrap( -1 ); + m_staticText103->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticText103, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextTimeRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeRemaining->Wrap( -1 ); + m_staticTextTimeRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer12->Add( m_staticTextTimeRemaining, 0, wxALIGN_BOTTOM, 5 ); + + sbSizer13->Add( fgSizer12, 1, wxEXPAND, 5 ); + + bSizer42->Add( sbSizer13, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer131; + sbSizer131 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxHORIZONTAL ); + + wxBoxSizer* bSizer117; + bSizer117 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText37 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText37->Wrap( -1 ); + m_staticText37->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Arial") ) ); + + bSizer117->Add( m_staticText37, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer117->Add( m_staticTextTimeElapsed, 0, wxALIGN_BOTTOM|wxLEFT, 5 ); + + sbSizer131->Add( bSizer117, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer42->Add( sbSizer131, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + bSizer40->Add( bSizer42, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); + + wxBoxSizer* bSizer48; + bSizer48 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText30 = new wxStaticText( this, wxID_ANY, _("Operation:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText30->Wrap( -1 ); + m_staticText30->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer48->Add( m_staticText30, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlStatus = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY ); + m_textCtrlStatus->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer48->Add( m_textCtrlStatus, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer40->Add( bSizer48, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_gauge2 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,14 ), wxGA_HORIZONTAL|wxGA_SMOOTH ); + bSizer40->Add( m_gauge2, 0, wxALL|wxEXPAND, 5 ); + + this->SetSizer( bSizer40 ); + this->Layout(); + bSizer40->Fit( this ); } CompareStatusGenerated::~CompareStatusGenerated() @@ -1734,2050 +1747,2063 @@ CompareStatusGenerated::~CompareStatusGenerated() SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer181; - bSizer181 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer29; - bSizer29 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer7; - sbSizer7 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - m_staticText1 = new wxStaticText( this, wxID_ANY, _("Select variant:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1->Wrap( -1 ); - m_staticText1->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - sbSizer7->Add( m_staticText1, 0, wxALL, 5 ); - - wxFlexGridSizer* fgSizer1; - fgSizer1 = new wxFlexGridSizer( 4, 3, 8, 5 ); - fgSizer1->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_radioBtn1 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtn1->SetValue( true ); - m_radioBtn1->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_radioBtn1, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonOneWay = new wxButton( this, wxID_ANY, _("Mirror ->>"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonOneWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_buttonOneWay, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticText8 = new wxStaticText( this, wxID_ANY, _("Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText8->Wrap( 300 ); - fgSizer1->Add( m_staticText8, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_radioBtnUpdate = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtnUpdate->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_radioBtnUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonUpdate = new wxButton( this, wxID_ANY, _("Update ->"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonUpdate->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_buttonUpdate, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticText101 = new wxStaticText( this, wxID_ANY, _("Copy new or updated files to right folder."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText101->Wrap( 300 ); - fgSizer1->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_radioBtn2 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtn2->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_radioBtn2, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonTwoWay = new wxButton( this, wxID_ANY, _("Two way <->"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_buttonTwoWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_buttonTwoWay, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText10 = new wxStaticText( this, wxID_ANY, _("Synchronize both sides simultaneously: Copy new or updated files in both directions."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText10->Wrap( 300 ); - fgSizer1->Add( m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - m_radioBtn3 = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtn3->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer1->Add( m_radioBtn3, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer65; - bSizer65 = new wxBoxSizer( wxVERTICAL ); - - - bSizer65->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText23 = new wxStaticText( this, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( -1,-1 ), wxALIGN_CENTRE|wxSTATIC_BORDER ); - m_staticText23->Wrap( -1 ); - m_staticText23->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer65->Add( m_staticText23, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - - bSizer65->Add( 0, 0, 1, wxEXPAND, 5 ); - - fgSizer1->Add( bSizer65, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticText9 = new wxStaticText( this, wxID_ANY, _("Configure your own synchronization rules."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText9->Wrap( 300 ); - fgSizer1->Add( m_staticText9, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - sbSizer7->Add( fgSizer1, 0, 0, 5 ); - - bSizer29->Add( sbSizer7, 0, wxEXPAND, 5 ); - - - bSizer29->Add( 0, 5, 1, 0, 5 ); - - bSizer201 = new wxBoxSizer( wxHORIZONTAL ); - - sbSizerErrorHandling = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); - - wxArrayString m_choiceHandleErrorChoices; - m_choiceHandleError = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleErrorChoices, 0 ); - m_choiceHandleError->SetSelection( 0 ); - sbSizerErrorHandling->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer201->Add( sbSizerErrorHandling, 0, wxEXPAND|wxRIGHT, 10 ); - - wxStaticBoxSizer* sbSizer231; - sbSizer231 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Deletion handling") ), wxVERTICAL ); - - wxArrayString m_choiceHandleDeletionChoices; - m_choiceHandleDeletion = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleDeletionChoices, 0 ); - m_choiceHandleDeletion->SetSelection( 0 ); - sbSizer231->Add( m_choiceHandleDeletion, 0, wxBOTTOM, 5 ); - - m_panelCustomDeletionDir = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer1151; - bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); - - m_textCtrlCustomDelFolder = new wxTextCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RIGHT ); - m_textCtrlCustomDelFolder->SetMinSize( wxSize( 160,-1 ) ); - - bSizer1151->Add( m_textCtrlCustomDelFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_dirPickerCustomDelFolder = new wxDirPickerCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer1151->Add( m_dirPickerCustomDelFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panelCustomDeletionDir->SetSizer( bSizer1151 ); - m_panelCustomDeletionDir->Layout(); - bSizer1151->Fit( m_panelCustomDeletionDir ); - sbSizer231->Add( m_panelCustomDeletionDir, 0, 0, 5 ); - - bSizer201->Add( sbSizer231, 0, wxEXPAND, 5 ); - - bSizer29->Add( bSizer201, 0, wxTOP|wxBOTTOM, 5 ); - - - bSizer29->Add( 0, 5, 1, 0, 5 ); - - wxBoxSizer* bSizer291; - bSizer291 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonApply = new wxButton( this, wxID_OK, _("&Apply"), wxDefaultPosition, wxSize( 120,35 ), 0 ); - m_buttonApply->SetDefault(); - m_buttonApply->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer291->Add( m_buttonApply, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer291->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer291->Add( 20, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer29->Add( bSizer291, 0, wxEXPAND, 5 ); - - bSizer181->Add( bSizer29, 0, wxEXPAND, 5 ); - - - bSizer181->Add( 10, 0, 0, 0, 5 ); - - wxStaticBoxSizer* sbSizer6; - sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Configuration") ), wxVERTICAL ); - - wxGridSizer* gSizer3; - gSizer3 = new wxGridSizer( 1, 2, 0, 5 ); - - m_staticText21 = new wxStaticText( this, wxID_ANY, _("Result"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText21->Wrap( -1 ); - m_staticText21->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - gSizer3->Add( m_staticText21, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText31 = new wxStaticText( this, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText31->Wrap( -1 ); - m_staticText31->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - gSizer3->Add( m_staticText31, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer6->Add( gSizer3, 0, wxEXPAND, 5 ); - - m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - sbSizer6->Add( m_staticline3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer121; - bSizer121 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer122; - bSizer122 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftOnly = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftOnly->SetToolTip( _("Files/folders that exist on left side only") ); - - bSizer122->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer122->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonLeftOnly = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer122->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer122, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer123; - bSizer123 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightOnly = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightOnly->SetToolTip( _("Files/folders that exist on right side only") ); - - bSizer123->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer123->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightOnly = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer123->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer123, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer124; - bSizer124 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeftNewer = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapLeftNewer->SetToolTip( _("Files that exist on both sides, left one is newer") ); - - bSizer124->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer124->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonLeftNewer = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer124->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer124, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer125; - bSizer125 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapRightNewer = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapRightNewer->SetToolTip( _("Files that exist on both sides, right one is newer") ); - - bSizer125->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer125->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonRightNewer = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer125->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer125, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer126; - bSizer126 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapDifferent = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapDifferent->SetToolTip( _("Files that exist on both sides and have different content") ); - - bSizer126->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer126->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonDifferent = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer126->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer126, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer127; - bSizer127 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapConflict = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); - m_bitmapConflict->SetToolTip( _("Conflicts/files that cannot be categorized") ); - - bSizer127->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer127->Add( 5, 0, 0, 0, 5 ); - - m_bpButtonConflict = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); - bSizer127->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer121->Add( bSizer127, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - sbSizer6->Add( bSizer121, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer181->Add( sbSizer6, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer7->Add( bSizer181, 0, wxALL, 5 ); - - this->SetSizer( bSizer7 ); - this->Layout(); - bSizer7->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); - m_radioBtn1->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); - m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); - m_radioBtnUpdate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); - m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); - m_radioBtn2->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); - m_buttonTwoWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); - m_radioBtn3->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCostum ), NULL, this ); - m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); - m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); - m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); - m_button16->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnCancel ), NULL, this ); - m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExLeftSideOnly ), NULL, this ); - m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExRightSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnLeftNewer ), NULL, this ); - m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnRightNewer ), NULL, this ); - m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDifferent ), NULL, this ); - m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnConflict ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer181; + bSizer181 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer29; + bSizer29 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer7; + sbSizer7 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + m_staticText1 = new wxStaticText( this, wxID_ANY, _("Select variant:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + m_staticText1->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + sbSizer7->Add( m_staticText1, 0, wxALL, 5 ); + + wxFlexGridSizer* fgSizer1; + fgSizer1 = new wxFlexGridSizer( 5, 3, 8, 5 ); + fgSizer1->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_radioBtnAutomatic = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnAutomatic->SetValue( true ); + m_radioBtnAutomatic->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtnAutomatic, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonAutomatic = new wxButton( this, wxID_ANY, _("<Automatic>"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonAutomatic->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonAutomatic, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticText81 = new wxStaticText( this, wxID_ANY, _("Synchronize both sides using a database. Deletions are detected automatically."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText81->Wrap( 300 ); + fgSizer1->Add( m_staticText81, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_radioBtnMirror = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnMirror->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtnMirror, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonOneWay = new wxButton( this, wxID_ANY, _("Mirror ->>"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonOneWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonOneWay, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticText8 = new wxStaticText( this, wxID_ANY, _("Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText8->Wrap( 300 ); + fgSizer1->Add( m_staticText8, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_radioBtnUpdate = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnUpdate->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtnUpdate, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonUpdate = new wxButton( this, wxID_ANY, _("Update ->"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonUpdate->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonUpdate, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticText101 = new wxStaticText( this, wxID_ANY, _("Copy new or updated files to right folder."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText101->Wrap( 300 ); + fgSizer1->Add( m_staticText101, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_radioBtnTwoWay = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnTwoWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_radioBtnTwoWay, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonTwoWay = new wxButton( this, wxID_ANY, _("Two way <->"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_buttonTwoWay->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer1->Add( m_buttonTwoWay, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText10 = new wxStaticText( this, wxID_ANY, _("Synchronize both sides simultaneously: Copy new or updated files in both directions."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText10->Wrap( 300 ); + fgSizer1->Add( m_staticText10, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + m_radioBtnCustom = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnCustom->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + m_radioBtnCustom->Enable( false ); + + fgSizer1->Add( m_radioBtnCustom, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer65; + bSizer65 = new wxBoxSizer( wxVERTICAL ); + + + bSizer65->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText23 = new wxStaticText( this, wxID_ANY, _("Custom"), wxDefaultPosition, wxSize( -1,-1 ), wxALIGN_CENTRE|wxSTATIC_BORDER ); + m_staticText23->Wrap( -1 ); + m_staticText23->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer65->Add( m_staticText23, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + + bSizer65->Add( 0, 0, 1, wxEXPAND, 5 ); + + fgSizer1->Add( bSizer65, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticText9 = new wxStaticText( this, wxID_ANY, _("Configure your own synchronization rules."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText9->Wrap( 300 ); + fgSizer1->Add( m_staticText9, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + sbSizer7->Add( fgSizer1, 0, 0, 5 ); + + bSizer29->Add( sbSizer7, 0, wxEXPAND, 5 ); + + + bSizer29->Add( 0, 5, 1, 0, 5 ); + + bSizer201 = new wxBoxSizer( wxHORIZONTAL ); + + sbSizerErrorHandling = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Error handling") ), wxHORIZONTAL ); + + wxArrayString m_choiceHandleErrorChoices; + m_choiceHandleError = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleErrorChoices, 0 ); + m_choiceHandleError->SetSelection( 0 ); + sbSizerErrorHandling->Add( m_choiceHandleError, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer201->Add( sbSizerErrorHandling, 0, wxEXPAND|wxRIGHT, 10 ); + + wxStaticBoxSizer* sbSizer231; + sbSizer231 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Deletion handling") ), wxVERTICAL ); + + wxArrayString m_choiceHandleDeletionChoices; + m_choiceHandleDeletion = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceHandleDeletionChoices, 0 ); + m_choiceHandleDeletion->SetSelection( 0 ); + sbSizer231->Add( m_choiceHandleDeletion, 0, wxBOTTOM, 5 ); + + m_panelCustomDeletionDir = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer1151; + bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); + + m_textCtrlCustomDelFolder = new wxTextCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_textCtrlCustomDelFolder->SetMinSize( wxSize( 160,-1 ) ); + + bSizer1151->Add( m_textCtrlCustomDelFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_dirPickerCustomDelFolder = new wxDirPickerCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1151->Add( m_dirPickerCustomDelFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panelCustomDeletionDir->SetSizer( bSizer1151 ); + m_panelCustomDeletionDir->Layout(); + bSizer1151->Fit( m_panelCustomDeletionDir ); + sbSizer231->Add( m_panelCustomDeletionDir, 0, 0, 5 ); + + bSizer201->Add( sbSizer231, 0, wxEXPAND, 5 ); + + bSizer29->Add( bSizer201, 0, wxTOP|wxBOTTOM, 5 ); + + + bSizer29->Add( 0, 5, 1, 0, 5 ); + + wxBoxSizer* bSizer291; + bSizer291 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonApply = new wxButton( this, wxID_OK, _("&Apply"), wxDefaultPosition, wxSize( 120,35 ), 0 ); + m_buttonApply->SetDefault(); + m_buttonApply->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer291->Add( m_buttonApply, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer291->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer291->Add( 20, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer29->Add( bSizer291, 0, wxEXPAND, 5 ); + + bSizer181->Add( bSizer29, 0, wxEXPAND, 5 ); + + + bSizer181->Add( 10, 0, 0, 0, 5 ); + + sbSizerSyncDirections = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Configuration") ), wxVERTICAL ); + + wxGridSizer* gSizer3; + gSizer3 = new wxGridSizer( 1, 2, 0, 5 ); + + m_staticText21 = new wxStaticText( this, wxID_ANY, _("Category"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText21->Wrap( -1 ); + m_staticText21->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + gSizer3->Add( m_staticText21, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText31 = new wxStaticText( this, wxID_ANY, _("Action"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText31->Wrap( -1 ); + m_staticText31->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + gSizer3->Add( m_staticText31, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizerSyncDirections->Add( gSizer3, 0, wxEXPAND, 5 ); + + m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sbSizerSyncDirections->Add( m_staticline3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer121; + bSizer121 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer122; + bSizer122 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeftOnly = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapLeftOnly->SetToolTip( _("Files/folders that exist on left side only") ); + + bSizer122->Add( m_bitmapLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer122->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonLeftOnly = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer122->Add( m_bpButtonLeftOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer122, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer123; + bSizer123 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapRightOnly = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapRightOnly->SetToolTip( _("Files/folders that exist on right side only") ); + + bSizer123->Add( m_bitmapRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer123->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonRightOnly = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer123->Add( m_bpButtonRightOnly, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer123, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer124; + bSizer124 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeftNewer = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapLeftNewer->SetToolTip( _("Files that exist on both sides, left one is newer") ); + + bSizer124->Add( m_bitmapLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer124->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonLeftNewer = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer124->Add( m_bpButtonLeftNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer124, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer125; + bSizer125 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapRightNewer = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapRightNewer->SetToolTip( _("Files that exist on both sides, right one is newer") ); + + bSizer125->Add( m_bitmapRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer125->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonRightNewer = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer125->Add( m_bpButtonRightNewer, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer125, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer126; + bSizer126 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapDifferent = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapDifferent->SetToolTip( _("Files that exist on both sides and have different content") ); + + bSizer126->Add( m_bitmapDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer126->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonDifferent = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer126->Add( m_bpButtonDifferent, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer126, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer127; + bSizer127 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapConflict = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 45,45 ), 0 ); + m_bitmapConflict->SetToolTip( _("Conflicts/files that cannot be categorized") ); + + bSizer127->Add( m_bitmapConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer127->Add( 5, 0, 0, 0, 5 ); + + m_bpButtonConflict = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 42,42 ), wxBU_AUTODRAW ); + bSizer127->Add( m_bpButtonConflict, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer121->Add( bSizer127, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + sbSizerSyncDirections->Add( bSizer121, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer181->Add( sbSizerSyncDirections, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer7->Add( bSizer181, 0, wxALL, 5 ); + + this->SetSizer( bSizer7 ); + this->Layout(); + bSizer7->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); + m_radioBtnAutomatic->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_radioBtnMirror->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); + m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); + m_radioBtnUpdate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_radioBtnTwoWay->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); + m_buttonTwoWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); + m_choiceHandleError->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); + m_choiceHandleDeletion->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); + m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); + m_button16->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnCancel ), NULL, this ); + m_bpButtonLeftOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButtonRightOnly->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButtonLeftNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnLeftNewer ), NULL, this ); + m_bpButtonRightNewer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnRightNewer ), NULL, this ); + m_bpButtonDifferent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDifferent ), NULL, this ); + m_bpButtonConflict->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnConflict ), NULL, this ); } SyncCfgDlgGenerated::~SyncCfgDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); - m_radioBtn1->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); - m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); - m_radioBtnUpdate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); - m_buttonUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); - m_radioBtn2->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); - m_buttonTwoWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); - m_radioBtn3->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncCostum ), NULL, this ); - m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); - m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); - m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); - m_button16->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnCancel ), NULL, this ); - m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExLeftSideOnly ), NULL, this ); - m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExRightSideOnly ), NULL, this ); - m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnLeftNewer ), NULL, this ); - m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnRightNewer ), NULL, this ); - m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDifferent ), NULL, this ); - m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnConflict ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncCfgDlgGenerated::OnClose ) ); + m_radioBtnAutomatic->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_buttonAutomatic->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncAutomatic ), NULL, this ); + m_radioBtnMirror->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); + m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncLeftToRight ), NULL, this ); + m_radioBtnUpdate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_buttonUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncUpdate ), NULL, this ); + m_radioBtnTwoWay->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); + m_buttonTwoWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnSyncBothSides ), NULL, this ); + m_choiceHandleError->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeErrorHandling ), NULL, this ); + m_choiceHandleDeletion->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( SyncCfgDlgGenerated::OnChangeDeletionHandling ), NULL, this ); + m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnApply ), NULL, this ); + m_button16->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnCancel ), NULL, this ); + m_bpButtonLeftOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExLeftSideOnly ), NULL, this ); + m_bpButtonRightOnly->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnExRightSideOnly ), NULL, this ); + m_bpButtonLeftNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnLeftNewer ), NULL, this ); + m_bpButtonRightNewer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnRightNewer ), NULL, this ); + m_bpButtonDifferent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnDifferent ), NULL, this ); + m_bpButtonConflict->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncCfgDlgGenerated::OnConflict ), NULL, this ); } CmpCfgDlgGenerated::CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer136; - bSizer136 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer55; - bSizer55 = new wxBoxSizer( wxVERTICAL ); - - wxStaticBoxSizer* sbSizer6; - sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Compare by...") ), wxHORIZONTAL ); - - wxFlexGridSizer* fgSizer16; - fgSizer16 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer16->SetFlexibleDirection( wxBOTH ); - fgSizer16->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_radioBtnSizeDate = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); - m_radioBtnSizeDate->SetValue( true ); - m_radioBtnSizeDate->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); - - fgSizer16->Add( m_radioBtnSizeDate, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonTimeSize = new wxButton( this, wxID_ANY, _("File size and date"), wxDefaultPosition, wxSize( -1,40 ), 0 ); - m_buttonTimeSize->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - m_buttonTimeSize->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); - - fgSizer16->Add( m_buttonTimeSize, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_radioBtnContent = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_radioBtnContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); - - fgSizer16->Add( m_radioBtnContent, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_buttonContent = new wxButton( this, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,40 ), 0 ); - m_buttonContent->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); - m_buttonContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); - - fgSizer16->Add( m_buttonContent, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer6->Add( fgSizer16, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - sbSizer6->Add( m_staticline14, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_bpButtonHelp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButtonHelp->SetToolTip( _("Help") ); - - m_bpButtonHelp->SetToolTip( _("Help") ); - - sbSizer6->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer55->Add( sbSizer6, 0, wxALIGN_CENTER_VERTICAL, 2 ); - - - bSizer55->Add( 0, 4, 0, 0, 5 ); - - m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button6->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer55->Add( m_button6, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer136->Add( bSizer55, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - this->SetSizer( bSizer136 ); - this->Layout(); - bSizer136->Fit( this ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); - m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); - m_buttonTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); - m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); - m_buttonContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); - m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); - m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer136; + bSizer136 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer55; + bSizer55 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer6; + sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Compare by...") ), wxHORIZONTAL ); + + wxFlexGridSizer* fgSizer16; + fgSizer16 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer16->SetFlexibleDirection( wxBOTH ); + fgSizer16->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_radioBtnSizeDate = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_radioBtnSizeDate->SetValue( true ); + m_radioBtnSizeDate->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); + + fgSizer16->Add( m_radioBtnSizeDate, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonTimeSize = new wxButton( this, wxID_ANY, _("File size and date"), wxDefaultPosition, wxSize( -1,40 ), 0 ); + m_buttonTimeSize->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + m_buttonTimeSize->SetToolTip( _("Files are found equal if\n - filesize\n - last write time and date\nare the same.") ); + + fgSizer16->Add( m_buttonTimeSize, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_radioBtnContent = new wxRadioButton( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_radioBtnContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); + + fgSizer16->Add( m_radioBtnContent, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_buttonContent = new wxButton( this, wxID_ANY, _("File content"), wxDefaultPosition, wxSize( -1,40 ), 0 ); + m_buttonContent->SetFont( wxFont( 11, 74, 90, 92, false, wxT("Tahoma") ) ); + m_buttonContent->SetToolTip( _("Files are found equal if\n - file content\nis the same.") ); + + fgSizer16->Add( m_buttonContent, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer6->Add( fgSizer16, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + sbSizer6->Add( m_staticline14, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_bpButtonHelp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButtonHelp->SetToolTip( _("Help") ); + + m_bpButtonHelp->SetToolTip( _("Help") ); + + sbSizer6->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer55->Add( sbSizer6, 0, wxALIGN_CENTER_VERTICAL, 2 ); + + + bSizer55->Add( 0, 4, 0, 0, 5 ); + + m_button6 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button6->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer55->Add( m_button6, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer136->Add( bSizer55, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + this->SetSizer( bSizer136 ); + this->Layout(); + bSizer136->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); + m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); + m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnCancel ), NULL, this ); } CmpCfgDlgGenerated::~CmpCfgDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); - m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); - m_buttonTimeSize->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); - m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); - m_buttonContent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); - m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); - m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CmpCfgDlgGenerated::OnClose ) ); + m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_buttonTimeSize->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnTimeSize ), NULL, this ); + m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_buttonContent->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnContent ), NULL, this ); + m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnShowHelp ), NULL, this ); + m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CmpCfgDlgGenerated::OnCancel ), NULL, this ); } SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer27; - bSizer27 = new wxBoxSizer( wxVERTICAL ); - - - bSizer27->Add( 0, 15, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer37; - bSizer37 = new wxBoxSizer( wxHORIZONTAL ); - - m_animationControl1 = new wxAnimationCtrl(this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 45,45 )); - bSizer37->Add( m_animationControl1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxVERTICAL ); - - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Synchronization status"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText56->Wrap( -1 ); - m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - m_panel8->SetSizer( bSizer72 ); - m_panel8->Layout(); - bSizer72->Fit( m_panel8 ); - bSizer37->Add( m_panel8, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - bSizer27->Add( bSizer37, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - wxBoxSizer* bSizer42; - bSizer42 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 28,28 ), 0 ); - bSizer42->Add( m_bitmapStatus, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextStatus->Wrap( -1 ); - m_staticTextStatus->SetFont( wxFont( 14, 74, 93, 90, false, wxT("Tahoma") ) ); - - bSizer42->Add( m_staticTextStatus, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - - bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer27->Add( bSizer42, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer31 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText21 = new wxStaticText( this, wxID_ANY, _("Current operation:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText21->Wrap( -1 ); - m_staticText21->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_staticText21, 0, wxALIGN_BOTTOM, 5 ); - - - bSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText55 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText55->Wrap( -1 ); - m_staticText55->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_staticText55, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeElapsed->Wrap( -1 ); - m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer31->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer27->Add( bSizer31, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_textCtrlInfo = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); - m_textCtrlInfo->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer27->Add( m_textCtrlInfo, 3, wxEXPAND|wxALL, 5 ); - - m_gauge1 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,20 ), wxGA_HORIZONTAL ); - bSizer27->Add( m_gauge1, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer28 = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer111; - bSizer111 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer113; - bSizer113 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText25 = new wxStaticText( this, wxID_ANY, _("Files/folders remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText25->Wrap( -1 ); - m_staticText25->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer113->Add( m_staticText25, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextRemainingObj = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); - m_staticTextRemainingObj->Wrap( -1 ); - m_staticTextRemainingObj->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer113->Add( m_staticTextRemainingObj, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer111->Add( bSizer113, 0, 0, 5 ); - - bSizerSpeed = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText108 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText108->Wrap( -1 ); - m_staticText108->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - bSizerSpeed->Add( m_staticText108, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextSpeed->Wrap( -1 ); - m_staticTextSpeed->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - bSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer111->Add( bSizerSpeed, 0, wxTOP, 5 ); - - bSizer28->Add( bSizer111, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer28->Add( 0, 0, 1, 0, 5 ); - - m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); - m_buttonOK->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - m_buttonOK->Hide(); - - bSizer28->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( 100,32 ), 0 ); - m_buttonPause->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer28->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( 100,32 ), 0 ); - m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer28->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - - bSizer28->Add( 0, 0, 1, 0, 5 ); - - wxBoxSizer* bSizer114; - bSizer114 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer116; - bSizer116 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText26 = new wxStaticText( this, wxID_ANY, _("Data remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText26->Wrap( -1 ); - m_staticText26->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer116->Add( m_staticText26, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextDataRemaining->Wrap( -1 ); - m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - bSizer116->Add( m_staticTextDataRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer114->Add( bSizer116, 0, wxALIGN_RIGHT, 5 ); - - bSizerRemTime = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText106 = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText106->Wrap( -1 ); - m_staticText106->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - bSizerRemTime->Add( m_staticText106, 0, wxALIGN_BOTTOM, 5 ); - - m_staticTextTimeRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextTimeRemaining->Wrap( -1 ); - m_staticTextTimeRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); - - bSizerRemTime->Add( m_staticTextTimeRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); - - bSizer114->Add( bSizerRemTime, 0, wxALIGN_RIGHT|wxTOP, 5 ); - - bSizer28->Add( bSizer114, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer27->Add( bSizer28, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); - - - bSizer27->Add( 0, 5, 0, wxEXPAND, 5 ); - - this->SetSizer( bSizer27 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusDlgGenerated::OnClose ) ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnOkay ), NULL, this ); - m_buttonPause->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnPause ), NULL, this ); - m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnAbort ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer27; + bSizer27 = new wxBoxSizer( wxVERTICAL ); + + + bSizer27->Add( 0, 15, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer37; + bSizer37 = new wxBoxSizer( wxHORIZONTAL ); + + m_animationControl1 = new wxAnimationCtrl(this, wxID_ANY, wxNullAnimation, wxDefaultPosition, wxSize( 45,45 )); + bSizer37->Add( m_animationControl1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxVERTICAL ); + + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Synchronization status"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56->Wrap( -1 ); + m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + m_panel8->SetSizer( bSizer72 ); + m_panel8->Layout(); + bSizer72->Fit( m_panel8 ); + bSizer37->Add( m_panel8, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + bSizer27->Add( bSizer37, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + wxBoxSizer* bSizer42; + bSizer42 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_bitmapStatus = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 28,28 ), 0 ); + bSizer42->Add( m_bitmapStatus, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextStatus = new wxStaticText( this, wxID_ANY, _("Synchronizing..."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextStatus->Wrap( -1 ); + m_staticTextStatus->SetFont( wxFont( 14, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer42->Add( m_staticTextStatus, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer42->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer27->Add( bSizer42, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer31 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText21 = new wxStaticText( this, wxID_ANY, _("Current operation:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText21->Wrap( -1 ); + m_staticText21->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText21, 0, wxALIGN_BOTTOM, 5 ); + + + bSizer31->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText55 = new wxStaticText( this, wxID_ANY, _("Time elapsed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText55->Wrap( -1 ); + m_staticText55->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText55, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextTimeElapsed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeElapsed->Wrap( -1 ); + m_staticTextTimeElapsed->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer31->Add( m_staticTextTimeElapsed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer27->Add( bSizer31, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_textCtrlInfo = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrlInfo->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer27->Add( m_textCtrlInfo, 3, wxEXPAND|wxALL, 5 ); + + m_gauge1 = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxSize( -1,20 ), wxGA_HORIZONTAL ); + bSizer27->Add( m_gauge1, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + bSizer28 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer111; + bSizer111 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer113; + bSizer113 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText25 = new wxStaticText( this, wxID_ANY, _("Files/folders remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText25->Wrap( -1 ); + m_staticText25->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer113->Add( m_staticText25, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextRemainingObj = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 ); + m_staticTextRemainingObj->Wrap( -1 ); + m_staticTextRemainingObj->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer113->Add( m_staticTextRemainingObj, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer111->Add( bSizer113, 0, 0, 5 ); + + bSizerSpeed = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText108 = new wxStaticText( this, wxID_ANY, _("Speed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText108->Wrap( -1 ); + m_staticText108->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + bSizerSpeed->Add( m_staticText108, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextSpeed = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextSpeed->Wrap( -1 ); + m_staticTextSpeed->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + bSizerSpeed->Add( m_staticTextSpeed, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer111->Add( bSizerSpeed, 0, wxTOP, 5 ); + + bSizer28->Add( bSizer111, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer28->Add( 0, 0, 1, 0, 5 ); + + m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonOK->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + m_buttonOK->Hide(); + + bSizer28->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonPause->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer28->Add( m_buttonPause, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer28->Add( m_buttonAbort, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer28->Add( 0, 0, 1, 0, 5 ); + + wxBoxSizer* bSizer114; + bSizer114 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer116; + bSizer116 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText26 = new wxStaticText( this, wxID_ANY, _("Data remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText26->Wrap( -1 ); + m_staticText26->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer116->Add( m_staticText26, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextDataRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextDataRemaining->Wrap( -1 ); + m_staticTextDataRemaining->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + bSizer116->Add( m_staticTextDataRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer114->Add( bSizer116, 0, wxALIGN_RIGHT, 5 ); + + bSizerRemTime = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText106 = new wxStaticText( this, wxID_ANY, _("Time remaining:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText106->Wrap( -1 ); + m_staticText106->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + bSizerRemTime->Add( m_staticText106, 0, wxALIGN_BOTTOM, 5 ); + + m_staticTextTimeRemaining = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextTimeRemaining->Wrap( -1 ); + m_staticTextTimeRemaining->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Arial") ) ); + + bSizerRemTime->Add( m_staticTextTimeRemaining, 0, wxLEFT|wxALIGN_BOTTOM, 5 ); + + bSizer114->Add( bSizerRemTime, 0, wxALIGN_RIGHT|wxTOP, 5 ); + + bSizer28->Add( bSizer114, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer27->Add( bSizer28, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxALL, 5 ); + + + bSizer27->Add( 0, 5, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer27 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusDlgGenerated::OnClose ) ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnOkay ), NULL, this ); + m_buttonPause->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnPause ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnAbort ), NULL, this ); } SyncStatusDlgGenerated::~SyncStatusDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusDlgGenerated::OnClose ) ); - m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnOkay ), NULL, this ); - m_buttonPause->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnPause ), NULL, this ); - m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnAbort ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncStatusDlgGenerated::OnClose ) ); + m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnOkay ), NULL, this ); + m_buttonPause->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnPause ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncStatusDlgGenerated::OnAbort ), NULL, this ); } HelpDlgGenerated::HelpDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer20; - bSizer20 = new wxBoxSizer( wxVERTICAL ); - - - bSizer20->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer85; - bSizer85 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap25 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer85->Add( m_bitmap25, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer72->Add( 20, 0, 0, 0, 5 ); - - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Help"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText56->Wrap( -1 ); - m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer72->Add( 20, 0, 0, 0, 5 ); - - m_panel8->SetSizer( bSizer72 ); - m_panel8->Layout(); - bSizer72->Fit( m_panel8 ); - bSizer85->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer85->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer20->Add( bSizer85, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_scrolledWindow1 = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxSIMPLE_BORDER|wxVSCROLL ); - m_scrolledWindow1->SetScrollRate( 5, 5 ); - m_scrolledWindow1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVEBORDER ) ); - - wxBoxSizer* bSizer70; - bSizer70 = new wxBoxSizer( wxVERTICAL ); - - m_staticText59 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("Compare by \"File size and date\""), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText59->Wrap( 500 ); - m_staticText59->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - - bSizer70->Add( m_staticText59, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticText60 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText60->Wrap( 500 ); - bSizer70->Add( m_staticText60, 0, wxALL, 5 ); - - m_staticText61 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("When the comparison is started with this option set the following decision tree is processed:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText61->Wrap( 500 ); - bSizer70->Add( m_staticText61, 0, wxALL, 5 ); - - m_treeCtrl1 = new wxTreeCtrl( m_scrolledWindow1, wxID_ANY, wxDefaultPosition, wxSize( -1,180 ), wxTR_DEFAULT_STYLE ); - m_treeCtrl1->SetBackgroundColour( wxColour( 237, 236, 235 ) ); - - bSizer70->Add( m_treeCtrl1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticText63 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("As a result the files are separated into the following categories:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText63->Wrap( 500 ); - bSizer70->Add( m_staticText63, 0, wxALL, 5 ); - - m_staticText75 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- equal"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText75->Wrap( -1 ); - bSizer70->Add( m_staticText75, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText76 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- left newer"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText76->Wrap( -1 ); - bSizer70->Add( m_staticText76, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText77 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- right newer"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText77->Wrap( -1 ); - bSizer70->Add( m_staticText77, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText79 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- exists left only"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText79->Wrap( -1 ); - bSizer70->Add( m_staticText79, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText80 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- exists right only"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText80->Wrap( -1 ); - bSizer70->Add( m_staticText80, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText78 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- conflict"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText78->Wrap( -1 ); - bSizer70->Add( m_staticText78, 0, wxRIGHT|wxLEFT, 5 ); - - m_scrolledWindow1->SetSizer( bSizer70 ); - m_scrolledWindow1->Layout(); - bSizer70->Fit( m_scrolledWindow1 ); - m_notebook1->AddPage( m_scrolledWindow1, _("File size and date"), true ); - m_scrolledWindow5 = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); - m_scrolledWindow5->SetScrollRate( 5, 5 ); - m_scrolledWindow5->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVEBORDER ) ); - - wxBoxSizer* bSizer74; - bSizer74 = new wxBoxSizer( wxVERTICAL ); - - m_staticText65 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("Compare by \"File content\""), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText65->Wrap( 500 ); - m_staticText65->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - - bSizer74->Add( m_staticText65, 0, wxALL, 5 ); - - m_staticText66 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText66->Wrap( 500 ); - bSizer74->Add( m_staticText66, 0, wxALL, 5 ); - - m_treeCtrl2 = new wxTreeCtrl( m_scrolledWindow5, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE ); - m_treeCtrl2->SetBackgroundColour( wxColour( 237, 236, 235 ) ); - m_treeCtrl2->SetMinSize( wxSize( -1,130 ) ); - - bSizer74->Add( m_treeCtrl2, 0, wxALL|wxEXPAND, 5 ); - - m_staticText69 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("As a result the files are separated into the following categories:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText69->Wrap( 500 ); - bSizer74->Add( m_staticText69, 0, wxALL, 5 ); - - m_staticText81 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- equal"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText81->Wrap( -1 ); - bSizer74->Add( m_staticText81, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText82 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- different"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText82->Wrap( -1 ); - bSizer74->Add( m_staticText82, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText83 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- exists left only"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText83->Wrap( -1 ); - bSizer74->Add( m_staticText83, 0, wxRIGHT|wxLEFT, 5 ); - - m_staticText84 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- exists right only"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText84->Wrap( -1 ); - bSizer74->Add( m_staticText84, 0, wxRIGHT|wxLEFT, 5 ); - - m_scrolledWindow5->SetSizer( bSizer74 ); - m_scrolledWindow5->Layout(); - bSizer74->Fit( m_scrolledWindow5 ); - m_notebook1->AddPage( m_scrolledWindow5, _("File content"), false ); - - bSizer20->Add( m_notebook1, 1, wxEXPAND | wxALL, 5 ); - - m_button8 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); - m_button8->SetDefault(); - m_button8->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer20->Add( m_button8, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer20 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); - m_button8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxVERTICAL ); + + + bSizer20->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer85; + bSizer85 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap25 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); + bSizer85->Add( m_bitmap25, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer72->Add( 20, 0, 0, 0, 5 ); + + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Help"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56->Wrap( -1 ); + m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer72->Add( 20, 0, 0, 0, 5 ); + + m_panel8->SetSizer( bSizer72 ); + m_panel8->Layout(); + bSizer72->Fit( m_panel8 ); + bSizer85->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer85->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer20->Add( bSizer85, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_scrolledWindow1 = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxSIMPLE_BORDER|wxVSCROLL ); + m_scrolledWindow1->SetScrollRate( 5, 5 ); + m_scrolledWindow1->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVEBORDER ) ); + + wxBoxSizer* bSizer70; + bSizer70 = new wxBoxSizer( wxVERTICAL ); + + m_staticText59 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("Compare by \"File size and date\""), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText59->Wrap( 500 ); + m_staticText59->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + + bSizer70->Add( m_staticText59, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticText60 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText60->Wrap( 500 ); + bSizer70->Add( m_staticText60, 0, wxALL, 5 ); + + m_staticText61 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("When the comparison is started with this option set the following decision tree is processed:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText61->Wrap( 500 ); + bSizer70->Add( m_staticText61, 0, wxALL, 5 ); + + m_treeCtrl1 = new wxTreeCtrl( m_scrolledWindow1, wxID_ANY, wxDefaultPosition, wxSize( -1,180 ), wxTR_DEFAULT_STYLE ); + m_treeCtrl1->SetBackgroundColour( wxColour( 237, 236, 235 ) ); + + bSizer70->Add( m_treeCtrl1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_staticText63 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("As a result the files are separated into the following categories:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText63->Wrap( 500 ); + bSizer70->Add( m_staticText63, 0, wxALL, 5 ); + + m_staticText75 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- equal"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText75->Wrap( -1 ); + bSizer70->Add( m_staticText75, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText76 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- left newer"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText76->Wrap( -1 ); + bSizer70->Add( m_staticText76, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText77 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- right newer"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText77->Wrap( -1 ); + bSizer70->Add( m_staticText77, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText79 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- exists left only"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText79->Wrap( -1 ); + bSizer70->Add( m_staticText79, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText80 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- exists right only"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText80->Wrap( -1 ); + bSizer70->Add( m_staticText80, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText78 = new wxStaticText( m_scrolledWindow1, wxID_ANY, _("- conflict"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText78->Wrap( -1 ); + bSizer70->Add( m_staticText78, 0, wxRIGHT|wxLEFT, 5 ); + + m_scrolledWindow1->SetSizer( bSizer70 ); + m_scrolledWindow1->Layout(); + bSizer70->Fit( m_scrolledWindow1 ); + m_notebook1->AddPage( m_scrolledWindow1, _("File size and date"), true ); + m_scrolledWindow5 = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_scrolledWindow5->SetScrollRate( 5, 5 ); + m_scrolledWindow5->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVEBORDER ) ); + + wxBoxSizer* bSizer74; + bSizer74 = new wxBoxSizer( wxVERTICAL ); + + m_staticText65 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("Compare by \"File content\""), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText65->Wrap( 500 ); + m_staticText65->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + + bSizer74->Add( m_staticText65, 0, wxALL, 5 ); + + m_staticText66 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText66->Wrap( 500 ); + bSizer74->Add( m_staticText66, 0, wxALL, 5 ); + + m_treeCtrl2 = new wxTreeCtrl( m_scrolledWindow5, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_DEFAULT_STYLE ); + m_treeCtrl2->SetBackgroundColour( wxColour( 237, 236, 235 ) ); + m_treeCtrl2->SetMinSize( wxSize( -1,130 ) ); + + bSizer74->Add( m_treeCtrl2, 0, wxALL|wxEXPAND, 5 ); + + m_staticText69 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("As a result the files are separated into the following categories:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText69->Wrap( 500 ); + bSizer74->Add( m_staticText69, 0, wxALL, 5 ); + + m_staticText81 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- equal"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText81->Wrap( -1 ); + bSizer74->Add( m_staticText81, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText82 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- different"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText82->Wrap( -1 ); + bSizer74->Add( m_staticText82, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText83 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- exists left only"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText83->Wrap( -1 ); + bSizer74->Add( m_staticText83, 0, wxRIGHT|wxLEFT, 5 ); + + m_staticText84 = new wxStaticText( m_scrolledWindow5, wxID_ANY, _("- exists right only"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText84->Wrap( -1 ); + bSizer74->Add( m_staticText84, 0, wxRIGHT|wxLEFT, 5 ); + + m_scrolledWindow5->SetSizer( bSizer74 ); + m_scrolledWindow5->Layout(); + bSizer74->Fit( m_scrolledWindow5 ); + m_notebook1->AddPage( m_scrolledWindow5, _("File content"), false ); + + bSizer20->Add( m_notebook1, 1, wxEXPAND | wxALL, 5 ); + + m_button8 = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_button8->SetDefault(); + m_button8->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer20->Add( m_button8, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer20 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); + m_button8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); } HelpDlgGenerated::~HelpDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); - m_button8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( HelpDlgGenerated::OnClose ) ); + m_button8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( HelpDlgGenerated::OnOK ), NULL, this ); } AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer31; - bSizer31 = new wxBoxSizer( wxVERTICAL ); - - - bSizer31->Add( 0, 5, 0, 0, 5 ); - - m_panel5 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel5->SetBackgroundColour( wxColour( 255, 255, 255 ) ); - - wxBoxSizer* bSizer36; - bSizer36 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap11 = new wxStaticBitmap( m_panel5, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 404,55 ), 0 ); - bSizer36->Add( m_bitmap11, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel5->SetSizer( bSizer36 ); - m_panel5->Layout(); - bSizer36->Fit( m_panel5 ); - bSizer31->Add( m_panel5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticText15 = new wxStaticText( this, wxID_ANY, _("-Open-Source file synchronization-"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText15->Wrap( -1 ); - m_staticText15->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_staticText15, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - m_build = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_build->Wrap( -1 ); - m_build->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_build, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer31->Add( 0, 10, 0, 0, 5 ); - - wxBoxSizer* bSizer53; - bSizer53 = new wxBoxSizer( wxVERTICAL ); - - m_scrolledWindowCodeInfo = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL ); - m_scrolledWindowCodeInfo->SetScrollRate( 5, 5 ); - m_scrolledWindowCodeInfo->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - m_scrolledWindowCodeInfo->SetMinSize( wxSize( -1,125 ) ); - - bSizerCodeInfo = new wxBoxSizer( wxVERTICAL ); - - m_staticText72 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _("Source code written completely in C++ utilizing:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText72->Wrap( -1 ); - m_staticText72->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizerCodeInfo->Add( m_staticText72, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); - - m_staticText73 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _(" MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText73->Wrap( -1 ); - bSizerCodeInfo->Add( m_staticText73, 0, wxALL|wxEXPAND, 5 ); - - m_staticText74 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _("- ZenJu -"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText74->Wrap( -1 ); - m_staticText74->SetFont( wxFont( 10, 74, 93, 90, false, wxT("Tahoma") ) ); - - bSizerCodeInfo->Add( m_staticText74, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_scrolledWindowCodeInfo->SetSizer( bSizerCodeInfo ); - m_scrolledWindowCodeInfo->Layout(); - bSizerCodeInfo->Fit( m_scrolledWindowCodeInfo ); - bSizer53->Add( m_scrolledWindowCodeInfo, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 10 ); - - m_scrolledWindowTranslators = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL ); - m_scrolledWindowTranslators->SetScrollRate( 5, 5 ); - m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - m_scrolledWindowTranslators->SetMinSize( wxSize( -1,140 ) ); - m_scrolledWindowTranslators->SetMaxSize( wxSize( -1,140 ) ); - - bSizerTranslators = new wxBoxSizer( wxVERTICAL ); - - m_staticText54 = new wxStaticText( m_scrolledWindowTranslators, wxID_ANY, _("Big thanks for localizing FreeFileSync goes out to:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText54->Wrap( -1 ); - m_staticText54->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizerTranslators->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); - - - bSizerTranslators->Add( 0, 5, 0, 0, 5 ); - - fgSizerTranslators = new wxFlexGridSizer( 1, 3, 5, 20 ); - fgSizerTranslators->SetFlexibleDirection( wxBOTH ); - fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - bSizerTranslators->Add( fgSizerTranslators, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_scrolledWindowTranslators->SetSizer( bSizerTranslators ); - m_scrolledWindowTranslators->Layout(); - bSizerTranslators->Fit( m_scrolledWindowTranslators ); - bSizer53->Add( m_scrolledWindowTranslators, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 5 ); - - bSizer31->Add( bSizer53, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 25 ); - - m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer31->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - m_staticText131 = new wxStaticText( this, wxID_ANY, _("Feedback and suggestions are welcome at:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText131->Wrap( -1 ); - m_staticText131->SetFont( wxFont( 11, 74, 93, 92, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_staticText131, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer31->Add( m_staticline12, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer104; - bSizer104 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer103; - bSizer103 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); - m_bitmap9->SetToolTip( _("FreeFileSync at Sourceforge") ); - - bSizer103->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink1 = new wxHyperlinkCtrl( this, wxID_ANY, _("Homepage"), wxT("http://sourceforge.net/projects/freefilesync/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink1->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - m_hyperlink1->SetToolTip( _("http://sourceforge.net/projects/freefilesync/") ); - - bSizer103->Add( m_hyperlink1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer103->Add( 20, 0, 1, wxEXPAND, 5 ); - - m_hyperlink6 = new wxHyperlinkCtrl( this, wxID_ANY, _("Report translation error"), wxT("http://sourceforge.net/forum/forum.php?forum_id=976976"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink6->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - m_hyperlink6->SetToolTip( _("https://sourceforge.net/forum/forum.php?forum_id=976976") ); - - bSizer103->Add( m_hyperlink6, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - bSizer104->Add( bSizer103, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer108; - bSizer108 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); - m_bitmap10->SetToolTip( _("Email") ); - - bSizer108->Add( m_bitmap10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink2 = new wxHyperlinkCtrl( this, wxID_ANY, _("Email"), wxT("mailto:zhnmju123@gmx.de"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink2->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - m_hyperlink2->SetToolTip( _("zhnmju123@gmx.de") ); - - bSizer108->Add( m_hyperlink2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer108->Add( 30, 0, 1, wxEXPAND, 5 ); - - m_animationControl1 = new wxAnimationCtrl(this, wxID_ANY, wxNullAnimation); - m_animationControl1->SetToolTip( _("Donate with PayPal") ); - - bSizer108->Add( m_animationControl1, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_hyperlink3 = new wxHyperlinkCtrl( this, wxID_ANY, _("If you like FFS"), wxT("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=zhnmju123%40gmx%2ede&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=EN&bn=PP%2dDonationsBF&charset=UTF%2d8"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - m_hyperlink3->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - m_hyperlink3->SetToolTip( _("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=zhnmju123%40gmx%2ede&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=EN&bn=PP%2dDonationsBF&charset=UTF%2d8") ); - - bSizer108->Add( m_hyperlink3, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - bSizer104->Add( bSizer108, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - bSizer31->Add( bSizer104, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer31->Add( m_staticline2, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxStaticBoxSizer* sbSizer14; - sbSizer14 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Published under the GNU General Public License:") ), wxHORIZONTAL ); - - - sbSizer14->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmap13 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 88,31 ), 0 ); - sbSizer14->Add( m_bitmap13, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_hyperlink5 = new wxHyperlinkCtrl( this, wxID_ANY, _("http://www.gnu.org/licenses/gpl.html"), wxT("http://www.gnu.org/licenses/gpl.html"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - sbSizer14->Add( m_hyperlink5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - sbSizer14->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer31->Add( sbSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - m_buttonOkay = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_buttonOkay, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - this->SetSizer( bSizer31 ); - this->Layout(); - bSizer31->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer31; + bSizer31 = new wxBoxSizer( wxVERTICAL ); + + + bSizer31->Add( 0, 5, 0, 0, 5 ); + + m_panel5 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel5->SetBackgroundColour( wxColour( 255, 255, 255 ) ); + + wxBoxSizer* bSizer36; + bSizer36 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap11 = new wxStaticBitmap( m_panel5, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 404,55 ), 0 ); + bSizer36->Add( m_bitmap11, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel5->SetSizer( bSizer36 ); + m_panel5->Layout(); + bSizer36->Fit( m_panel5 ); + bSizer31->Add( m_panel5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticText15 = new wxStaticText( this, wxID_ANY, _("-Open-Source file synchronization-"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15->Wrap( -1 ); + m_staticText15->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText15, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_build = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_build->Wrap( -1 ); + m_build->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_build, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer31->Add( 0, 10, 0, 0, 5 ); + + wxBoxSizer* bSizer53; + bSizer53 = new wxBoxSizer( wxVERTICAL ); + + m_scrolledWindowCodeInfo = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL ); + m_scrolledWindowCodeInfo->SetScrollRate( 5, 5 ); + m_scrolledWindowCodeInfo->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + m_scrolledWindowCodeInfo->SetMinSize( wxSize( -1,125 ) ); + + bSizerCodeInfo = new wxBoxSizer( wxVERTICAL ); + + m_staticText72 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _("Source code written completely in C++ utilizing:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText72->Wrap( -1 ); + m_staticText72->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizerCodeInfo->Add( m_staticText72, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); + + m_staticText73 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _(" MinGW \t- Windows port of GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText73->Wrap( -1 ); + bSizerCodeInfo->Add( m_staticText73, 0, wxALL|wxEXPAND, 5 ); + + m_staticText74 = new wxStaticText( m_scrolledWindowCodeInfo, wxID_ANY, _("- ZenJu -"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText74->Wrap( -1 ); + m_staticText74->SetFont( wxFont( 10, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizerCodeInfo->Add( m_staticText74, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_scrolledWindowCodeInfo->SetSizer( bSizerCodeInfo ); + m_scrolledWindowCodeInfo->Layout(); + bSizerCodeInfo->Fit( m_scrolledWindowCodeInfo ); + bSizer53->Add( m_scrolledWindowCodeInfo, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 10 ); + + m_scrolledWindowTranslators = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxDOUBLE_BORDER|wxHSCROLL|wxVSCROLL ); + m_scrolledWindowTranslators->SetScrollRate( 5, 5 ); + m_scrolledWindowTranslators->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + m_scrolledWindowTranslators->SetMinSize( wxSize( -1,140 ) ); + m_scrolledWindowTranslators->SetMaxSize( wxSize( -1,140 ) ); + + bSizerTranslators = new wxBoxSizer( wxVERTICAL ); + + m_staticText54 = new wxStaticText( m_scrolledWindowTranslators, wxID_ANY, _("Big thanks for localizing FreeFileSync goes out to:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText54->Wrap( -1 ); + m_staticText54->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizerTranslators->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); + + + bSizerTranslators->Add( 0, 5, 0, 0, 5 ); + + fgSizerTranslators = new wxFlexGridSizer( 1, 3, 5, 20 ); + fgSizerTranslators->SetFlexibleDirection( wxBOTH ); + fgSizerTranslators->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + bSizerTranslators->Add( fgSizerTranslators, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_scrolledWindowTranslators->SetSizer( bSizerTranslators ); + m_scrolledWindowTranslators->Layout(); + bSizerTranslators->Fit( m_scrolledWindowTranslators ); + bSizer53->Add( m_scrolledWindowTranslators, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 5 ); + + bSizer31->Add( bSizer53, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 25 ); + + m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer31->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + m_staticText131 = new wxStaticText( this, wxID_ANY, _("Feedback and suggestions are welcome at:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText131->Wrap( -1 ); + m_staticText131->SetFont( wxFont( 11, 74, 93, 92, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_staticText131, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer31->Add( m_staticline12, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer104; + bSizer104 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer103; + bSizer103 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap9->SetToolTip( _("FreeFileSync at Sourceforge") ); + + bSizer103->Add( m_bitmap9, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink1 = new wxHyperlinkCtrl( this, wxID_ANY, _("Homepage"), wxT("http://sourceforge.net/projects/freefilesync/"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink1->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + m_hyperlink1->SetToolTip( _("http://sourceforge.net/projects/freefilesync/") ); + + bSizer103->Add( m_hyperlink1, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer103->Add( 20, 0, 1, wxEXPAND, 5 ); + + m_hyperlink6 = new wxHyperlinkCtrl( this, wxID_ANY, _("Report translation error"), wxT("http://sourceforge.net/forum/forum.php?forum_id=976976"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink6->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + m_hyperlink6->SetToolTip( _("https://sourceforge.net/forum/forum.php?forum_id=976976") ); + + bSizer103->Add( m_hyperlink6, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + bSizer104->Add( bSizer103, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer108; + bSizer108 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + m_bitmap10->SetToolTip( _("Email") ); + + bSizer108->Add( m_bitmap10, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink2 = new wxHyperlinkCtrl( this, wxID_ANY, _("Email"), wxT("mailto:zhnmju123@gmx.de"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink2->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + m_hyperlink2->SetToolTip( _("zhnmju123@gmx.de") ); + + bSizer108->Add( m_hyperlink2, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer108->Add( 30, 0, 1, wxEXPAND, 5 ); + + m_animationControl1 = new wxAnimationCtrl(this, wxID_ANY, wxNullAnimation); + m_animationControl1->SetToolTip( _("Donate with PayPal") ); + + bSizer108->Add( m_animationControl1, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_hyperlink3 = new wxHyperlinkCtrl( this, wxID_ANY, _("If you like FFS"), wxT("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=zhnmju123%40gmx%2ede&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=EN&bn=PP%2dDonationsBF&charset=UTF%2d8"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_hyperlink3->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + m_hyperlink3->SetToolTip( _("https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=zhnmju123%40gmx%2ede&no_shipping=0&no_note=1&tax=0¤cy_code=EUR&lc=EN&bn=PP%2dDonationsBF&charset=UTF%2d8") ); + + bSizer108->Add( m_hyperlink3, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + bSizer104->Add( bSizer108, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + bSizer31->Add( bSizer104, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer31->Add( m_staticline2, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxStaticBoxSizer* sbSizer14; + sbSizer14 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Published under the GNU General Public License:") ), wxHORIZONTAL ); + + + sbSizer14->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmap13 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 88,31 ), 0 ); + sbSizer14->Add( m_bitmap13, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_hyperlink5 = new wxHyperlinkCtrl( this, wxID_ANY, _("http://www.gnu.org/licenses/gpl.html"), wxT("http://www.gnu.org/licenses/gpl.html"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); + sbSizer14->Add( m_hyperlink5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + sbSizer14->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer31->Add( sbSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + m_buttonOkay = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer31->Add( m_buttonOkay, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + this->SetSizer( bSizer31 ); + this->Layout(); + bSizer31->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); } AboutDlgGenerated::~AboutDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); - m_buttonOkay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( AboutDlgGenerated::OnClose ) ); + m_buttonOkay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AboutDlgGenerated::OnOK ), NULL, this ); } ErrorDlgGenerated::ErrorDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer26; - bSizer26 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); - bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); - m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 5 ); - - m_checkBoxIgnoreErrors = new wxCheckBox( this, wxID_ANY, _("Ignore subsequent errors"), wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxIgnoreErrors->SetToolTip( _("Hide further error messages during the current process") ); - - bSizer24->Add( m_checkBoxIgnoreErrors, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer25; - bSizer25 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonIgnore = new wxButton( this, wxID_OK, _("&Ignore"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonIgnore->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonIgnore, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonRetry = new wxButton( this, wxID_RETRY, _("&Retry"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonRetry->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonRetry, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonAbort, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - - bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer24 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); - m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnIgnore ), NULL, this ); - m_buttonRetry->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); - m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + + bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer26; + bSizer26 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_checkBoxIgnoreErrors = new wxCheckBox( this, wxID_ANY, _("Ignore subsequent errors"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxIgnoreErrors->SetToolTip( _("Hide further error messages during the current process") ); + + bSizer24->Add( m_checkBoxIgnoreErrors, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 10 ); + + + bSizer24->Add( 0, 5, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonIgnore = new wxButton( this, wxID_OK, _("&Ignore"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonIgnore->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonIgnore, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonRetry = new wxButton( this, wxID_RETRY, _("&Retry"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonRetry->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonRetry, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonAbort, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + + bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer24 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); + m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnIgnore ), NULL, this ); + m_buttonRetry->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); } ErrorDlgGenerated::~ErrorDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); - m_buttonIgnore->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnIgnore ), NULL, this ); - m_buttonRetry->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); - m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ErrorDlgGenerated::OnClose ) ); + m_buttonIgnore->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnIgnore ), NULL, this ); + m_buttonRetry->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnRetry ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ErrorDlgGenerated::OnAbort ), NULL, this ); } WarningDlgGenerated::WarningDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer26; - bSizer26 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); - bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); - m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer24->Add( m_checkBoxDontShowAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer25; - bSizer25 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonIgnore = new wxButton( this, wxID_IGNORE, _("&Ignore"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonIgnore->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonIgnore, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonAbort, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - - bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer24 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarningDlgGenerated::OnClose ) ); - m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnIgnore ), NULL, this ); - m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnAbort ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + + bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer26; + bSizer26 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer24->Add( m_checkBoxDontShowAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 10 ); + + + bSizer24->Add( 0, 5, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonIgnore = new wxButton( this, wxID_IGNORE, _("&Ignore"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonIgnore->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonIgnore, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonAbort = new wxButton( this, wxID_CANCEL, _("&Abort"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonAbort->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonAbort, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + + bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer24 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarningDlgGenerated::OnClose ) ); + m_buttonIgnore->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnIgnore ), NULL, this ); + m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnAbort ), NULL, this ); } WarningDlgGenerated::~WarningDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarningDlgGenerated::OnClose ) ); - m_buttonIgnore->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnIgnore ), NULL, this ); - m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnAbort ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( WarningDlgGenerated::OnClose ) ); + m_buttonIgnore->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnIgnore ), NULL, this ); + m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( WarningDlgGenerated::OnAbort ), NULL, this ); } QuestionDlgGenerated::QuestionDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer26; - bSizer26 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); - bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); - m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxBOTTOM, 5 ); - - m_checkBoxDontAskAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer24->Add( m_checkBoxDontAskAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer25; - bSizer25 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonYes = new wxButton( this, wxID_YES, _("&Yes"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonYes->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonYes, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonNo = new wxButton( this, wxID_NO, _("&No"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonNo->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonNo, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonCancel->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonCancel, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - - bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer24 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( QuestionDlgGenerated::OnClose ) ); - m_buttonYes->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnYes ), NULL, this ); - m_buttonNo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnNo ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + + bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer26; + bSizer26 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap10 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 48,48 ), 0 ); + bSizer26->Add( m_bitmap10, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrl8 = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrl8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer26->Add( m_textCtrl8, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + bSizer24->Add( bSizer26, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_checkBoxDontAskAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer24->Add( m_checkBoxDontAskAgain, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP, 10 ); + + + bSizer24->Add( 0, 5, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonYes = new wxButton( this, wxID_YES, _("&Yes"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonYes->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonYes, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonNo = new wxButton( this, wxID_NO, _("&No"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonNo->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonNo, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonCancel->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonCancel, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + + bSizer25->Add( 5, 0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer24 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( QuestionDlgGenerated::OnClose ) ); + m_buttonYes->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnYes ), NULL, this ); + m_buttonNo->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnNo ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnCancel ), NULL, this ); } QuestionDlgGenerated::~QuestionDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( QuestionDlgGenerated::OnClose ) ); - m_buttonYes->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnYes ), NULL, this ); - m_buttonNo->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnNo ), NULL, this ); - m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( QuestionDlgGenerated::OnClose ) ); + m_buttonYes->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnYes ), NULL, this ); + m_buttonNo->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnNo ), NULL, this ); + m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( QuestionDlgGenerated::OnCancel ), NULL, this ); } DeleteDlgGenerated::DeleteDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer24; - bSizer24 = new wxBoxSizer( wxVERTICAL ); - - - bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer41; - bSizer41 = new wxBoxSizer( wxHORIZONTAL ); - - - bSizer41->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_bitmap12 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer41->Add( m_bitmap12, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( -1 ); - m_staticTextHeader->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer41->Add( m_staticTextHeader, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer41->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer24->Add( bSizer41, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer99; - bSizer99 = new wxBoxSizer( wxHORIZONTAL ); - - m_checkBoxDeleteBothSides = new wxCheckBox( this, wxID_ANY, _("Delete on both sides"), wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxDeleteBothSides->SetToolTip( _("Delete on both sides even if the file is selected on one side only") ); - - bSizer99->Add( m_checkBoxDeleteBothSides, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer99->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); - - m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("Use Recycle Bin"), wxDefaultPosition, wxDefaultSize, 0 ); - m_checkBoxUseRecycler->SetValue(true); - - bSizer99->Add( m_checkBoxUseRecycler, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer24->Add( bSizer99, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); - - m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); - m_textCtrlMessage->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); - - bSizer24->Add( m_textCtrlMessage, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer25; - bSizer25 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOK->SetDefault(); - m_buttonOK->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonOK, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); - - m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonCancel->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer25->Add( m_buttonCancel, 0, wxALL, 5 ); - - bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer24 ); - this->Layout(); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) ); - m_checkBoxDeleteBothSides->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnDelOnBothSides ), NULL, this ); - m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this ); - m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnOK ), NULL, this ); - m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer24; + bSizer24 = new wxBoxSizer( wxVERTICAL ); + + + bSizer24->Add( 0, 10, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer41; + bSizer41 = new wxBoxSizer( wxHORIZONTAL ); + + + bSizer41->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_bitmap12 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); + bSizer41->Add( m_bitmap12, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextHeader->Wrap( -1 ); + m_staticTextHeader->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer41->Add( m_staticTextHeader, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer41->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer24->Add( bSizer41, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer99; + bSizer99 = new wxBoxSizer( wxHORIZONTAL ); + + m_checkBoxDeleteBothSides = new wxCheckBox( this, wxID_ANY, _("Delete on both sides"), wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxDeleteBothSides->SetToolTip( _("Delete on both sides even if the file is selected on one side only") ); + + bSizer99->Add( m_checkBoxDeleteBothSides, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer99->Add( 0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); + + m_checkBoxUseRecycler = new wxCheckBox( this, wxID_ANY, _("Use Recycle Bin"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxUseRecycler->SetValue(true); + + bSizer99->Add( m_checkBoxUseRecycler, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer24->Add( bSizer99, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); + + m_textCtrlMessage = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE|wxTE_READONLY ); + m_textCtrlMessage->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ) ); + + bSizer24->Add( m_textCtrlMessage, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer25; + bSizer25 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonOK->SetDefault(); + m_buttonOK->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonOK, 0, wxTOP|wxBOTTOM|wxLEFT, 5 ); + + m_buttonCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonCancel->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer25->Add( m_buttonCancel, 0, wxALL, 5 ); + + bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer24 ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) ); + m_checkBoxDeleteBothSides->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnDelOnBothSides ), NULL, this ); + m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this ); + m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnOK ), NULL, this ); + m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnCancel ), NULL, this ); } DeleteDlgGenerated::~DeleteDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) ); - m_checkBoxDeleteBothSides->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnDelOnBothSides ), NULL, this ); - m_checkBoxUseRecycler->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this ); - m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnOK ), NULL, this ); - m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DeleteDlgGenerated::OnClose ) ); + m_checkBoxDeleteBothSides->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnDelOnBothSides ), NULL, this ); + m_checkBoxUseRecycler->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnUseRecycler ), NULL, this ); + m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnOK ), NULL, this ); + m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DeleteDlgGenerated::OnCancel ), NULL, this ); } FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer21; - bSizer21 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer86; - bSizer86 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmap26 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer86->Add( m_bitmap26, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); - - m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxVERTICAL ); - - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Filter files"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText56->Wrap( -1 ); - m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - m_panel8->SetSizer( bSizer72 ); - m_panel8->Layout(); - bSizer72->Fit( m_panel8 ); - bSizer86->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - - bSizer86->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer21->Add( bSizer86, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer70; - bSizer70 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText44 = new wxStaticText( this, wxID_ANY, _("Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText44->Wrap( 400 ); - bSizer70->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bpButtonHelp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButtonHelp->SetToolTip( _("Help") ); - - m_bpButtonHelp->SetToolTip( _("Help") ); - - bSizer70->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - bSizer21->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); - - - bSizer21->Add( 0, 5, 0, 0, 5 ); - - m_panel13 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer69; - bSizer69 = new wxBoxSizer( wxVERTICAL ); - - m_staticline10 = new wxStaticLine( m_panel13, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer52; - bSizer52 = new wxBoxSizer( wxVERTICAL ); - - m_staticText45 = new wxStaticText( m_panel13, wxID_ANY, _("Hints:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText45->Wrap( -1 ); - m_staticText45->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); - - bSizer52->Add( m_staticText45, 0, wxBOTTOM, 5 ); - - m_staticText83 = new wxStaticText( m_panel13, wxID_ANY, _("1. Enter relative file or directory names separated by ';' or a new line."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText83->Wrap( -1 ); - bSizer52->Add( m_staticText83, 0, 0, 5 ); - - m_staticText84 = new wxStaticText( m_panel13, wxID_ANY, _("2. Use wildcard characters '*' and '?'."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText84->Wrap( -1 ); - bSizer52->Add( m_staticText84, 0, 0, 5 ); - - m_staticText85 = new wxStaticText( m_panel13, wxID_ANY, _("3. Exclude files directly on main grid via context menu."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText85->Wrap( -1 ); - bSizer52->Add( m_staticText85, 0, 0, 5 ); - - bSizer69->Add( bSizer52, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); - - wxStaticBoxSizer* sbSizer21; - sbSizer21 = new wxStaticBoxSizer( new wxStaticBox( m_panel13, wxID_ANY, _("Example") ), wxVERTICAL ); - - wxBoxSizer* bSizer66; - bSizer66 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText181 = new wxStaticText( m_panel13, wxID_ANY, _("Include: *.doc;*.zip;*.exe\nExclude: temp\\*"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText181->Wrap( -1 ); - bSizer66->Add( m_staticText181, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticText1811 = new wxStaticText( m_panel13, wxID_ANY, _("Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\"."), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1811->Wrap( 250 ); - m_staticText1811->SetFont( wxFont( 8, 74, 93, 90, false, wxT("Tahoma") ) ); - - bSizer66->Add( m_staticText1811, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); - - sbSizer21->Add( bSizer66, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); - - bSizer69->Add( sbSizer21, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_panel13->SetSizer( bSizer69 ); - m_panel13->Layout(); - bSizer69->Fit( m_panel13 ); - bSizer21->Add( m_panel13, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxEXPAND, 5 ); - - wxStaticBoxSizer* sbSizer8; - sbSizer8 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxFlexGridSizer* fgSizer3; - fgSizer3 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer3->AddGrowableCol( 1 ); - fgSizer3->AddGrowableRow( 1 ); - fgSizer3->SetFlexibleDirection( wxBOTH ); - fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText15 = new wxStaticText( this, wxID_ANY, _("Include"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText15->Wrap( -1 ); - m_staticText15->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer3->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_bitmap8 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - fgSizer3->Add( m_bitmap8, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlInclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - fgSizer3->Add( m_textCtrlInclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer8->Add( fgSizer3, 1, wxEXPAND, 5 ); - - wxFlexGridSizer* fgSizer4; - fgSizer4 = new wxFlexGridSizer( 2, 2, 0, 0 ); - fgSizer4->AddGrowableCol( 1 ); - fgSizer4->AddGrowableRow( 1 ); - fgSizer4->SetFlexibleDirection( wxBOTH ); - fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_staticText16 = new wxStaticText( this, wxID_ANY, _("Exclude"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText16->Wrap( -1 ); - m_staticText16->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - fgSizer4->Add( m_staticText16, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); - fgSizer4->Add( m_bitmap9, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlExclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); - fgSizer4->Add( m_textCtrlExclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - - sbSizer8->Add( fgSizer4, 1, wxEXPAND, 5 ); - - bSizer21->Add( sbSizer8, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - - bSizer21->Add( 0, 0, 0, 0, 5 ); - - wxBoxSizer* bSizer22; - bSizer22 = new wxBoxSizer( wxHORIZONTAL ); - - m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer22->Add( m_button9, 0, wxALL, 5 ); - - - bSizer22->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_button10 = new wxButton( this, wxID_OK, _("&Apply"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button10->SetDefault(); - m_button10->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer22->Add( m_button10, 0, wxALL, 5 ); - - m_button17 = new wxButton( this, wxID_CANCEL, _("dummy"), wxDefaultPosition, wxSize( 0,0 ), 0 ); - bSizer22->Add( m_button17, 0, wxALIGN_BOTTOM, 5 ); - - bSizer21->Add( bSizer22, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); - - this->SetSizer( bSizer21 ); - this->Layout(); - bSizer21->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); - m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnHelp ), NULL, this ); - m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); - m_button10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnApply ), NULL, this ); - m_button17->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer21; + bSizer21 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer86; + bSizer86 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmap26 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); + bSizer86->Add( m_bitmap26, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + + m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxVERTICAL ); + + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Filter files"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56->Wrap( -1 ); + m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + m_panel8->SetSizer( bSizer72 ); + m_panel8->Layout(); + bSizer72->Fit( m_panel8 ); + bSizer86->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + bSizer86->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer21->Add( bSizer86, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer70; + bSizer70 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText44 = new wxStaticText( this, wxID_ANY, _("Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the name relative(!) to the base synchronization directories."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText44->Wrap( 400 ); + bSizer70->Add( m_staticText44, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_bpButtonHelp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButtonHelp->SetToolTip( _("Help") ); + + m_bpButtonHelp->SetToolTip( _("Help") ); + + bSizer70->Add( m_bpButtonHelp, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + bSizer21->Add( bSizer70, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); + + + bSizer21->Add( 0, 5, 0, 0, 5 ); + + m_panel13 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer69; + bSizer69 = new wxBoxSizer( wxVERTICAL ); + + m_staticline10 = new wxStaticLine( m_panel13, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer69->Add( m_staticline10, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer52; + bSizer52 = new wxBoxSizer( wxVERTICAL ); + + m_staticText45 = new wxStaticText( m_panel13, wxID_ANY, _("Hints:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText45->Wrap( -1 ); + m_staticText45->SetFont( wxFont( 10, 74, 90, 92, true, wxT("Tahoma") ) ); + + bSizer52->Add( m_staticText45, 0, wxBOTTOM, 5 ); + + m_staticText83 = new wxStaticText( m_panel13, wxID_ANY, _("1. Enter relative file or directory names separated by ';' or a new line."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText83->Wrap( -1 ); + bSizer52->Add( m_staticText83, 0, 0, 5 ); + + m_staticText84 = new wxStaticText( m_panel13, wxID_ANY, _("2. Use wildcard characters '*' and '?'."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText84->Wrap( -1 ); + bSizer52->Add( m_staticText84, 0, 0, 5 ); + + m_staticText85 = new wxStaticText( m_panel13, wxID_ANY, _("3. Exclude files directly on main grid via context menu."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText85->Wrap( -1 ); + bSizer52->Add( m_staticText85, 0, 0, 5 ); + + bSizer69->Add( bSizer52, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 10 ); + + wxStaticBoxSizer* sbSizer21; + sbSizer21 = new wxStaticBoxSizer( new wxStaticBox( m_panel13, wxID_ANY, _("Example") ), wxVERTICAL ); + + wxBoxSizer* bSizer66; + bSizer66 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText181 = new wxStaticText( m_panel13, wxID_ANY, _("Include: *.doc;*.zip;*.exe\nExclude: temp\\*"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText181->Wrap( -1 ); + bSizer66->Add( m_staticText181, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText1811 = new wxStaticText( m_panel13, wxID_ANY, _("Synchronize all .doc, .zip and .exe files except everything in subfolder \"temp\"."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1811->Wrap( 250 ); + m_staticText1811->SetFont( wxFont( 8, 74, 93, 90, false, wxT("Tahoma") ) ); + + bSizer66->Add( m_staticText1811, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + + sbSizer21->Add( bSizer66, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); + + bSizer69->Add( sbSizer21, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_panel13->SetSizer( bSizer69 ); + m_panel13->Layout(); + bSizer69->Fit( m_panel13 ); + bSizer21->Add( m_panel13, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxEXPAND, 5 ); + + wxStaticBoxSizer* sbSizer8; + sbSizer8 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxFlexGridSizer* fgSizer3; + fgSizer3 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer3->AddGrowableCol( 1 ); + fgSizer3->AddGrowableRow( 1 ); + fgSizer3->SetFlexibleDirection( wxBOTH ); + fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText15 = new wxStaticText( this, wxID_ANY, _("Include"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText15->Wrap( -1 ); + m_staticText15->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer3->Add( m_staticText15, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap8 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + fgSizer3->Add( m_bitmap8, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlInclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); + fgSizer3->Add( m_textCtrlInclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer8->Add( fgSizer3, 1, wxEXPAND, 5 ); + + wxFlexGridSizer* fgSizer4; + fgSizer4 = new wxFlexGridSizer( 2, 2, 0, 0 ); + fgSizer4->AddGrowableCol( 1 ); + fgSizer4->AddGrowableRow( 1 ); + fgSizer4->SetFlexibleDirection( wxBOTH ); + fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer4->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_staticText16 = new wxStaticText( this, wxID_ANY, _("Exclude"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText16->Wrap( -1 ); + m_staticText16->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + fgSizer4->Add( m_staticText16, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bitmap9 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 30,30 ), 0 ); + fgSizer4->Add( m_bitmap9, 0, wxTOP|wxBOTTOM|wxLEFT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlExclude = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxTE_MULTILINE ); + fgSizer4->Add( m_textCtrlExclude, 1, wxALL|wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + + sbSizer8->Add( fgSizer4, 1, wxEXPAND, 5 ); + + bSizer21->Add( sbSizer8, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + + bSizer21->Add( 0, 0, 0, 0, 5 ); + + wxBoxSizer* bSizer22; + bSizer22 = new wxBoxSizer( wxHORIZONTAL ); + + m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer22->Add( m_button9, 0, wxALL, 5 ); + + + bSizer22->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_button10 = new wxButton( this, wxID_OK, _("&Apply"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button10->SetDefault(); + m_button10->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer22->Add( m_button10, 0, wxALL, 5 ); + + m_button17 = new wxButton( this, wxID_CANCEL, _("dummy"), wxDefaultPosition, wxSize( 0,0 ), 0 ); + bSizer22->Add( m_button17, 0, wxALIGN_BOTTOM, 5 ); + + bSizer21->Add( bSizer22, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); + + this->SetSizer( bSizer21 ); + this->Layout(); + bSizer21->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); + m_bpButtonHelp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnHelp ), NULL, this ); + m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); + m_button10->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnApply ), NULL, this ); + m_button17->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); } FilterDlgGenerated::~FilterDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); - m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnHelp ), NULL, this ); - m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); - m_button10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnApply ), NULL, this ); - m_button17->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FilterDlgGenerated::OnClose ) ); + m_bpButtonHelp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnHelp ), NULL, this ); + m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnDefault ), NULL, this ); + m_button10->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnApply ), NULL, this ); + m_button17->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); } CustomizeColsDlgGenerated::CustomizeColsDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer96; - bSizer96 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer99; - bSizer99 = new wxBoxSizer( wxHORIZONTAL ); - - wxArrayString m_checkListColumnsChoices; - m_checkListColumns = new wxCheckListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_checkListColumnsChoices, 0 ); - bSizer99->Add( m_checkListColumns, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - wxBoxSizer* bSizer98; - bSizer98 = new wxBoxSizer( wxVERTICAL ); - - m_bpButton29 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButton29->SetToolTip( _("Move column up") ); - - m_bpButton29->SetToolTip( _("Move column up") ); - - bSizer98->Add( m_bpButton29, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); - - m_bpButton30 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); - m_bpButton30->SetToolTip( _("Move column down") ); - - m_bpButton30->SetToolTip( _("Move column down") ); - - bSizer98->Add( m_bpButton30, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer99->Add( bSizer98, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer96->Add( bSizer99, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_checkBoxShowFileIcons = new wxCheckBox( this, wxID_ANY, _("Show file icons"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer96->Add( m_checkBoxShowFileIcons, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer97; - bSizer97 = new wxBoxSizer( wxHORIZONTAL ); - - m_button28 = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button28->SetDefault(); - m_button28->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_button28, 0, wxALL, 5 ); - - m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_button9, 0, wxALL, 5 ); - - m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button29->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_button29, 0, wxALL, 5 ); - - bSizer96->Add( bSizer97, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - this->SetSizer( bSizer96 ); - this->Layout(); - bSizer96->Fit( this ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CustomizeColsDlgGenerated::OnClose ) ); - m_bpButton29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveUp ), NULL, this ); - m_bpButton30->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveDown ), NULL, this ); - m_button28->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnOkay ), NULL, this ); - m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnDefault ), NULL, this ); - m_button29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer96; + bSizer96 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer99; + bSizer99 = new wxBoxSizer( wxHORIZONTAL ); + + wxArrayString m_checkListColumnsChoices; + m_checkListColumns = new wxCheckListBox( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_checkListColumnsChoices, 0 ); + bSizer99->Add( m_checkListColumns, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + wxBoxSizer* bSizer98; + bSizer98 = new wxBoxSizer( wxVERTICAL ); + + m_bpButton29 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton29->SetToolTip( _("Move column up") ); + + m_bpButton29->SetToolTip( _("Move column up") ); + + bSizer98->Add( m_bpButton29, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_bpButton30 = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), wxBU_AUTODRAW ); + m_bpButton30->SetToolTip( _("Move column down") ); + + m_bpButton30->SetToolTip( _("Move column down") ); + + bSizer98->Add( m_bpButton30, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + bSizer99->Add( bSizer98, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer96->Add( bSizer99, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_checkBoxShowFileIcons = new wxCheckBox( this, wxID_ANY, _("Show file icons"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer96->Add( m_checkBoxShowFileIcons, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer97; + bSizer97 = new wxBoxSizer( wxHORIZONTAL ); + + m_button28 = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button28->SetDefault(); + m_button28->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_button28, 0, wxALL, 5 ); + + m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_button9, 0, wxALL, 5 ); + + m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button29->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_button29, 0, wxALL, 5 ); + + bSizer96->Add( bSizer97, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + this->SetSizer( bSizer96 ); + this->Layout(); + bSizer96->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CustomizeColsDlgGenerated::OnClose ) ); + m_bpButton29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveUp ), NULL, this ); + m_bpButton30->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveDown ), NULL, this ); + m_button28->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnOkay ), NULL, this ); + m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnDefault ), NULL, this ); + m_button29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnCancel ), NULL, this ); } CustomizeColsDlgGenerated::~CustomizeColsDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CustomizeColsDlgGenerated::OnClose ) ); - m_bpButton29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveUp ), NULL, this ); - m_bpButton30->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveDown ), NULL, this ); - m_button28->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnOkay ), NULL, this ); - m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnDefault ), NULL, this ); - m_button29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( CustomizeColsDlgGenerated::OnClose ) ); + m_bpButton29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveUp ), NULL, this ); + m_bpButton30->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnMoveDown ), NULL, this ); + m_button28->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnOkay ), NULL, this ); + m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnDefault ), NULL, this ); + m_button29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CustomizeColsDlgGenerated::OnCancel ), NULL, this ); } GlobalSettingsDlgGenerated::GlobalSettingsDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer95; - bSizer95 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer86; - bSizer86 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer86->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - - bSizer86->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - - m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); - m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); - - wxBoxSizer* bSizer72; - bSizer72 = new wxBoxSizer( wxVERTICAL ); - - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Global settings"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText56->Wrap( -1 ); - m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - m_panel8->SetSizer( bSizer72 ); - m_panel8->Layout(); - bSizer72->Fit( m_panel8 ); - bSizer86->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - - bSizer95->Add( bSizer86, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - bSizer95->Add( 0, 10, 0, 0, 5 ); - - wxStaticBoxSizer* sbSizer23; - sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - - wxBoxSizer* bSizer120; - bSizer120 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText114 = new wxStaticText( this, wxID_ANY, _("Ignore 1-hour file time difference"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText114->Wrap( -1 ); - m_staticText114->SetToolTip( _("Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.") ); - - bSizer120->Add( m_staticText114, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer120->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_checkBoxIgnoreOneHour = new wxCheckBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - - m_checkBoxIgnoreOneHour->SetToolTip( _("Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.") ); - - bSizer120->Add( m_checkBoxIgnoreOneHour, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer23->Add( bSizer120, 1, wxEXPAND, 5 ); - - m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - sbSizer23->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer101; - bSizer101 = new wxBoxSizer( wxHORIZONTAL ); - - m_staticText100 = new wxStaticText( this, wxID_ANY, _("Hidden dialogs:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText100->Wrap( -1 ); - bSizer101->Add( m_staticText100, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer101->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_buttonResetDialogs = new wxButtonWithImage( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxSize( 80,-1 ), 0 ); - m_buttonResetDialogs->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - m_buttonResetDialogs->SetToolTip( _("Show hidden dialogs") ); - - bSizer101->Add( m_buttonResetDialogs, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer23->Add( bSizer101, 1, wxEXPAND, 5 ); - - bSizer95->Add( sbSizer23, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - - bSizer95->Add( 0, 10, 0, 0, 5 ); - - wxStaticBoxSizer* sbSizer26; - sbSizer26 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("External applications") ), wxHORIZONTAL ); - - - sbSizer26->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_gridCustomCommand = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - - // Grid - m_gridCustomCommand->CreateGrid( 5, 2 ); - m_gridCustomCommand->EnableEditing( true ); - m_gridCustomCommand->EnableGridLines( true ); - m_gridCustomCommand->EnableDragGridSize( false ); - m_gridCustomCommand->SetMargins( 0, 0 ); - - // Columns - m_gridCustomCommand->SetColSize( 0, 98 ); - m_gridCustomCommand->SetColSize( 1, 179 ); - m_gridCustomCommand->EnableDragColMove( false ); - m_gridCustomCommand->EnableDragColSize( true ); - m_gridCustomCommand->SetColLabelSize( 20 ); - m_gridCustomCommand->SetColLabelValue( 0, _("Description") ); - m_gridCustomCommand->SetColLabelValue( 1, _("Commandline") ); - m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Rows - m_gridCustomCommand->EnableDragRowSize( false ); - m_gridCustomCommand->SetRowLabelSize( 0 ); - m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); - - // Label Appearance - - // Cell Defaults - m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); - sbSizer26->Add( m_gridCustomCommand, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer157; - bSizer157 = new wxBoxSizer( wxVERTICAL ); - - m_bpButtonAddRow = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - bSizer157->Add( m_bpButtonAddRow, 0, 0, 5 ); - - m_bpButtonRemoveRow = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); - bSizer157->Add( m_bpButtonRemoveRow, 0, 0, 5 ); - - sbSizer26->Add( bSizer157, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - - sbSizer26->Add( 0, 0, 1, wxEXPAND, 5 ); - - bSizer95->Add( sbSizer26, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - wxBoxSizer* bSizer97; - bSizer97 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_buttonOkay->SetDefault(); - m_buttonOkay->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_buttonOkay, 0, wxALL, 5 ); - - m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_button9, 0, wxALL, 5 ); - - m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button29->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer97->Add( m_button29, 0, wxALL, 5 ); - - bSizer95->Add( bSizer97, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - this->SetSizer( bSizer95 ); - this->Layout(); - bSizer95->Fit( this ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); - m_buttonResetDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this ); - m_bpButtonAddRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnAddRow ), NULL, this ); - m_bpButtonRemoveRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnRemoveRow ), NULL, this ); - m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnOkay ), NULL, this ); - m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this ); - m_button29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer95; + bSizer95 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer86; + bSizer86 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapSettings = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); + bSizer86->Add( m_bitmapSettings, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + + bSizer86->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); + + m_panel8 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER|wxTAB_TRAVERSAL ); + m_panel8->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) ); + + wxBoxSizer* bSizer72; + bSizer72 = new wxBoxSizer( wxVERTICAL ); + + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Global settings"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56->Wrap( -1 ); + m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + m_panel8->SetSizer( bSizer72 ); + m_panel8->Layout(); + bSizer72->Fit( m_panel8 ); + bSizer86->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + bSizer95->Add( bSizer86, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + + bSizer95->Add( 0, 10, 0, 0, 5 ); + + wxStaticBoxSizer* sbSizer23; + sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); + + wxBoxSizer* bSizer120; + bSizer120 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText114 = new wxStaticText( this, wxID_ANY, _("Ignore 1-hour file time difference"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText114->Wrap( -1 ); + m_staticText114->SetToolTip( _("Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.") ); + + bSizer120->Add( m_staticText114, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer120->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_checkBoxIgnoreOneHour = new wxCheckBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + + m_checkBoxIgnoreOneHour->SetToolTip( _("Treat file times that differ by exactly +/- 1 hour as equal, less than 1 hour as conflict in order to handle Daylight Saving Time changes.") ); + + bSizer120->Add( m_checkBoxIgnoreOneHour, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer23->Add( bSizer120, 1, wxEXPAND, 5 ); + + m_staticline10 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + sbSizer23->Add( m_staticline10, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer101; + bSizer101 = new wxBoxSizer( wxHORIZONTAL ); + + m_staticText100 = new wxStaticText( this, wxID_ANY, _("Hidden dialogs:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText100->Wrap( -1 ); + bSizer101->Add( m_staticText100, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer101->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_buttonResetDialogs = new wxButtonWithImage( this, wxID_ANY, _("Reset"), wxDefaultPosition, wxSize( 80,-1 ), 0 ); + m_buttonResetDialogs->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); + m_buttonResetDialogs->SetToolTip( _("Show hidden dialogs") ); + + bSizer101->Add( m_buttonResetDialogs, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer23->Add( bSizer101, 1, wxEXPAND, 5 ); + + bSizer95->Add( sbSizer23, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + + bSizer95->Add( 0, 10, 0, 0, 5 ); + + wxStaticBoxSizer* sbSizer26; + sbSizer26 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("External applications") ), wxHORIZONTAL ); + + + sbSizer26->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_gridCustomCommand = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + + // Grid + m_gridCustomCommand->CreateGrid( 5, 2 ); + m_gridCustomCommand->EnableEditing( true ); + m_gridCustomCommand->EnableGridLines( true ); + m_gridCustomCommand->EnableDragGridSize( false ); + m_gridCustomCommand->SetMargins( 0, 0 ); + + // Columns + m_gridCustomCommand->SetColSize( 0, 98 ); + m_gridCustomCommand->SetColSize( 1, 179 ); + m_gridCustomCommand->EnableDragColMove( false ); + m_gridCustomCommand->EnableDragColSize( true ); + m_gridCustomCommand->SetColLabelSize( 20 ); + m_gridCustomCommand->SetColLabelValue( 0, _("Description") ); + m_gridCustomCommand->SetColLabelValue( 1, _("Commandline") ); + m_gridCustomCommand->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_gridCustomCommand->EnableDragRowSize( false ); + m_gridCustomCommand->SetRowLabelSize( 0 ); + m_gridCustomCommand->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_gridCustomCommand->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + sbSizer26->Add( m_gridCustomCommand, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + wxBoxSizer* bSizer157; + bSizer157 = new wxBoxSizer( wxVERTICAL ); + + m_bpButtonAddRow = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + bSizer157->Add( m_bpButtonAddRow, 0, 0, 5 ); + + m_bpButtonRemoveRow = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + bSizer157->Add( m_bpButtonRemoveRow, 0, 0, 5 ); + + sbSizer26->Add( bSizer157, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + + sbSizer26->Add( 0, 0, 1, wxEXPAND, 5 ); + + bSizer95->Add( sbSizer26, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxBoxSizer* bSizer97; + bSizer97 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonOkay = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_buttonOkay->SetDefault(); + m_buttonOkay->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_buttonOkay, 0, wxALL, 5 ); + + m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_button9, 0, wxALL, 5 ); + + m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button29->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer97->Add( m_button29, 0, wxALL, 5 ); + + bSizer95->Add( bSizer97, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + this->SetSizer( bSizer95 ); + this->Layout(); + bSizer95->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); + m_buttonResetDialogs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this ); + m_bpButtonAddRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnAddRow ), NULL, this ); + m_bpButtonRemoveRow->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnRemoveRow ), NULL, this ); + m_buttonOkay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnOkay ), NULL, this ); + m_button9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this ); + m_button29->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this ); } GlobalSettingsDlgGenerated::~GlobalSettingsDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); - m_buttonResetDialogs->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this ); - m_bpButtonAddRow->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnAddRow ), NULL, this ); - m_bpButtonRemoveRow->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnRemoveRow ), NULL, this ); - m_buttonOkay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnOkay ), NULL, this ); - m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this ); - m_button29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); + m_buttonResetDialogs->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnResetDialogs ), NULL, this ); + m_bpButtonAddRow->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnAddRow ), NULL, this ); + m_bpButtonRemoveRow->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnRemoveRow ), NULL, this ); + m_buttonOkay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnOkay ), NULL, this ); + m_button9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnDefault ), NULL, this ); + m_button29->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( GlobalSettingsDlgGenerated::OnCancel ), NULL, this ); } SyncPreviewDlgGenerated::SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizer134; - bSizer134 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxHORIZONTAL ); - - m_buttonStartSync = new wxButtonWithImage( this, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 ); - m_buttonStartSync->SetDefault(); - m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); - m_buttonStartSync->SetToolTip( _("Start synchronization") ); - - bSizer158->Add( m_buttonStartSync, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticline16 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); - bSizer158->Add( m_staticline16, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); - - wxStaticBoxSizer* sbSizer28; - sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Variant") ), wxVERTICAL ); - - m_staticTextVariant = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextVariant->Wrap( -1 ); - m_staticTextVariant->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); - - sbSizer28->Add( m_staticTextVariant, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer158->Add( sbSizer28, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - - bSizer134->Add( bSizer158, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - - m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline14, 0, wxEXPAND, 5 ); - - wxBoxSizer* bSizer141; - bSizer141 = new wxBoxSizer( wxHORIZONTAL ); - - wxStaticBoxSizer* sbSizer161; - sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Statistics") ), wxVERTICAL ); - - wxBoxSizer* bSizer157; - bSizer157 = new wxBoxSizer( wxHORIZONTAL ); - - wxFlexGridSizer* fgSizer5; - fgSizer5 = new wxFlexGridSizer( 4, 2, 0, 5 ); - fgSizer5->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - - fgSizer5->Add( 0, 0, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticText94 = new wxStaticText( this, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText94->Wrap( -1 ); - m_staticText94->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer5->Add( m_staticText94, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapCreate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapCreate->SetToolTip( _("Number of files and directories that will be created") ); - - fgSizer5->Add( m_bitmapCreate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlCreateL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlCreateL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlCreateL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlCreateL->SetToolTip( _("Number of files and directories that will be created") ); - - fgSizer5->Add( m_textCtrlCreateL, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapUpdate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapUpdate->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer5->Add( m_bitmapUpdate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_textCtrlUpdateL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlUpdateL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlUpdateL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlUpdateL->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer5->Add( m_textCtrlUpdateL, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_bitmapDelete = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapDelete->SetToolTip( _("Number of files and directories that will be deleted") ); - - fgSizer5->Add( m_bitmapDelete, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlDeleteL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlDeleteL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlDeleteL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlDeleteL->SetToolTip( _("Number of files and directories that will be deleted") ); - - fgSizer5->Add( m_textCtrlDeleteL, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer157->Add( fgSizer5, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); - - wxFlexGridSizer* fgSizer51; - fgSizer51 = new wxFlexGridSizer( 3, 1, 0, 5 ); - fgSizer51->SetFlexibleDirection( wxHORIZONTAL ); - fgSizer51->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - - m_staticText95 = new wxStaticText( this, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText95->Wrap( -1 ); - m_staticText95->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); - - fgSizer51->Add( m_staticText95, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlCreateR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlCreateR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlCreateR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlCreateR->SetToolTip( _("Number of files and directories that will be created") ); - - fgSizer51->Add( m_textCtrlCreateR, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlUpdateR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlUpdateR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlUpdateR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlUpdateR->SetToolTip( _("Number of files that will be overwritten") ); - - fgSizer51->Add( m_textCtrlUpdateR, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - m_textCtrlDeleteR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlDeleteR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlDeleteR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlDeleteR->SetToolTip( _("Number of files and directories that will be deleted") ); - - fgSizer51->Add( m_textCtrlDeleteR, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - bSizer157->Add( fgSizer51, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); - - sbSizer161->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - - sbSizer161->Add( 0, 10, 0, 0, 5 ); - - wxBoxSizer* bSizer156; - bSizer156 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapData = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - m_bitmapData->SetToolTip( _("Total amount of data that will be transferred") ); - - bSizer156->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT, 5 ); - - - bSizer156->Add( 0, 0, 1, wxEXPAND, 5 ); - - m_textCtrlData = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); - m_textCtrlData->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); - m_textCtrlData->SetBackgroundColour( wxColour( 222, 222, 236 ) ); - m_textCtrlData->SetToolTip( _("Total amount of data that will be transferred") ); - - bSizer156->Add( m_textCtrlData, 0, wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer156->Add( 0, 0, 1, wxEXPAND, 5 ); - - sbSizer161->Add( bSizer156, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); - - bSizer141->Add( sbSizer161, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); - - bSizer134->Add( bSizer141, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - - m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer134->Add( m_staticline12, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer142; - bSizer142 = new wxBoxSizer( wxHORIZONTAL ); - - m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); - - bSizer142->Add( m_checkBoxDontShowAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer142->Add( 10, 0, 1, 0, 5 ); - - m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - - bSizer142->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); - - bSizer134->Add( bSizer142, 0, wxEXPAND, 5 ); - - this->SetSizer( bSizer134 ); - this->Layout(); - bSizer134->Fit( this ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) ); - m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this ); - m_button16->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizer134; + bSizer134 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer158; + bSizer158 = new wxBoxSizer( wxHORIZONTAL ); + + m_buttonStartSync = new wxButtonWithImage( this, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 ); + m_buttonStartSync->SetDefault(); + m_buttonStartSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + m_buttonStartSync->SetToolTip( _("Start synchronization") ); + + bSizer158->Add( m_buttonStartSync, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticline16 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + bSizer158->Add( m_staticline16, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + + wxStaticBoxSizer* sbSizer28; + sbSizer28 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Variant") ), wxVERTICAL ); + + m_staticTextVariant = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextVariant->Wrap( -1 ); + m_staticTextVariant->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Arial Black") ) ); + + sbSizer28->Add( m_staticTextVariant, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer158->Add( sbSizer28, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + bSizer134->Add( bSizer158, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); + + m_staticline14 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline14, 0, wxEXPAND, 5 ); + + wxBoxSizer* bSizer141; + bSizer141 = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbSizer161; + sbSizer161 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Statistics") ), wxVERTICAL ); + + wxBoxSizer* bSizer157; + bSizer157 = new wxBoxSizer( wxHORIZONTAL ); + + wxFlexGridSizer* fgSizer5; + fgSizer5 = new wxFlexGridSizer( 4, 2, 0, 5 ); + fgSizer5->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + fgSizer5->Add( 0, 0, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticText94 = new wxStaticText( this, wxID_ANY, _("Left"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText94->Wrap( -1 ); + m_staticText94->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer5->Add( m_staticText94, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmapCreate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapCreate->SetToolTip( _("Number of files and directories that will be created") ); + + fgSizer5->Add( m_bitmapCreate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlCreateL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlCreateL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlCreateL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlCreateL->SetToolTip( _("Number of files and directories that will be created") ); + + fgSizer5->Add( m_textCtrlCreateL, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmapUpdate = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapUpdate->SetToolTip( _("Number of files that will be overwritten") ); + + fgSizer5->Add( m_bitmapUpdate, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_textCtrlUpdateL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlUpdateL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlUpdateL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlUpdateL->SetToolTip( _("Number of files that will be overwritten") ); + + fgSizer5->Add( m_textCtrlUpdateL, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_bitmapDelete = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapDelete->SetToolTip( _("Number of files and directories that will be deleted") ); + + fgSizer5->Add( m_bitmapDelete, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlDeleteL = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlDeleteL->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlDeleteL->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlDeleteL->SetToolTip( _("Number of files and directories that will be deleted") ); + + fgSizer5->Add( m_textCtrlDeleteL, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer157->Add( fgSizer5, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); + + wxFlexGridSizer* fgSizer51; + fgSizer51 = new wxFlexGridSizer( 3, 1, 0, 5 ); + fgSizer51->SetFlexibleDirection( wxHORIZONTAL ); + fgSizer51->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText95 = new wxStaticText( this, wxID_ANY, _("Right"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText95->Wrap( -1 ); + m_staticText95->SetFont( wxFont( 9, 74, 90, 92, false, wxT("Arial") ) ); + + fgSizer51->Add( m_staticText95, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlCreateR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlCreateR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlCreateR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlCreateR->SetToolTip( _("Number of files and directories that will be created") ); + + fgSizer51->Add( m_textCtrlCreateR, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlUpdateR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlUpdateR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlUpdateR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlUpdateR->SetToolTip( _("Number of files that will be overwritten") ); + + fgSizer51->Add( m_textCtrlUpdateR, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_textCtrlDeleteR = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlDeleteR->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlDeleteR->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlDeleteR->SetToolTip( _("Number of files and directories that will be deleted") ); + + fgSizer51->Add( m_textCtrlDeleteR, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + bSizer157->Add( fgSizer51, 0, wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL, 5 ); + + sbSizer161->Add( bSizer157, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + + sbSizer161->Add( 0, 10, 0, 0, 5 ); + + wxBoxSizer* bSizer156; + bSizer156 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapData = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_bitmapData->SetToolTip( _("Total amount of data that will be transferred") ); + + bSizer156->Add( m_bitmapData, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxRIGHT, 5 ); + + + bSizer156->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_textCtrlData = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxTE_READONLY ); + m_textCtrlData->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + m_textCtrlData->SetBackgroundColour( wxColour( 222, 222, 236 ) ); + m_textCtrlData->SetToolTip( _("Total amount of data that will be transferred") ); + + bSizer156->Add( m_textCtrlData, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer156->Add( 0, 0, 1, wxEXPAND, 5 ); + + sbSizer161->Add( bSizer156, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + bSizer141->Add( sbSizer161, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); + + bSizer134->Add( bSizer141, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + + m_staticline12 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizer134->Add( m_staticline12, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer142; + bSizer142 = new wxBoxSizer( wxHORIZONTAL ); + + m_checkBoxDontShowAgain = new wxCheckBox( this, wxID_ANY, _("Do not show this dialog again"), wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer142->Add( m_checkBoxDontShowAgain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizer142->Add( 10, 0, 1, 0, 5 ); + + m_button16 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button16->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + + bSizer142->Add( m_button16, 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + + bSizer134->Add( bSizer142, 0, wxEXPAND, 5 ); + + this->SetSizer( bSizer134 ); + this->Layout(); + bSizer134->Fit( this ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) ); + m_buttonStartSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this ); + m_button16->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this ); } SyncPreviewDlgGenerated::~SyncPreviewDlgGenerated() { - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) ); - m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this ); - m_button16->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this ); + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncPreviewDlgGenerated::OnClose ) ); + m_buttonStartSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnStartSync ), NULL, this ); + m_button16->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncPreviewDlgGenerated::OnCancel ), NULL, this ); } PopupFrameGenerated1::PopupFrameGenerated1( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - this->SetBackgroundColour( wxColour( 255, 255, 255 ) ); - - wxBoxSizer* bSizer158; - bSizer158 = new wxBoxSizer( wxHORIZONTAL ); - - m_bitmapLeft = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer158->Add( m_bitmapLeft, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - - m_staticTextMain = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextMain->Wrap( 600 ); - bSizer158->Add( m_staticTextMain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - this->SetSizer( bSizer158 ); - this->Layout(); - bSizer158->Fit( this ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + this->SetBackgroundColour( wxColour( 255, 255, 255 ) ); + + wxBoxSizer* bSizer158; + bSizer158 = new wxBoxSizer( wxHORIZONTAL ); + + m_bitmapLeft = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer158->Add( m_bitmapLeft, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticTextMain = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextMain->Wrap( 600 ); + bSizer158->Add( m_staticTextMain, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + + this->SetSizer( bSizer158 ); + this->Layout(); + bSizer158->Fit( this ); } PopupFrameGenerated1::~PopupFrameGenerated1() diff --git a/ui/guiGenerated.h b/ui/guiGenerated.h index 5f4cc208..65685a17 100644 --- a/ui/guiGenerated.h +++ b/ui/guiGenerated.h @@ -56,956 +56,1357 @@ class wxButtonWithImage; /////////////////////////////////////////////////////////////////////////////// /// Class MainDialogGenerated /////////////////////////////////////////////////////////////////////////////// -class MainDialogGenerated : public wxFrame +class MainDialogGenerated : public wxFrame { - private: - - protected: - wxMenuBar* m_menubar1; - wxMenu* m_menuFile; - wxMenuItem* m_menuItem10; - wxMenuItem* m_menuItem11; - wxMenuItem* m_menuItemSwitchView; - wxMenuItem* m_menuItemNew; - wxMenuItem* m_menuItemSave; - wxMenuItem* m_menuItemLoad; - wxMenu* m_menuAdvanced; - wxMenu* m_menuLanguages; - wxMenuItem* m_menuItemGlobSett; - wxMenuItem* m_menuItem7; - wxMenu* m_menuHelp; - wxMenuItem* m_menuItemAbout; - wxBoxSizer* bSizer1; - wxPanel* m_panel71; - wxBoxSizer* bSizer6; - - wxStaticText* m_staticTextCmpVariant; - - wxButtonWithImage* m_buttonCompare; - wxButton* m_buttonAbort; - wxBitmapButton* m_bpButtonCmpConfig; - - - wxStaticText* m_staticTextSyncVariant; - wxBitmapButton* m_bpButtonSyncConfig; - wxButtonWithImage* m_buttonStartSync; - - wxPanel* m_panelTopLeft; - wxStaticBoxSizer* sbSizer2; - wxComboBox* m_directoryLeft; - wxDirPickerCtrl* m_dirPickerLeft; - wxPanel* m_panelTopMiddle; - - wxBoxSizer* bSizerMiddle; - wxBitmapButton* m_bpButtonSwapSides; - wxPanel* m_panelTopRight; - wxBitmapButton* m_bpButtonAddPair; - wxComboBox* m_directoryRight; - wxDirPickerCtrl* m_dirPickerRight; - wxScrolledWindow* m_scrolledWindowFolderPairs; - wxBoxSizer* bSizerAddFolderPairs; - wxPanel* m_panelLeft; - CustomGridLeft* m_gridLeft; - wxPanel* m_panelMiddle; - CustomGridMiddle* m_gridMiddle; - wxPanel* m_panelRight; - CustomGridRight* m_gridRight; - wxBoxSizer* bSizer3; - wxNotebook* m_notebookBottomLeft; - wxPanel* m_panel30; - wxBitmapButton* m_bpButtonSave; - wxBitmapButton* m_bpButtonLoad; - wxChoice* m_choiceHistory; - wxPanel* m_panelFilter; - wxBitmapButton* m_bpButtonFilter; - wxHyperlinkCtrl* m_hyperlinkCfgFilter; - wxCheckBox* m_checkBoxHideFilt; - wxPanel* m_panel112; - - ToggleButton* m_bpButtonLeftOnly; - ToggleButton* m_bpButtonLeftNewer; - ToggleButton* m_bpButtonEqual; - ToggleButton* m_bpButtonDifferent; - ToggleButton* m_bpButtonRightNewer; - ToggleButton* m_bpButtonRightOnly; - ToggleButton* m_bpButtonSyncCreateLeft; - ToggleButton* m_bpButtonSyncDirOverwLeft; - ToggleButton* m_bpButtonSyncDeleteLeft; - ToggleButton* m_bpButtonSyncDirNone; - ToggleButton* m_bpButtonSyncDeleteRight; - ToggleButton* m_bpButtonSyncDirOverwRight; - ToggleButton* m_bpButtonSyncCreateRight; - ToggleButton* m_bpButtonConflict; - - wxBoxSizer* bSizerBottomRight; - - wxPanel* m_panelSyncPreview; - wxStaticBitmap* m_bitmapCreate; - wxTextCtrl* m_textCtrlCreate; - wxStaticBitmap* m_bitmapDelete; - wxTextCtrl* m_textCtrlDelete; - wxStaticBitmap* m_bitmapUpdate; - wxTextCtrl* m_textCtrlUpdate; - wxStaticBitmap* m_bitmapData; - wxTextCtrl* m_textCtrlData; - wxBitmapButton* m_bpButton10; - wxPanel* m_panel7; - - wxStaticText* m_staticTextStatusLeft; - - wxStaticLine* m_staticline9; - - wxStaticText* m_staticTextStatusMiddle; - - wxStaticLine* m_staticline10; - - wxStaticText* m_staticTextStatusRight; - - wxStaticBitmap* m_bitmap15; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnCompare( wxCommandEvent& event ){ event.Skip(); } - virtual void OnStartSync( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSwitchView( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNewConfig( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSaveConfig( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLoadConfig( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuQuit( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuGlobalSettings( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuBatchJob( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuExportFileList( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuCheckVersion( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuAbout( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCmpSettings( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncSettings( wxCommandEvent& event ){ event.Skip(); } - virtual void OnFolderHistoryKeyEvent( wxKeyEvent& event ){ event.Skip(); } - virtual void OnDirSelected( wxFileDirPickerEvent& event ){ event.Skip(); } - virtual void OnSwapSides( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddFolderPair( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLeftGridDoubleClick( wxGridEvent& event ){ event.Skip(); } - virtual void OnContextRim( wxGridEvent& event ){ event.Skip(); } - virtual void OnSortLeftGrid( wxGridEvent& event ){ event.Skip(); } - virtual void OnContextRimLabelLeft( wxGridEvent& event ){ event.Skip(); } - virtual void OnContextMiddle( wxGridEvent& event ){ event.Skip(); } - virtual void OnSortMiddleGrid( wxGridEvent& event ){ event.Skip(); } - virtual void OnContextMiddleLabel( wxGridEvent& event ){ event.Skip(); } - virtual void OnRightGridDoubleClick( wxGridEvent& event ){ event.Skip(); } - virtual void OnSortRightGrid( wxGridEvent& event ){ event.Skip(); } - virtual void OnContextRimLabelRight( wxGridEvent& event ){ event.Skip(); } - virtual void OnCfgHistoryKeyEvent( wxKeyEvent& event ){ event.Skip(); } - virtual void OnLoadFromHistory( wxCommandEvent& event ){ event.Skip(); } - virtual void OnFilterButton( wxCommandEvent& event ){ event.Skip(); } - virtual void OnConfigureFilter( wxHyperlinkEvent& event ){ event.Skip(); } - virtual void OnHideFilteredButton( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLeftOnlyFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLeftNewerFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnEqualFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDifferentFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRightNewerFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRightOnlyFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncCreateLeft( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncDirLeft( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncDeleteLeft( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncDirNone( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncDeleteRight( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncDirRight( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncCreateRight( wxCommandEvent& event ){ event.Skip(); } - virtual void OnConflictFiles( wxCommandEvent& event ){ event.Skip(); } - virtual void OnQuit( wxCommandEvent& event ){ event.Skip(); } - - - public: - MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("FreeFileSync - Folder Comparison and Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 933,612 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); - ~MainDialogGenerated(); - +private: + +protected: + wxMenuBar* m_menubar1; + wxMenu* m_menuFile; + wxMenuItem* m_menuItem10; + wxMenuItem* m_menuItem11; + wxMenuItem* m_menuItemSwitchView; + wxMenuItem* m_menuItemNew; + wxMenuItem* m_menuItemSave; + wxMenuItem* m_menuItemLoad; + wxMenu* m_menuAdvanced; + wxMenu* m_menuLanguages; + wxMenuItem* m_menuItemGlobSett; + wxMenuItem* m_menuItem7; + wxMenu* m_menuHelp; + wxMenuItem* m_menuItemAbout; + wxBoxSizer* bSizer1; + wxPanel* m_panel71; + wxBoxSizer* bSizer6; + + wxStaticText* m_staticTextCmpVariant; + + wxButtonWithImage* m_buttonCompare; + wxButton* m_buttonAbort; + wxBitmapButton* m_bpButtonCmpConfig; + + + wxStaticText* m_staticTextSyncVariant; + wxBitmapButton* m_bpButtonSyncConfig; + wxButtonWithImage* m_buttonStartSync; + + wxPanel* m_panelTopLeft; + wxStaticBoxSizer* sbSizer2; + wxComboBox* m_directoryLeft; + wxDirPickerCtrl* m_dirPickerLeft; + wxPanel* m_panelTopMiddle; + + wxBoxSizer* bSizerMiddle; + wxBitmapButton* m_bpButtonSwapSides; + wxPanel* m_panelTopRight; + wxBitmapButton* m_bpButtonAddPair; + wxComboBox* m_directoryRight; + wxDirPickerCtrl* m_dirPickerRight; + wxScrolledWindow* m_scrolledWindowFolderPairs; + wxBoxSizer* bSizerAddFolderPairs; + wxPanel* m_panelLeft; + CustomGridLeft* m_gridLeft; + wxPanel* m_panelMiddle; + CustomGridMiddle* m_gridMiddle; + wxPanel* m_panelRight; + CustomGridRight* m_gridRight; + wxBoxSizer* bSizer3; + wxNotebook* m_notebookBottomLeft; + wxPanel* m_panel30; + wxBitmapButton* m_bpButtonSave; + wxBitmapButton* m_bpButtonLoad; + wxChoice* m_choiceHistory; + wxPanel* m_panelFilter; + wxBitmapButton* m_bpButtonFilter; + wxHyperlinkCtrl* m_hyperlinkCfgFilter; + wxCheckBox* m_checkBoxHideFilt; + wxPanel* m_panel112; + + ToggleButton* m_bpButtonLeftOnly; + ToggleButton* m_bpButtonLeftNewer; + ToggleButton* m_bpButtonEqual; + ToggleButton* m_bpButtonDifferent; + ToggleButton* m_bpButtonRightNewer; + ToggleButton* m_bpButtonRightOnly; + ToggleButton* m_bpButtonSyncCreateLeft; + ToggleButton* m_bpButtonSyncDirOverwLeft; + ToggleButton* m_bpButtonSyncDeleteLeft; + ToggleButton* m_bpButtonSyncDirNone; + ToggleButton* m_bpButtonSyncDeleteRight; + ToggleButton* m_bpButtonSyncDirOverwRight; + ToggleButton* m_bpButtonSyncCreateRight; + ToggleButton* m_bpButtonConflict; + + wxBoxSizer* bSizerBottomRight; + + wxPanel* m_panelSyncPreview; + wxStaticBitmap* m_bitmapCreate; + wxTextCtrl* m_textCtrlCreate; + wxStaticBitmap* m_bitmapDelete; + wxTextCtrl* m_textCtrlDelete; + wxStaticBitmap* m_bitmapUpdate; + wxTextCtrl* m_textCtrlUpdate; + wxStaticBitmap* m_bitmapData; + wxTextCtrl* m_textCtrlData; + wxBitmapButton* m_bpButton10; + wxPanel* m_panel7; + + wxStaticText* m_staticTextStatusLeft; + + wxStaticLine* m_staticline9; + + wxStaticText* m_staticTextStatusMiddle; + + wxStaticLine* m_staticline10; + + wxStaticText* m_staticTextStatusRight; + + wxStaticBitmap* m_bitmap15; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnCompare( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnStartSync( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSwitchView( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnNewConfig( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSaveConfig( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLoadConfig( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuQuit( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuGlobalSettings( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuBatchJob( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuExportFileList( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuCheckVersion( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMenuAbout( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCmpSettings( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncSettings( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnFolderHistoryKeyEvent( wxKeyEvent& event ) + { + event.Skip(); + } + virtual void OnDirSelected( wxFileDirPickerEvent& event ) + { + event.Skip(); + } + virtual void OnSwapSides( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnAddFolderPair( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLeftGridDoubleClick( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnContextRim( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnSortLeftGrid( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnContextRimLabelLeft( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnContextMiddle( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnSortMiddleGrid( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnContextMiddleLabel( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnRightGridDoubleClick( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnSortRightGrid( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnContextRimLabelRight( wxGridEvent& event ) + { + event.Skip(); + } + virtual void OnCfgHistoryKeyEvent( wxKeyEvent& event ) + { + event.Skip(); + } + virtual void OnLoadFromHistory( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnFilterButton( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnConfigureFilter( wxHyperlinkEvent& event ) + { + event.Skip(); + } + virtual void OnHideFilteredButton( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLeftOnlyFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLeftNewerFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnEqualFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDifferentFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRightNewerFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRightOnlyFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncCreateLeft( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncDirLeft( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncDeleteLeft( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncDirNone( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncDeleteRight( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncDirRight( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncCreateRight( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnConflictFiles( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnQuit( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + MainDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("FreeFileSync - Folder Comparison and Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 933,612 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + ~MainDialogGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class FolderPairGenerated /////////////////////////////////////////////////////////////////////////////// -class FolderPairGenerated : public wxPanel +class FolderPairGenerated : public wxPanel { - private: - - protected: - wxPanel* m_panel20; - - wxBitmapButton* m_bpButtonAltFilter; - wxBitmapButton* m_bpButtonAltSyncCfg; - - - public: - wxPanel* m_panelLeft; - wxTextCtrl* m_directoryLeft; - wxDirPickerCtrl* m_dirPickerLeft; - wxPanel* m_panel21; - wxPanel* m_panelRight; - wxBitmapButton* m_bpButtonRemovePair; - wxTextCtrl* m_directoryRight; - wxDirPickerCtrl* m_dirPickerRight; - FolderPairGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~FolderPairGenerated(); - +private: + +protected: + wxPanel* m_panel20; + + wxBitmapButton* m_bpButtonAltFilter; + wxBitmapButton* m_bpButtonAltSyncCfg; + + +public: + wxPanel* m_panelLeft; + wxTextCtrl* m_directoryLeft; + wxDirPickerCtrl* m_dirPickerLeft; + wxPanel* m_panel21; + wxPanel* m_panelRight; + wxBitmapButton* m_bpButtonRemovePair; + wxTextCtrl* m_directoryRight; + wxDirPickerCtrl* m_dirPickerRight; + FolderPairGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~FolderPairGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class BatchFolderPairGenerated /////////////////////////////////////////////////////////////////////////////// -class BatchFolderPairGenerated : public wxPanel +class BatchFolderPairGenerated : public wxPanel { - private: - - protected: - wxPanel* m_panel32; - wxStaticText* m_staticText53; - wxStaticText* m_staticText541; - wxPanel* m_panelLeft; - wxBitmapButton* m_bpButtonAltSyncCfg; - wxPanel* m_panelRight; - wxBitmapButton* m_bpButtonAltFilter; - - - public: - wxBitmapButton* m_bpButtonRemovePair; - wxTextCtrl* m_directoryLeft; - wxDirPickerCtrl* m_dirPickerLeft; - wxTextCtrl* m_directoryRight; - wxDirPickerCtrl* m_dirPickerRight; - BatchFolderPairGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~BatchFolderPairGenerated(); - +private: + +protected: + wxPanel* m_panel32; + wxStaticText* m_staticText53; + wxStaticText* m_staticText541; + wxPanel* m_panelLeft; + wxBitmapButton* m_bpButtonAltSyncCfg; + wxPanel* m_panelRight; + wxBitmapButton* m_bpButtonAltFilter; + + +public: + wxBitmapButton* m_bpButtonRemovePair; + wxTextCtrl* m_directoryLeft; + wxDirPickerCtrl* m_dirPickerLeft; + wxTextCtrl* m_directoryRight; + wxDirPickerCtrl* m_dirPickerRight; + BatchFolderPairGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~BatchFolderPairGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class BatchDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class BatchDlgGenerated : public wxDialog +class BatchDlgGenerated : public wxDialog { - private: - - protected: - wxBoxSizer* bSizer69; - wxStaticBitmap* m_bitmap27; - wxPanel* m_panel8; - wxStaticText* m_staticText56; - - - wxStaticText* m_staticText54; - - wxStaticLine* m_staticline10; - wxStaticText* m_staticText531; - wxNotebook* m_notebookSettings; - wxPanel* m_panelOverview; - wxScrolledWindow* m_scrolledWindow6; - wxBoxSizer* sbSizerMainPair; - wxPanel* m_panelMainPair; - wxStaticText* m_staticText532; - wxStaticText* m_staticText5411; - wxPanel* m_panelLeft; - wxPanel* m_panelRight; - wxBoxSizer* bSizerAddFolderPairs; - - wxRadioButton* m_radioBtnSizeDate; - wxRadioButton* m_radioBtnContent; - - wxCheckBox* m_checkBoxFilter; - wxCheckBox* m_checkBoxSilent; - - wxChoice* m_choiceHandleError; - wxChoice* m_choiceHandleDeletion; - wxPanel* m_panelCustomDeletionDir; - wxTextCtrl* m_textCtrlCustomDelFolder; - wxDirPickerCtrl* m_dirPickerCustomDelFolder; - - wxStaticText* m_staticText21; - wxStaticText* m_staticText31; - wxStaticLine* m_staticline3; - wxStaticBitmap* m_bitmapLeftOnly; - - wxBitmapButton* m_bpButtonLeftOnly; - wxStaticBitmap* m_bitmapRightOnly; - - wxBitmapButton* m_bpButtonRightOnly; - wxStaticBitmap* m_bitmapLeftNewer; - - wxBitmapButton* m_bpButtonLeftNewer; - wxStaticBitmap* m_bitmapRightNewer; - - wxBitmapButton* m_bpButtonRightNewer; - wxStaticBitmap* m_bitmapDifferent; - - wxBitmapButton* m_bpButtonDifferent; - wxStaticBitmap* m_bitmapConflict; - - wxBitmapButton* m_bpButtonConflict; - wxPanel* m_panelFilter; - - wxStaticText* m_staticText15; - wxStaticBitmap* m_bitmap8; - wxTextCtrl* m_textCtrlInclude; - - wxStaticText* m_staticText16; - wxStaticBitmap* m_bitmap9; - wxTextCtrl* m_textCtrlExclude; - wxPanel* m_panelLogging; - wxStaticText* m_staticText120; - wxTextCtrl* m_textCtrlLogfileDir; - wxDirPickerCtrl* m_dirPickerLogfileDir; - wxButton* m_buttonSave; - wxButton* m_buttonLoad; - wxButton* m_button6; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnAddFolderPair( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeCompareVar( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCheckFilter( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCheckLogging( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeErrorHandling( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeDeletionHandling( wxCommandEvent& event ){ event.Skip(); } - virtual void OnExLeftSideOnly( wxCommandEvent& event ){ event.Skip(); } - virtual void OnExRightSideOnly( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLeftNewer( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRightNewer( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDifferent( wxCommandEvent& event ){ event.Skip(); } - virtual void OnConflict( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSaveBatchJob( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLoadBatchJob( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - wxBitmapButton* m_bpButtonAddPair; - wxTextCtrl* m_directoryLeft; - wxDirPickerCtrl* m_dirPickerLeft; - wxTextCtrl* m_directoryRight; - wxDirPickerCtrl* m_dirPickerRight; - BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Create a batch job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~BatchDlgGenerated(); - +private: + +protected: + wxBoxSizer* bSizer69; + wxStaticBitmap* m_bitmap27; + wxPanel* m_panel8; + wxStaticText* m_staticText56; + + + wxStaticText* m_staticText54; + + wxStaticLine* m_staticline10; + wxStaticText* m_staticText531; + wxNotebook* m_notebookSettings; + wxPanel* m_panelOverview; + wxScrolledWindow* m_scrolledWindow6; + wxBoxSizer* sbSizerMainPair; + wxPanel* m_panelMainPair; + wxStaticText* m_staticText532; + wxStaticText* m_staticText5411; + wxPanel* m_panelLeft; + wxPanel* m_panelRight; + wxBoxSizer* bSizerAddFolderPairs; + + + wxRadioButton* m_radioBtnSizeDate; + wxRadioButton* m_radioBtnContent; + + + wxCheckBox* m_checkBoxAutomatic; + wxCheckBox* m_checkBoxFilter; + wxCheckBox* m_checkBoxSilent; + + wxChoice* m_choiceHandleError; + wxChoice* m_choiceHandleDeletion; + wxPanel* m_panelCustomDeletionDir; + wxTextCtrl* m_textCtrlCustomDelFolder; + wxDirPickerCtrl* m_dirPickerCustomDelFolder; + + wxStaticBoxSizer* sbSizerSyncDirections; + wxStaticText* m_staticText21; + wxStaticText* m_staticText31; + wxStaticLine* m_staticline3; + wxStaticBitmap* m_bitmapLeftOnly; + + wxBitmapButton* m_bpButtonLeftOnly; + wxStaticBitmap* m_bitmapRightOnly; + + wxBitmapButton* m_bpButtonRightOnly; + wxStaticBitmap* m_bitmapLeftNewer; + + wxBitmapButton* m_bpButtonLeftNewer; + wxStaticBitmap* m_bitmapRightNewer; + + wxBitmapButton* m_bpButtonRightNewer; + wxStaticBitmap* m_bitmapDifferent; + + wxBitmapButton* m_bpButtonDifferent; + wxStaticBitmap* m_bitmapConflict; + + wxBitmapButton* m_bpButtonConflict; + wxPanel* m_panelFilter; + + wxStaticText* m_staticText15; + wxStaticBitmap* m_bitmap8; + wxTextCtrl* m_textCtrlInclude; + + wxStaticText* m_staticText16; + wxStaticBitmap* m_bitmap9; + wxTextCtrl* m_textCtrlExclude; + wxPanel* m_panelLogging; + wxStaticText* m_staticText120; + wxTextCtrl* m_textCtrlLogfileDir; + wxDirPickerCtrl* m_dirPickerLogfileDir; + wxButton* m_buttonSave; + wxButton* m_buttonLoad; + wxButton* m_button6; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnAddFolderPair( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnChangeCompareVar( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCheckAutomatic( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCheckFilter( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCheckSilent( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnChangeErrorHandling( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnChangeDeletionHandling( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnExLeftSideOnly( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnExRightSideOnly( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLeftNewer( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRightNewer( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDifferent( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnConflict( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSaveBatchJob( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLoadBatchJob( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + wxBitmapButton* m_bpButtonAddPair; + wxTextCtrl* m_directoryLeft; + wxDirPickerCtrl* m_dirPickerLeft; + wxTextCtrl* m_directoryRight; + wxDirPickerCtrl* m_dirPickerRight; + BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Create a batch job"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~BatchDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class CompareStatusGenerated /////////////////////////////////////////////////////////////////////////////// -class CompareStatusGenerated : public wxPanel +class CompareStatusGenerated : public wxPanel { - private: - - protected: - wxBoxSizer* bSizer42; - wxStaticText* m_staticText321; - wxStaticText* m_staticTextScanned; - - wxStaticBoxSizer* sbSizer13; - wxStaticText* m_staticText46; - wxStaticText* m_staticTextFilesRemaining; - wxStaticText* m_staticText32; - wxStaticText* m_staticTextDataRemaining; - wxStaticText* m_staticText104; - wxStaticText* m_staticTextSpeed; - wxStaticText* m_staticText103; - wxStaticText* m_staticTextTimeRemaining; - - wxStaticText* m_staticText37; - wxStaticText* m_staticTextTimeElapsed; - wxStaticText* m_staticText30; - wxTextCtrl* m_textCtrlStatus; - wxGauge* m_gauge2; - - public: - CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); - ~CompareStatusGenerated(); - +private: + +protected: + wxBoxSizer* bSizer42; + wxStaticText* m_staticText321; + wxStaticText* m_staticTextScanned; + + wxStaticBoxSizer* sbSizer13; + wxStaticText* m_staticText46; + wxStaticText* m_staticTextFilesRemaining; + wxStaticText* m_staticText32; + wxStaticText* m_staticTextDataRemaining; + wxStaticText* m_staticText104; + wxStaticText* m_staticTextSpeed; + wxStaticText* m_staticText103; + wxStaticText* m_staticTextTimeRemaining; + + wxStaticText* m_staticText37; + wxStaticText* m_staticTextTimeElapsed; + wxStaticText* m_staticText30; + wxTextCtrl* m_textCtrlStatus; + wxGauge* m_gauge2; + +public: + CompareStatusGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + ~CompareStatusGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class SyncCfgDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class SyncCfgDlgGenerated : public wxDialog +class SyncCfgDlgGenerated : public wxDialog { - private: - - protected: - wxStaticText* m_staticText1; - wxRadioButton* m_radioBtn1; - wxButton* m_buttonOneWay; - wxStaticText* m_staticText8; - wxRadioButton* m_radioBtnUpdate; - wxButton* m_buttonUpdate; - wxStaticText* m_staticText101; - wxRadioButton* m_radioBtn2; - wxButton* m_buttonTwoWay; - wxStaticText* m_staticText10; - wxRadioButton* m_radioBtn3; - - wxStaticText* m_staticText23; - - wxStaticText* m_staticText9; - - wxBoxSizer* bSizer201; - wxStaticBoxSizer* sbSizerErrorHandling; - wxChoice* m_choiceHandleError; - wxChoice* m_choiceHandleDeletion; - wxPanel* m_panelCustomDeletionDir; - wxTextCtrl* m_textCtrlCustomDelFolder; - wxDirPickerCtrl* m_dirPickerCustomDelFolder; - - wxButton* m_buttonApply; - wxButton* m_button16; - - - wxStaticText* m_staticText21; - wxStaticText* m_staticText31; - wxStaticLine* m_staticline3; - wxStaticBitmap* m_bitmapLeftOnly; - - wxBitmapButton* m_bpButtonLeftOnly; - wxStaticBitmap* m_bitmapRightOnly; - - wxBitmapButton* m_bpButtonRightOnly; - wxStaticBitmap* m_bitmapLeftNewer; - - wxBitmapButton* m_bpButtonLeftNewer; - wxStaticBitmap* m_bitmapRightNewer; - - wxBitmapButton* m_bpButtonRightNewer; - wxStaticBitmap* m_bitmapDifferent; - - wxBitmapButton* m_bpButtonDifferent; - wxStaticBitmap* m_bitmapConflict; - - wxBitmapButton* m_bpButtonConflict; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnSyncLeftToRight( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncUpdate( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncBothSides( wxCommandEvent& event ){ event.Skip(); } - virtual void OnSyncCostum( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeErrorHandling( wxCommandEvent& event ){ event.Skip(); } - virtual void OnChangeDeletionHandling( wxCommandEvent& event ){ event.Skip(); } - virtual void OnApply( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - virtual void OnExLeftSideOnly( wxCommandEvent& event ){ event.Skip(); } - virtual void OnExRightSideOnly( wxCommandEvent& event ){ event.Skip(); } - virtual void OnLeftNewer( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRightNewer( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDifferent( wxCommandEvent& event ){ event.Skip(); } - virtual void OnConflict( wxCommandEvent& event ){ event.Skip(); } - - - public: - SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~SyncCfgDlgGenerated(); - +private: + +protected: + wxStaticText* m_staticText1; + wxRadioButton* m_radioBtnAutomatic; + wxButton* m_buttonAutomatic; + wxStaticText* m_staticText81; + wxRadioButton* m_radioBtnMirror; + wxButton* m_buttonOneWay; + wxStaticText* m_staticText8; + wxRadioButton* m_radioBtnUpdate; + wxButton* m_buttonUpdate; + wxStaticText* m_staticText101; + wxRadioButton* m_radioBtnTwoWay; + wxButton* m_buttonTwoWay; + wxStaticText* m_staticText10; + wxRadioButton* m_radioBtnCustom; + + wxStaticText* m_staticText23; + + wxStaticText* m_staticText9; + + wxBoxSizer* bSizer201; + wxStaticBoxSizer* sbSizerErrorHandling; + wxChoice* m_choiceHandleError; + wxChoice* m_choiceHandleDeletion; + wxPanel* m_panelCustomDeletionDir; + wxTextCtrl* m_textCtrlCustomDelFolder; + wxDirPickerCtrl* m_dirPickerCustomDelFolder; + + wxButton* m_buttonApply; + wxButton* m_button16; + + + wxStaticBoxSizer* sbSizerSyncDirections; + wxStaticText* m_staticText21; + wxStaticText* m_staticText31; + wxStaticLine* m_staticline3; + wxStaticBitmap* m_bitmapLeftOnly; + + wxBitmapButton* m_bpButtonLeftOnly; + wxStaticBitmap* m_bitmapRightOnly; + + wxBitmapButton* m_bpButtonRightOnly; + wxStaticBitmap* m_bitmapLeftNewer; + + wxBitmapButton* m_bpButtonLeftNewer; + wxStaticBitmap* m_bitmapRightNewer; + + wxBitmapButton* m_bpButtonRightNewer; + wxStaticBitmap* m_bitmapDifferent; + + wxBitmapButton* m_bpButtonDifferent; + wxStaticBitmap* m_bitmapConflict; + + wxBitmapButton* m_bpButtonConflict; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnSyncAutomatic( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncLeftToRight( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncUpdate( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnSyncBothSides( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnChangeErrorHandling( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnChangeDeletionHandling( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnApply( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnExLeftSideOnly( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnExRightSideOnly( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnLeftNewer( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRightNewer( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDifferent( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnConflict( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~SyncCfgDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class CmpCfgDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class CmpCfgDlgGenerated : public wxDialog +class CmpCfgDlgGenerated : public wxDialog { - private: - - protected: - wxRadioButton* m_radioBtnSizeDate; - wxButton* m_buttonTimeSize; - wxRadioButton* m_radioBtnContent; - wxButton* m_buttonContent; - wxStaticLine* m_staticline14; - wxBitmapButton* m_bpButtonHelp; - - wxButton* m_button6; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnTimeSize( wxCommandEvent& event ){ event.Skip(); } - virtual void OnContent( wxCommandEvent& event ){ event.Skip(); } - virtual void OnShowHelp( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Comparison settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~CmpCfgDlgGenerated(); - +private: + +protected: + wxRadioButton* m_radioBtnSizeDate; + wxButton* m_buttonTimeSize; + wxRadioButton* m_radioBtnContent; + wxButton* m_buttonContent; + wxStaticLine* m_staticline14; + wxBitmapButton* m_bpButtonHelp; + + wxButton* m_button6; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnTimeSize( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnContent( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnShowHelp( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + CmpCfgDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Comparison settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~CmpCfgDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class SyncStatusDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class SyncStatusDlgGenerated : public wxDialog +class SyncStatusDlgGenerated : public wxDialog { - private: - - protected: - - wxAnimationCtrl* m_animationControl1; - wxPanel* m_panel8; - wxStaticText* m_staticText56; - - wxStaticBitmap* m_bitmapStatus; - wxStaticText* m_staticTextStatus; - - wxBoxSizer* bSizer31; - wxStaticText* m_staticText21; - - wxStaticText* m_staticText55; - wxStaticText* m_staticTextTimeElapsed; - wxTextCtrl* m_textCtrlInfo; - wxBoxSizer* bSizer28; - wxStaticText* m_staticText25; - wxStaticText* m_staticTextRemainingObj; - wxBoxSizer* bSizerSpeed; - wxStaticText* m_staticText108; - wxStaticText* m_staticTextSpeed; - - wxButton* m_buttonOK; - wxButton* m_buttonPause; - wxButton* m_buttonAbort; - - wxStaticText* m_staticText26; - wxStaticText* m_staticTextDataRemaining; - wxBoxSizer* bSizerRemTime; - wxStaticText* m_staticText106; - wxStaticText* m_staticTextTimeRemaining; - - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ){ event.Skip(); } - virtual void OnPause( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAbort( wxCommandEvent& event ){ event.Skip(); } - - - public: - wxGauge* m_gauge1; - SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 638,376 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~SyncStatusDlgGenerated(); - +private: + +protected: + + wxAnimationCtrl* m_animationControl1; + wxPanel* m_panel8; + wxStaticText* m_staticText56; + + wxStaticBitmap* m_bitmapStatus; + wxStaticText* m_staticTextStatus; + + wxBoxSizer* bSizer31; + wxStaticText* m_staticText21; + + wxStaticText* m_staticText55; + wxStaticText* m_staticTextTimeElapsed; + wxTextCtrl* m_textCtrlInfo; + wxBoxSizer* bSizer28; + wxStaticText* m_staticText25; + wxStaticText* m_staticTextRemainingObj; + wxBoxSizer* bSizerSpeed; + wxStaticText* m_staticText108; + wxStaticText* m_staticTextSpeed; + + wxButton* m_buttonOK; + wxButton* m_buttonPause; + wxButton* m_buttonAbort; + + wxStaticText* m_staticText26; + wxStaticText* m_staticTextDataRemaining; + wxBoxSizer* bSizerRemTime; + wxStaticText* m_staticText106; + wxStaticText* m_staticTextTimeRemaining; + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnOkay( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnPause( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnAbort( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + wxGauge* m_gauge1; + SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 638,376 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~SyncStatusDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class HelpDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class HelpDlgGenerated : public wxDialog +class HelpDlgGenerated : public wxDialog { - private: - - protected: - - wxStaticBitmap* m_bitmap25; - wxPanel* m_panel8; - - wxStaticText* m_staticText56; - - - wxNotebook* m_notebook1; - wxScrolledWindow* m_scrolledWindow1; - wxStaticText* m_staticText59; - wxStaticText* m_staticText60; - wxStaticText* m_staticText61; - wxTreeCtrl* m_treeCtrl1; - wxStaticText* m_staticText63; - wxStaticText* m_staticText75; - wxStaticText* m_staticText76; - wxStaticText* m_staticText77; - wxStaticText* m_staticText79; - wxStaticText* m_staticText80; - wxStaticText* m_staticText78; - wxScrolledWindow* m_scrolledWindow5; - wxStaticText* m_staticText65; - wxStaticText* m_staticText66; - wxTreeCtrl* m_treeCtrl2; - wxStaticText* m_staticText69; - wxStaticText* m_staticText81; - wxStaticText* m_staticText82; - wxStaticText* m_staticText83; - wxStaticText* m_staticText84; - wxButton* m_button8; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnOK( wxCommandEvent& event ){ event.Skip(); } - - - public: - HelpDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 565,501 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~HelpDlgGenerated(); - +private: + +protected: + + wxStaticBitmap* m_bitmap25; + wxPanel* m_panel8; + + wxStaticText* m_staticText56; + + + wxNotebook* m_notebook1; + wxScrolledWindow* m_scrolledWindow1; + wxStaticText* m_staticText59; + wxStaticText* m_staticText60; + wxStaticText* m_staticText61; + wxTreeCtrl* m_treeCtrl1; + wxStaticText* m_staticText63; + wxStaticText* m_staticText75; + wxStaticText* m_staticText76; + wxStaticText* m_staticText77; + wxStaticText* m_staticText79; + wxStaticText* m_staticText80; + wxStaticText* m_staticText78; + wxScrolledWindow* m_scrolledWindow5; + wxStaticText* m_staticText65; + wxStaticText* m_staticText66; + wxTreeCtrl* m_treeCtrl2; + wxStaticText* m_staticText69; + wxStaticText* m_staticText81; + wxStaticText* m_staticText82; + wxStaticText* m_staticText83; + wxStaticText* m_staticText84; + wxButton* m_button8; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnOK( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + HelpDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 565,501 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~HelpDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class AboutDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class AboutDlgGenerated : public wxDialog +class AboutDlgGenerated : public wxDialog { - private: - - protected: - - wxPanel* m_panel5; - wxStaticBitmap* m_bitmap11; - wxStaticText* m_staticText15; - wxStaticText* m_build; - - wxScrolledWindow* m_scrolledWindowCodeInfo; - wxBoxSizer* bSizerCodeInfo; - wxStaticText* m_staticText72; - wxStaticText* m_staticText73; - wxStaticText* m_staticText74; - wxScrolledWindow* m_scrolledWindowTranslators; - wxBoxSizer* bSizerTranslators; - wxStaticText* m_staticText54; - - wxFlexGridSizer* fgSizerTranslators; - wxStaticLine* m_staticline3; - wxStaticText* m_staticText131; - wxStaticLine* m_staticline12; - wxStaticBitmap* m_bitmap9; - wxHyperlinkCtrl* m_hyperlink1; - - wxHyperlinkCtrl* m_hyperlink6; - wxStaticBitmap* m_bitmap10; - wxHyperlinkCtrl* m_hyperlink2; - - wxAnimationCtrl* m_animationControl1; - wxHyperlinkCtrl* m_hyperlink3; - wxStaticLine* m_staticline2; - - wxStaticBitmap* m_bitmap13; - wxHyperlinkCtrl* m_hyperlink5; - - wxButton* m_buttonOkay; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnOK( wxCommandEvent& event ){ event.Skip(); } - - - public: - AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); - ~AboutDlgGenerated(); - +private: + +protected: + + wxPanel* m_panel5; + wxStaticBitmap* m_bitmap11; + wxStaticText* m_staticText15; + wxStaticText* m_build; + + wxScrolledWindow* m_scrolledWindowCodeInfo; + wxBoxSizer* bSizerCodeInfo; + wxStaticText* m_staticText72; + wxStaticText* m_staticText73; + wxStaticText* m_staticText74; + wxScrolledWindow* m_scrolledWindowTranslators; + wxBoxSizer* bSizerTranslators; + wxStaticText* m_staticText54; + + wxFlexGridSizer* fgSizerTranslators; + wxStaticLine* m_staticline3; + wxStaticText* m_staticText131; + wxStaticLine* m_staticline12; + wxStaticBitmap* m_bitmap9; + wxHyperlinkCtrl* m_hyperlink1; + + wxHyperlinkCtrl* m_hyperlink6; + wxStaticBitmap* m_bitmap10; + wxHyperlinkCtrl* m_hyperlink2; + + wxAnimationCtrl* m_animationControl1; + wxHyperlinkCtrl* m_hyperlink3; + wxStaticLine* m_staticline2; + + wxStaticBitmap* m_bitmap13; + wxHyperlinkCtrl* m_hyperlink5; + + wxButton* m_buttonOkay; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnOK( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + AboutDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~AboutDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class ErrorDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class ErrorDlgGenerated : public wxDialog +class ErrorDlgGenerated : public wxDialog { - private: - - protected: - - wxStaticBitmap* m_bitmap10; - wxTextCtrl* m_textCtrl8; - wxCheckBox* m_checkBoxIgnoreErrors; - - wxButton* m_buttonIgnore; - wxButton* m_buttonRetry; - wxButton* m_buttonAbort; - - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnIgnore( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRetry( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAbort( wxCommandEvent& event ){ event.Skip(); } - - - public: - ErrorDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Error"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 420,270 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~ErrorDlgGenerated(); - +private: + +protected: + + wxStaticBitmap* m_bitmap10; + wxTextCtrl* m_textCtrl8; + wxCheckBox* m_checkBoxIgnoreErrors; + + wxButton* m_buttonIgnore; + wxButton* m_buttonRetry; + wxButton* m_buttonAbort; + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnIgnore( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRetry( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnAbort( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + ErrorDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Error"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 421,228 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~ErrorDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class WarningDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class WarningDlgGenerated : public wxDialog +class WarningDlgGenerated : public wxDialog { - private: - - protected: - - wxTextCtrl* m_textCtrl8; - - wxCheckBox* m_checkBoxDontShowAgain; - - wxButton* m_buttonIgnore; - wxButton* m_buttonAbort; - - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnIgnore( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAbort( wxCommandEvent& event ){ event.Skip(); } - - - public: - wxStaticBitmap* m_bitmap10; - WarningDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Warning"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 420,270 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~WarningDlgGenerated(); - +private: + +protected: + + wxTextCtrl* m_textCtrl8; + wxCheckBox* m_checkBoxDontShowAgain; + + wxButton* m_buttonIgnore; + wxButton* m_buttonAbort; + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnIgnore( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnAbort( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + wxStaticBitmap* m_bitmap10; + WarningDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Warning"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 421,231 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~WarningDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class QuestionDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class QuestionDlgGenerated : public wxDialog +class QuestionDlgGenerated : public wxDialog { - private: - - protected: - - wxStaticBitmap* m_bitmap10; - wxTextCtrl* m_textCtrl8; - wxCheckBox* m_checkBoxDontAskAgain; - - wxButton* m_buttonYes; - wxButton* m_buttonNo; - wxButton* m_buttonCancel; - - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnYes( wxCommandEvent& event ){ event.Skip(); } - virtual void OnNo( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - QuestionDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Question"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 420,260 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~QuestionDlgGenerated(); - +private: + +protected: + + wxStaticBitmap* m_bitmap10; + wxTextCtrl* m_textCtrl8; + wxCheckBox* m_checkBoxDontAskAgain; + + wxButton* m_buttonYes; + wxButton* m_buttonNo; + wxButton* m_buttonCancel; + + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnYes( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnNo( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + QuestionDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Question"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 420,198 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~QuestionDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class DeleteDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class DeleteDlgGenerated : public wxDialog +class DeleteDlgGenerated : public wxDialog { - private: - - protected: - - - wxStaticBitmap* m_bitmap12; - wxStaticText* m_staticTextHeader; - - wxCheckBox* m_checkBoxDeleteBothSides; - - wxCheckBox* m_checkBoxUseRecycler; - wxTextCtrl* m_textCtrlMessage; - wxButton* m_buttonOK; - wxButton* m_buttonCancel; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnDelOnBothSides( wxCommandEvent& 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: - DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Confirm"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 553,336 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~DeleteDlgGenerated(); - +private: + +protected: + + + wxStaticBitmap* m_bitmap12; + wxStaticText* m_staticTextHeader; + + wxCheckBox* m_checkBoxDeleteBothSides; + + wxCheckBox* m_checkBoxUseRecycler; + wxTextCtrl* m_textCtrlMessage; + wxButton* m_buttonOK; + wxButton* m_buttonCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnDelOnBothSides( wxCommandEvent& 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: + DeleteDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Confirm"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 553,336 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DeleteDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class FilterDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class FilterDlgGenerated : public wxDialog +class FilterDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmap26; - wxPanel* m_panel8; - wxStaticText* m_staticText56; - - wxStaticText* m_staticText44; - wxBitmapButton* m_bpButtonHelp; - - wxPanel* m_panel13; - wxStaticLine* m_staticline10; - wxStaticText* m_staticText45; - wxStaticText* m_staticText83; - wxStaticText* m_staticText84; - wxStaticText* m_staticText85; - wxStaticText* m_staticText181; - wxStaticText* m_staticText1811; - - wxStaticText* m_staticText15; - wxStaticBitmap* m_bitmap8; - wxTextCtrl* m_textCtrlInclude; - - wxStaticText* m_staticText16; - wxStaticBitmap* m_bitmap9; - wxTextCtrl* m_textCtrlExclude; - - wxButton* m_button9; - - wxButton* m_button10; - wxButton* m_button17; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnHelp( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDefault( wxCommandEvent& event ){ event.Skip(); } - virtual void OnApply( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Configure filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~FilterDlgGenerated(); - +private: + +protected: + wxStaticBitmap* m_bitmap26; + wxPanel* m_panel8; + wxStaticText* m_staticText56; + + wxStaticText* m_staticText44; + wxBitmapButton* m_bpButtonHelp; + + wxPanel* m_panel13; + wxStaticLine* m_staticline10; + wxStaticText* m_staticText45; + wxStaticText* m_staticText83; + wxStaticText* m_staticText84; + wxStaticText* m_staticText85; + wxStaticText* m_staticText181; + wxStaticText* m_staticText1811; + + wxStaticText* m_staticText15; + wxStaticBitmap* m_bitmap8; + wxTextCtrl* m_textCtrlInclude; + + wxStaticText* m_staticText16; + wxStaticBitmap* m_bitmap9; + wxTextCtrl* m_textCtrlExclude; + + wxButton* m_button9; + + wxButton* m_button10; + wxButton* m_button17; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnHelp( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDefault( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnApply( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + FilterDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Configure filter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~FilterDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class CustomizeColsDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class CustomizeColsDlgGenerated : public wxDialog +class CustomizeColsDlgGenerated : public wxDialog { - private: - - protected: - wxCheckListBox* m_checkListColumns; - wxBitmapButton* m_bpButton29; - wxBitmapButton* m_bpButton30; - wxCheckBox* m_checkBoxShowFileIcons; - wxButton* m_button28; - wxButton* m_button9; - wxButton* m_button29; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnMoveUp( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMoveDown( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDefault( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - CustomizeColsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Customize columns"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~CustomizeColsDlgGenerated(); - +private: + +protected: + wxCheckListBox* m_checkListColumns; + wxBitmapButton* m_bpButton29; + wxBitmapButton* m_bpButton30; + wxCheckBox* m_checkBoxShowFileIcons; + wxButton* m_button28; + wxButton* m_button9; + wxButton* m_button29; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnMoveUp( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnMoveDown( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnOkay( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDefault( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + CustomizeColsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Customize columns"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~CustomizeColsDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class GlobalSettingsDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class GlobalSettingsDlgGenerated : public wxDialog +class GlobalSettingsDlgGenerated : public wxDialog { - private: - - protected: - wxStaticBitmap* m_bitmapSettings; - - wxPanel* m_panel8; - wxStaticText* m_staticText56; - - wxStaticText* m_staticText114; - - wxCheckBox* m_checkBoxIgnoreOneHour; - wxStaticLine* m_staticline10; - wxStaticText* m_staticText100; - - wxButtonWithImage* m_buttonResetDialogs; - - - wxGrid* m_gridCustomCommand; - wxBitmapButton* m_bpButtonAddRow; - wxBitmapButton* m_bpButtonRemoveRow; - - wxButton* m_buttonOkay; - wxButton* m_button9; - wxButton* m_button29; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnResetDialogs( wxCommandEvent& event ){ event.Skip(); } - virtual void OnAddRow( wxCommandEvent& event ){ event.Skip(); } - virtual void OnRemoveRow( wxCommandEvent& event ){ event.Skip(); } - virtual void OnOkay( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDefault( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - GlobalSettingsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Global settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~GlobalSettingsDlgGenerated(); - +private: + +protected: + wxStaticBitmap* m_bitmapSettings; + + wxPanel* m_panel8; + wxStaticText* m_staticText56; + + wxStaticText* m_staticText114; + + wxCheckBox* m_checkBoxIgnoreOneHour; + wxStaticLine* m_staticline10; + wxStaticText* m_staticText100; + + wxButtonWithImage* m_buttonResetDialogs; + + + wxGrid* m_gridCustomCommand; + wxBitmapButton* m_bpButtonAddRow; + wxBitmapButton* m_bpButtonRemoveRow; + + wxButton* m_buttonOkay; + wxButton* m_button9; + wxButton* m_button29; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnResetDialogs( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnAddRow( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnRemoveRow( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnOkay( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnDefault( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + GlobalSettingsDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Global settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~GlobalSettingsDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class SyncPreviewDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class SyncPreviewDlgGenerated : public wxDialog +class SyncPreviewDlgGenerated : public wxDialog { - private: - - protected: - wxButtonWithImage* m_buttonStartSync; - wxStaticLine* m_staticline16; - wxStaticText* m_staticTextVariant; - wxStaticLine* m_staticline14; - - wxStaticText* m_staticText94; - wxStaticBitmap* m_bitmapCreate; - wxTextCtrl* m_textCtrlCreateL; - wxStaticBitmap* m_bitmapUpdate; - wxTextCtrl* m_textCtrlUpdateL; - wxStaticBitmap* m_bitmapDelete; - wxTextCtrl* m_textCtrlDeleteL; - wxStaticText* m_staticText95; - wxTextCtrl* m_textCtrlCreateR; - wxTextCtrl* m_textCtrlUpdateR; - wxTextCtrl* m_textCtrlDeleteR; - - wxStaticBitmap* m_bitmapData; - - wxTextCtrl* m_textCtrlData; - - wxStaticLine* m_staticline12; - wxCheckBox* m_checkBoxDontShowAgain; - - wxButton* m_button16; - - // Virtual event handlers, overide them in your derived class - virtual void OnClose( wxCloseEvent& event ){ event.Skip(); } - virtual void OnStartSync( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } - - - public: - SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization Preview"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~SyncPreviewDlgGenerated(); - +private: + +protected: + wxButtonWithImage* m_buttonStartSync; + wxStaticLine* m_staticline16; + wxStaticText* m_staticTextVariant; + wxStaticLine* m_staticline14; + + wxStaticText* m_staticText94; + wxStaticBitmap* m_bitmapCreate; + wxTextCtrl* m_textCtrlCreateL; + wxStaticBitmap* m_bitmapUpdate; + wxTextCtrl* m_textCtrlUpdateL; + wxStaticBitmap* m_bitmapDelete; + wxTextCtrl* m_textCtrlDeleteL; + wxStaticText* m_staticText95; + wxTextCtrl* m_textCtrlCreateR; + wxTextCtrl* m_textCtrlUpdateR; + wxTextCtrl* m_textCtrlDeleteR; + + wxStaticBitmap* m_bitmapData; + + wxTextCtrl* m_textCtrlData; + + wxStaticLine* m_staticline12; + wxCheckBox* m_checkBoxDontShowAgain; + + wxButton* m_button16; + + // Virtual event handlers, overide them in your derived class + virtual void OnClose( wxCloseEvent& event ) + { + event.Skip(); + } + virtual void OnStartSync( wxCommandEvent& event ) + { + event.Skip(); + } + virtual void OnCancel( wxCommandEvent& event ) + { + event.Skip(); + } + + +public: + SyncPreviewDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Synchronization Preview"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); + ~SyncPreviewDlgGenerated(); + }; /////////////////////////////////////////////////////////////////////////////// /// Class PopupFrameGenerated1 /////////////////////////////////////////////////////////////////////////////// -class PopupFrameGenerated1 : public wxFrame +class PopupFrameGenerated1 : public wxFrame { - private: - - protected: - - public: - wxStaticBitmap* m_bitmapLeft; - wxStaticText* m_staticTextMain; - PopupFrameGenerated1( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP|wxSTATIC_BORDER ); - ~PopupFrameGenerated1(); - +private: + +protected: + +public: + wxStaticBitmap* m_bitmapLeft; + wxStaticText* m_staticTextMain; + PopupFrameGenerated1( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP|wxSTATIC_BORDER ); + ~PopupFrameGenerated1(); + }; #endif //__guiGenerated__ diff --git a/ui/guiStatusHandler.cpp b/ui/guiStatusHandler.cpp index 4e69b66e..c4c98a85 100644 --- a/ui/guiStatusHandler.cpp +++ b/ui/guiStatusHandler.cpp @@ -7,9 +7,9 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) : - mainDialog(dlg), - ignoreErrors(false), - currentProcess(StatusHandler::PROCESS_NONE) + mainDialog(dlg), + ignoreErrors(false), + currentProcess(StatusHandler::PROCESS_NONE) { wxWindowUpdateLocker dummy(mainDialog); //avoid display distortion @@ -189,7 +189,7 @@ void CompareStatusHandler::abortThisProcess() SyncStatusHandler::SyncStatusHandler(wxWindow* dlg, bool ignoreAllErrors) : - ignoreErrors(ignoreAllErrors) + ignoreErrors(ignoreAllErrors) { syncStatusFrame = new SyncStatus(this, dlg); syncStatusFrame->Show(); @@ -224,20 +224,17 @@ SyncStatusHandler::~SyncStatusHandler() if (abortIsRequested()) { result += wxString(_("Synchronization aborted!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"); - syncStatusFrame->setStatusText_NoUpdate(result.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::ABORTED); //enable okay and close events + syncStatusFrame->processHasFinished(SyncStatus::ABORTED, result); //enable okay and close events } else if (errorLog.errorsTotal() > 0) { result += wxString(_("Synchronization completed with errors!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"); - syncStatusFrame->setStatusText_NoUpdate(result.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR, result); } else { result += _("Synchronization completed successfully!"); - syncStatusFrame->setStatusText_NoUpdate(result.c_str()); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS, result); } } diff --git a/ui/SyncDialog.cpp b/ui/settingsDialog.cpp index 8f5066c5..250fbe68 100644 --- a/ui/SyncDialog.cpp +++ b/ui/settingsDialog.cpp @@ -1,10 +1,12 @@ -#include "syncDialog.h" +#include "settingsDialog.h" #include "../shared/systemConstants.h" #include "../library/resources.h" #include <wx/msgdlg.h> #include "../shared/customButton.h" #include "../synchronization.h" -#include "../algorithm.h" +//#include "../algorithm.h" +#include "../shared/stringConv.h" +#include "util.h" #include <wx/dnd.h> #include "../shared/dragAndDrop.h" #include "../shared/fileHandling.h" @@ -21,14 +23,14 @@ SyncCfgDialog::SyncCfgDialog(wxWindow* window, DeletionPolicy& handleDeletion, wxString& customDeletionDirectory, bool* ignoreErrors) : - SyncCfgDlgGenerated(window), - cmpVariant(compareVar), - localSyncConfiguration(syncConfiguration), //make working copy of syncConfiguration - refSyncConfiguration(syncConfiguration), - refHandleDeletion(handleDeletion), - refCustomDeletionDirectory(customDeletionDirectory), - refIgnoreErrors(ignoreErrors), - dragDropCustomDelFolder(new DragDropOnDlg(m_panelCustomDeletionDir, m_dirPickerCustomDelFolder, m_textCtrlCustomDelFolder)) + SyncCfgDlgGenerated(window), + cmpVariant(compareVar), + localSyncConfiguration(syncConfiguration), //make working copy of syncConfiguration + refSyncConfiguration(syncConfiguration), + refHandleDeletion(handleDeletion), + refCustomDeletionDirectory(customDeletionDirectory), + refIgnoreErrors(ignoreErrors), + dragDropCustomDelFolder(new DragDropOnDlg(m_panelCustomDeletionDir, m_dirPickerCustomDelFolder, m_textCtrlCustomDelFolder)) { setDeletionHandling(handleDeletion); m_textCtrlCustomDelFolder->SetValue(customDeletionDirectory); @@ -55,23 +57,6 @@ SyncCfgDialog::SyncCfgDialog(wxWindow* window, bSizer201->Layout(); //wxButtonWithImage size might have changed - //set radiobutton - switch (localSyncConfiguration.getVariant()) - { - case SyncConfiguration::MIRROR: - m_radioBtn1->SetValue(true); //one way -> - break; - case SyncConfiguration::UPDATE: - m_radioBtnUpdate->SetValue(true); //Update -> - break; - case SyncConfiguration::TWOWAY: - m_radioBtn2->SetValue(true); //two way <-> - break; - case SyncConfiguration::CUSTOM: - m_radioBtn3->SetValue(true); //other - break; - } - m_buttonApply->SetFocus(); Fit(); @@ -84,6 +69,16 @@ SyncCfgDialog::~SyncCfgDialog() {} void SyncCfgDialog::updateConfigIcons(const FreeFileSync::CompareVariant cmpVar, const FreeFileSync::SyncConfiguration& syncConfig) { + //wxWindowUpdateLocker dummy(this); //avoid display distortion + wxWindowUpdateLocker dummy2(m_panelCustomDeletionDir); //avoid display distortion + wxWindowUpdateLocker dummy3(m_bpButtonLeftOnly); + wxWindowUpdateLocker dummy4(m_bpButtonRightOnly); + wxWindowUpdateLocker dummy5(m_bpButtonLeftNewer); + wxWindowUpdateLocker dummy6(m_bpButtonRightNewer); + wxWindowUpdateLocker dummy7(m_bpButtonDifferent); + wxWindowUpdateLocker dummy8(m_bpButtonConflict); + + updateConfigIcons(cmpVar, syncConfig, m_bpButtonLeftOnly, @@ -97,7 +92,30 @@ void SyncCfgDialog::updateConfigIcons(const FreeFileSync::CompareVariant cmpVar, m_bitmapLeftNewer, m_bitmapRightNewer, m_bitmapDifferent, - m_bitmapConflict); + m_bitmapConflict, + sbSizerSyncDirections); + + //set radiobuttons -> have no parameter-ownership at all! + switch (localSyncConfiguration.getVariant()) + { + case SyncConfiguration::AUTOMATIC: + m_radioBtnAutomatic->SetValue(true); //automatic mode + break; + case SyncConfiguration::MIRROR: + m_radioBtnMirror->SetValue(true); //one way -> + break; + case SyncConfiguration::UPDATE: + m_radioBtnUpdate->SetValue(true); //Update -> + break; + case SyncConfiguration::TWOWAY: + m_radioBtnTwoWay->SetValue(true); //two way <-> + break; + case SyncConfiguration::CUSTOM: + m_radioBtnCustom->SetValue(true); //custom + break; + } + + GetSizer()->SetSizeHints(this); //this works like a charm for GTK2 with window resizing problems!!! (includes call to Fit()) } @@ -114,44 +132,45 @@ void SyncCfgDialog::updateConfigIcons(const CompareVariant compareVar, wxStaticBitmap* bitmapLeftNewer, wxStaticBitmap* bitmapRightNewer, wxStaticBitmap* bitmapDifferent, - wxStaticBitmap* bitmapConflict) + wxStaticBitmap* bitmapConflict, + wxSizer* syncDirections) //sizer containing all sync-directions { //display only relevant sync options + syncDirections->Show(true); + + buttonLeftOnly ->Show(); // + buttonRightOnly ->Show(); // + buttonLeftNewer ->Show(); // + buttonRightNewer->Show(); // enable everything by default + buttonDifferent ->Show(); // + buttonConflict ->Show(); // + + bitmapLeftOnly ->Show(); // + bitmapRightOnly ->Show(); // + bitmapLeftNewer ->Show(); // + bitmapRightNewer->Show(); // + bitmapDifferent ->Show(); // + bitmapConflict ->Show(); // + switch (compareVar) { case CMP_BY_TIME_SIZE: - buttonLeftOnly ->Show(); - buttonRightOnly ->Show(); - buttonLeftNewer ->Show(); - buttonRightNewer->Show(); buttonDifferent ->Hide(); - buttonConflict ->Show(); - bitmapLeftOnly ->Show(); - bitmapRightOnly ->Show(); - bitmapLeftNewer ->Show(); - bitmapRightNewer->Show(); bitmapDifferent ->Hide(); - bitmapConflict ->Show(); break; case CMP_BY_CONTENT: - buttonLeftOnly ->Show(); - buttonRightOnly ->Show(); buttonLeftNewer ->Hide(); buttonRightNewer->Hide(); - buttonDifferent ->Show(); - buttonConflict ->Show(); - bitmapLeftOnly ->Show(); - bitmapRightOnly ->Show(); bitmapLeftNewer ->Hide(); bitmapRightNewer->Hide(); - bitmapDifferent ->Show(); - bitmapConflict ->Show(); break; } + if (syncConfig.automatic) //automatic mode needs no sync-directions + syncDirections->Show(false); switch (syncConfig.exLeftSideOnly) { @@ -276,23 +295,12 @@ void SyncCfgDialog::OnApply(wxCommandEvent& event) } -void updateToolTipErrorHandling(wxChoice* choiceHandleError, const xmlAccess::OnError value) +void SyncCfgDialog::updateToolTipErrorHandling(bool ignoreErrors) { - switch (value) - { - case xmlAccess::ON_ERROR_POPUP: - choiceHandleError->SetToolTip(_("Show popup on errors or warnings")); - break; - case xmlAccess::ON_ERROR_IGNORE: - choiceHandleError->SetToolTip(_("Hide all error and warning messages")); - break; - case xmlAccess::ON_ERROR_EXIT: - choiceHandleError->SetToolTip(_("Exit immediately and set returncode < 0")); - break; - default: - assert(false); - choiceHandleError->SetToolTip(wxEmptyString); - } + if (ignoreErrors) + m_choiceHandleError->SetToolTip(_("Hide all error and warning messages")); + else + m_choiceHandleError->SetToolTip(_("Show popup on errors or warnings")); } @@ -316,13 +324,13 @@ void SyncCfgDialog::setErrorHandling(bool ignoreErrors) else m_choiceHandleError->SetSelection(0); - updateToolTipErrorHandling(m_choiceHandleError, ignoreErrors ? xmlAccess::ON_ERROR_IGNORE : xmlAccess::ON_ERROR_POPUP); + updateToolTipErrorHandling(ignoreErrors); } void SyncCfgDialog::OnChangeErrorHandling(wxCommandEvent& event) { - updateToolTipErrorHandling(m_choiceHandleError, getErrorHandling() ? xmlAccess::ON_ERROR_IGNORE : xmlAccess::ON_ERROR_POPUP); + updateToolTipErrorHandling(getErrorHandling()); } //------------------- @@ -396,51 +404,46 @@ void SyncCfgDialog::OnChangeDeletionHandling(wxCommandEvent& event) } +void SyncCfgDialog::OnSyncAutomatic(wxCommandEvent& event) +{ + localSyncConfiguration.setVariant(SyncConfiguration::AUTOMATIC); + updateConfigIcons(cmpVariant, localSyncConfiguration); +} + + void SyncCfgDialog::OnSyncLeftToRight(wxCommandEvent& event) { localSyncConfiguration.setVariant(SyncConfiguration::MIRROR); - updateConfigIcons(cmpVariant, localSyncConfiguration); - - //if event is triggered by button - m_radioBtn1->SetValue(true); } void SyncCfgDialog::OnSyncUpdate(wxCommandEvent& event) { localSyncConfiguration.setVariant(SyncConfiguration::UPDATE); - updateConfigIcons(cmpVariant, localSyncConfiguration); - - //if event is triggered by button - m_radioBtnUpdate->SetValue(true); } void SyncCfgDialog::OnSyncBothSides(wxCommandEvent& event) { localSyncConfiguration.setVariant(SyncConfiguration::TWOWAY); - updateConfigIcons(cmpVariant, localSyncConfiguration); - - //if event is triggered by button - m_radioBtn2->SetValue(true); } -void toggleSyncDirection(SyncDirectionCfg& current) +void toggleSyncDirection(SyncDirection& current) { switch (current) { - case SYNC_DIR_CFG_RIGHT: - current = SYNC_DIR_CFG_LEFT; + case SYNC_DIR_RIGHT: + current = SYNC_DIR_LEFT; break; - case SYNC_DIR_CFG_LEFT: - current = SYNC_DIR_CFG_NONE; + case SYNC_DIR_LEFT: + current = SYNC_DIR_NONE; break; - case SYNC_DIR_CFG_NONE: - current = SYNC_DIR_CFG_RIGHT; + case SYNC_DIR_NONE: + current = SYNC_DIR_RIGHT; break; } } @@ -450,8 +453,6 @@ void SyncCfgDialog::OnExLeftSideOnly( wxCommandEvent& event ) { toggleSyncDirection(localSyncConfiguration.exLeftSideOnly); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } @@ -459,8 +460,6 @@ void SyncCfgDialog::OnExRightSideOnly( wxCommandEvent& event ) { toggleSyncDirection(localSyncConfiguration.exRightSideOnly); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } @@ -468,8 +467,6 @@ void SyncCfgDialog::OnLeftNewer( wxCommandEvent& event ) { toggleSyncDirection(localSyncConfiguration.leftNewer); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } @@ -477,8 +474,6 @@ void SyncCfgDialog::OnRightNewer( wxCommandEvent& event ) { toggleSyncDirection(localSyncConfiguration.rightNewer); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } @@ -486,8 +481,6 @@ void SyncCfgDialog::OnDifferent( wxCommandEvent& event ) { toggleSyncDirection(localSyncConfiguration.different); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } @@ -495,8 +488,6 @@ void SyncCfgDialog::OnConflict(wxCommandEvent& event) { toggleSyncDirection(localSyncConfiguration.conflict); updateConfigIcons(cmpVariant, localSyncConfiguration); - //set custom config button - m_radioBtn3->SetValue(true); } //################################################################################################################################### @@ -507,8 +498,8 @@ class BatchFolderPairPanel : public FolderPairParent { public: BatchFolderPairPanel(wxWindow* parent, BatchDialog* batchDialog) : - FolderPairParent(parent), - batchDlg(batchDialog) {} + FolderPairParent(parent), + batchDlg(batchDialog) {} private: virtual wxWindow* getParentWindow() @@ -540,7 +531,7 @@ class BatchFileDropEvent : public wxFileDropTarget { public: BatchFileDropEvent(BatchDialog* dlg) : - batchDlg(dlg) {} + batchDlg(dlg) {} virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) { @@ -569,7 +560,7 @@ private: BatchDialog::BatchDialog(wxWindow* window, const xmlAccess::XmlBatchConfig& batchCfg) : - BatchDlgGenerated(window) + BatchDlgGenerated(window) { init(); loadBatchCfg(batchCfg); @@ -577,7 +568,7 @@ BatchDialog::BatchDialog(wxWindow* window, const xmlAccess::XmlBatchConfig& batc BatchDialog::BatchDialog(wxWindow* window, const wxString& filename) : - BatchDlgGenerated(window) + BatchDlgGenerated(window) { init(); loadBatchFile(filename); @@ -631,12 +622,33 @@ xmlAccess::OnError BatchDialog::getSelectionHandleError() const } +void BatchDialog::updateToolTipErrorHandling(const xmlAccess::OnError value) +{ + switch (value) + { + case xmlAccess::ON_ERROR_POPUP: + m_choiceHandleError->SetToolTip(_("Show popup on errors or warnings")); + break; + case xmlAccess::ON_ERROR_IGNORE: + m_choiceHandleError->SetToolTip(_("Hide all error and warning messages")); + break; + case xmlAccess::ON_ERROR_EXIT: + m_choiceHandleError->SetToolTip(_("Exit immediately and set returncode < 0")); + break; + } +} + + void BatchDialog::setSelectionHandleError(const xmlAccess::OnError value) { m_choiceHandleError->Clear(); m_choiceHandleError->Append(_("Show popup")); m_choiceHandleError->Append(_("Ignore errors")); - m_choiceHandleError->Append(_("Exit with RC < 0")); + if (m_checkBoxSilent->GetValue()) //this option shall be available for silent mode only! + m_choiceHandleError->Append(_("Exit with RC < 0")); + + //default + m_choiceHandleError->SetSelection(0); switch (value) { @@ -647,20 +659,18 @@ void BatchDialog::setSelectionHandleError(const xmlAccess::OnError value) m_choiceHandleError->SetSelection(1); break; case xmlAccess::ON_ERROR_EXIT: - m_choiceHandleError->SetSelection(2); + if (m_checkBoxSilent->GetValue()) //this option shall be available for silent mode only! + m_choiceHandleError->SetSelection(2); break; - default: - assert(false); - m_choiceHandleError->SetSelection(0); } - updateToolTipErrorHandling(m_choiceHandleError, getSelectionHandleError()); + updateToolTipErrorHandling(getSelectionHandleError()); } void BatchDialog::OnChangeErrorHandling(wxCommandEvent& event) { - updateToolTipErrorHandling(m_choiceHandleError, getSelectionHandleError()); + updateToolTipErrorHandling(getSelectionHandleError()); } @@ -762,9 +772,27 @@ void BatchDialog::OnCheckFilter(wxCommandEvent& event) } -void BatchDialog::OnCheckLogging(wxCommandEvent& event) +void BatchDialog::OnCheckAutomatic(wxCommandEvent& event) +{ + wxWindowUpdateLocker dummy(m_panelOverview); //avoid display distortion + + //toggle automatic setting + localSyncConfiguration.automatic = !localSyncConfiguration.automatic; + + if (localSyncConfiguration.automatic) + localSyncConfiguration.setVariant(SyncConfiguration::AUTOMATIC); //reset conflict-setting + + updateConfigIcons(getCurrentCompareVar(), localSyncConfiguration); + Fit(); +} + + +void BatchDialog::OnCheckSilent(wxCommandEvent& event) { updateVisibleTabs(); + + //reset error handling depending on "m_checkBoxSilent" + setSelectionHandleError(getSelectionHandleError()); } @@ -821,6 +849,8 @@ CompareVariant BatchDialog::getCurrentCompareVar() const void BatchDialog::updateConfigIcons(const FreeFileSync::CompareVariant cmpVar, const FreeFileSync::SyncConfiguration& syncConfig) { + wxWindowUpdateLocker dummy(m_panelOverview); //avoid display distortion + SyncCfgDialog::updateConfigIcons(cmpVar, syncConfig, m_bpButtonLeftOnly, @@ -834,15 +864,21 @@ void BatchDialog::updateConfigIcons(const FreeFileSync::CompareVariant cmpVar, c m_bitmapLeftNewer, m_bitmapRightNewer, m_bitmapDifferent, - m_bitmapConflict); + m_bitmapConflict, + sbSizerSyncDirections); + + //parameter ownership lies within localSyncConfiguration, NOT m_checkBoxAutomatic!!! + m_checkBoxAutomatic->SetValue(localSyncConfiguration.automatic); + + m_panelOverview->Layout(); //needed } void BatchDialog::OnChangeCompareVar(wxCommandEvent& event) { + wxWindowUpdateLocker dummy(m_panelOverview); //avoid display distortion updateConfigIcons(getCurrentCompareVar(), localSyncConfiguration); - m_panelOverview->Layout(); //needed Fit(); } @@ -868,11 +904,13 @@ void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) if (filePicker->ShowModal() == wxID_OK) { const wxString newFileName = filePicker->GetPath(); - if (FreeFileSync::fileExists(newFileName.c_str())) + if (FreeFileSync::fileExists(wxToZ(newFileName))) { - wxMessageDialog* messageDlg = new wxMessageDialog(this, wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\""), _("Warning") , wxOK | wxCANCEL); + QuestionDlg* messageDlg = new QuestionDlg(this, + QuestionDlg::BUTTON_YES | QuestionDlg::BUTTON_CANCEL, + wxString(_("File already exists. Overwrite?")) + wxT(" \"") + newFileName + wxT("\"")); - if (messageDlg->ShowModal() != wxID_OK) + if (messageDlg->ShowModal() != QuestionDlg::BUTTON_YES) { OnSaveBatchJob(event); //retry return; @@ -898,8 +936,8 @@ void BatchDialog::OnLoadBatchJob(wxCommandEvent& event) inline FolderPairEnh getEnahncedPair(const BatchFolderPairPanel* panel) { - return FolderPairEnh(panel->m_directoryLeft->GetValue().c_str(), - panel->m_directoryRight->GetValue().c_str(), + return FolderPairEnh(wxToZ(panel->m_directoryLeft->GetValue()), + wxToZ(panel->m_directoryRight->GetValue()), panel->altSyncConfig, panel->altFilter); } @@ -913,14 +951,14 @@ xmlAccess::XmlBatchConfig BatchDialog::getCurrentConfiguration() const batchCfg.mainCfg.compareVar = getCurrentCompareVar(); batchCfg.mainCfg.syncConfiguration = localSyncConfiguration; batchCfg.mainCfg.filterIsActive = m_checkBoxFilter->GetValue(); - batchCfg.mainCfg.includeFilter = m_textCtrlInclude->GetValue(); - batchCfg.mainCfg.excludeFilter = m_textCtrlExclude->GetValue(); + batchCfg.mainCfg.includeFilter = wxToZ(m_textCtrlInclude->GetValue()); + batchCfg.mainCfg.excludeFilter = wxToZ(m_textCtrlExclude->GetValue()); batchCfg.mainCfg.handleDeletion = getDeletionHandling(); batchCfg.mainCfg.customDeletionDirectory = m_textCtrlCustomDelFolder->GetValue(); //main pair - batchCfg.mainCfg.mainFolderPair.leftDirectory = m_directoryLeft->GetValue().c_str(); - batchCfg.mainCfg.mainFolderPair.rightDirectory = m_directoryRight->GetValue().c_str(); + batchCfg.mainCfg.mainFolderPair.leftDirectory = wxToZ(m_directoryLeft->GetValue()); + batchCfg.mainCfg.mainFolderPair.rightDirectory = wxToZ(m_directoryRight->GetValue()); //add additional pairs batchCfg.mainCfg.additionalPairs.clear(); @@ -994,8 +1032,6 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) setDeletionHandling(batchCfg.mainCfg.handleDeletion); m_textCtrlCustomDelFolder->SetValue(batchCfg.mainCfg.customDeletionDirectory); - setSelectionHandleError(batchCfg.handleError); - switch (batchCfg.mainCfg.compareVar) { case CMP_BY_TIME_SIZE: @@ -1009,16 +1045,18 @@ void BatchDialog::loadBatchCfg(const xmlAccess::XmlBatchConfig& batchCfg) updateConfigIcons(batchCfg.mainCfg.compareVar, batchCfg.mainCfg.syncConfiguration); m_checkBoxFilter->SetValue(batchCfg.mainCfg.filterIsActive); - m_textCtrlInclude->SetValue(batchCfg.mainCfg.includeFilter); - m_textCtrlExclude->SetValue(batchCfg.mainCfg.excludeFilter); + m_textCtrlInclude->SetValue(zToWx(batchCfg.mainCfg.includeFilter)); + m_textCtrlExclude->SetValue(zToWx(batchCfg.mainCfg.excludeFilter)); m_checkBoxSilent->SetValue(batchCfg.silent); m_textCtrlLogfileDir->SetValue(batchCfg.logFileDirectory); + //error handling is dependent from m_checkBoxSilent! /|\ \|/ + setSelectionHandleError(batchCfg.handleError); //set main folder pair - FreeFileSync::setDirectoryName(batchCfg.mainCfg.mainFolderPair.leftDirectory.c_str(), m_directoryLeft, m_dirPickerLeft); - FreeFileSync::setDirectoryName(batchCfg.mainCfg.mainFolderPair.rightDirectory.c_str(), m_directoryRight, m_dirPickerRight); + FreeFileSync::setDirectoryName(zToWx(batchCfg.mainCfg.mainFolderPair.leftDirectory), m_directoryLeft, m_dirPickerLeft); + FreeFileSync::setDirectoryName(zToWx(batchCfg.mainCfg.mainFolderPair.rightDirectory), m_directoryRight, m_dirPickerRight); //remove existing additional folder pairs clearAddFolderPairs(); @@ -1111,8 +1149,8 @@ void BatchDialog::addFolderPair(const std::vector<FreeFileSync::FolderPairEnh>& newPair->m_bpButtonRemovePair->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BatchDialog::OnRemoveFolderPair), NULL, this ); //insert directory names - FreeFileSync::setDirectoryName(i->leftDirectory.c_str(), newPair->m_directoryLeft, newPair->m_dirPickerLeft); - FreeFileSync::setDirectoryName(i->rightDirectory.c_str(), newPair->m_directoryRight, newPair->m_dirPickerRight); + FreeFileSync::setDirectoryName(zToWx(i->leftDirectory), newPair->m_directoryLeft, newPair->m_dirPickerLeft); + FreeFileSync::setDirectoryName(zToWx(i->rightDirectory), newPair->m_directoryRight, newPair->m_dirPickerRight); //set alternate configuration newPair->altSyncConfig = i->altSyncConfig; diff --git a/ui/SyncDialog.h b/ui/settingsDialog.h index 53ab1b5a..feb763a9 100644 --- a/ui/SyncDialog.h +++ b/ui/settingsDialog.h @@ -10,7 +10,7 @@ class BatchFolderPairPanel; namespace FreeFileSync { - class DragDropOnDlg; +class DragDropOnDlg; } @@ -44,11 +44,13 @@ public: wxStaticBitmap* bitmapLeftNewer, wxStaticBitmap* bitmapRightNewer, wxStaticBitmap* bitmapDifferent, - wxStaticBitmap* bitmapConflict); + wxStaticBitmap* bitmapConflict, + wxSizer* syncDirections); //some syntax relaxation void updateConfigIcons(const FreeFileSync::CompareVariant cmpVar, const FreeFileSync::SyncConfiguration& syncConfig); private: + virtual void OnSyncAutomatic( wxCommandEvent& event); virtual void OnSyncLeftToRight( wxCommandEvent& event); virtual void OnSyncUpdate( wxCommandEvent& event); virtual void OnSyncBothSides( wxCommandEvent& event); @@ -64,6 +66,9 @@ private: virtual void OnCancel( wxCommandEvent& event); virtual void OnApply( wxCommandEvent& event); + //set tooltip + void updateToolTipErrorHandling(bool ignoreErrors); + //error handling bool getErrorHandling(); void setErrorHandling(bool ignoreErrors); @@ -114,8 +119,9 @@ private: virtual void OnDifferent( wxCommandEvent& event); virtual void OnConflict( wxCommandEvent& event); + virtual void OnCheckAutomatic( wxCommandEvent& event); virtual void OnCheckFilter( wxCommandEvent& event); - virtual void OnCheckLogging( wxCommandEvent& event); + virtual void OnCheckSilent( wxCommandEvent& event); virtual void OnChangeCompareVar( wxCommandEvent& event); virtual void OnClose( wxCloseEvent& event); virtual void OnCancel( wxCommandEvent& event); @@ -141,6 +147,9 @@ private: void setSelectionHandleError(const xmlAccess::OnError value); void OnChangeErrorHandling(wxCommandEvent& event); + //set tooltip + void updateToolTipErrorHandling(const xmlAccess::OnError value); + //deletion handling FreeFileSync::DeletionPolicy getDeletionHandling() const; void setDeletionHandling(FreeFileSync::DeletionPolicy newValue); diff --git a/ui/sorting.h b/ui/sorting.h index 33a6404f..e65344e6 100644 --- a/ui/sorting.h +++ b/ui/sorting.h @@ -4,167 +4,178 @@ #include "../fileHierarchy.h" #include "../shared/systemConstants.h" #include "../synchronization.h" +#include "../shared/staticAssert.h" namespace FreeFileSync { - inline - int compareString(const Zstring& stringA, const Zstring& stringB) - { +inline +int compareString(const Zstring& stringA, const Zstring& stringB) +{ #ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - return stringA.CmpNoCase(stringB); + return stringA.CmpNoCase(stringB); #elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case - return stringA.Cmp(stringB); + return stringA.Cmp(stringB); #endif - } +} - inline - bool stringSmallerThan(const Zstring& stringA, const Zstring& stringB) +template <bool ascending> +struct Compare +{ + template <class T> + bool isSmallerThan(T a, T b) { - return compareString(stringA, stringB) < 0; + assert_static(sizeof(T) <= 2 * sizeof(int)); //use for comparing (small) INTEGRAL types only! + return a < b; } +}; +template <> +struct Compare<false> +{ + template <class T> + bool isSmallerThan(T a, T b) + { + assert_static(sizeof(T) <= 2 * sizeof(int)); //use for comparing (small) INTEGRAL types only! + return a > b; + } +}; + + +inline +bool stringSmallerThan(const Zstring& stringA, const Zstring& stringB) +{ + return compareString(stringA, stringB) < 0; +} + + +template <bool ascending, SelectedSide side> +inline +bool sortByFileName(const FileSystemObject& a, const FileSystemObject& b) +{ + //presort types: first files, then directories then empty rows + if (a.isEmpty<side>()) + return false; //empty rows always last + else if (b.isEmpty<side>()) + return true; //empty rows always last - template <bool ascending, SelectedSide side> - inline - bool sortByFileName(const FileSystemObject& a, const FileSystemObject& b) + if (dynamic_cast<const DirMapping*>(&a)) //sort directories by relative name { - //presort types: first files, then directories then empty rows - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last - - - if (dynamic_cast<const DirMapping*>(&a)) //sort directories by relative name - { - if (dynamic_cast<const DirMapping*>(&b)) - return stringSmallerThan(a.getRelativeName<side>(), b.getRelativeName<side>()); - else - return false; - } + if (dynamic_cast<const DirMapping*>(&b)) + return stringSmallerThan(a.getRelativeName<side>(), b.getRelativeName<side>()); else - { - if (dynamic_cast<const DirMapping*>(&b)) - return true; - else - { - return ascending ? - stringSmallerThan(a.getShortName<side>(), b.getShortName<side>()) : - stringSmallerThan(b.getShortName<side>(), a.getShortName<side>()); - } - } + return false; } + else + { + if (dynamic_cast<const DirMapping*>(&b)) + return true; + else + return Compare<ascending>().isSmallerThan(a.getShortName<side>(), b.getShortName<side>()); + } +} - template <bool ascending, SelectedSide side> - bool sortByRelativeName(const FileSystemObject& a, const FileSystemObject& b) +template <bool ascending, SelectedSide side> +bool sortByRelativeName(const FileSystemObject& a, const FileSystemObject& b) +{ + if (a.isEmpty<side>()) + return false; //empty rows always last + else if (b.isEmpty<side>()) + return true; //empty rows always last + + const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); + const Zstring relDirNameA = fileObjA != NULL ? + a.getParentRelativeName() : //file + a.getRelativeName<side>(); //directory + + const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); + const Zstring relDirNameB = fileObjB != NULL ? + b.getParentRelativeName() : //file + b.getRelativeName<side>(); //directory + + //compare relative names without filenames first + const int rv = compareString(relDirNameA, relDirNameB); + if (rv != 0) + return Compare<ascending>().isSmallerThan(rv, 0); + else //compare the filenames { - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last - - - const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); - const Zstring relDirNameA = fileObjA != NULL ? - a.getParentRelativeName<side>() : //file - a.getRelativeName<side>(); //directory - - const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); - const Zstring relDirNameB = fileObjB != NULL ? - b.getParentRelativeName<side>() : //file - b.getRelativeName<side>(); //directory - - //compare relative names without filenames first - const int rv = compareString(relDirNameA, relDirNameB); - if (rv != 0) - return ascending ? rv < 0 : rv > 0; - else //compare the filenames - { - if (fileObjB == NULL) //directories shall appear before files - return false; - else if (fileObjA == NULL) - return true; - - return stringSmallerThan(a.getShortName<side>(), b.getShortName<side>()); - } + if (fileObjB == NULL) //directories shall appear before files + return false; + else if (fileObjA == NULL) + return true; + + return stringSmallerThan(a.getShortName<side>(), b.getShortName<side>()); } +} - template <bool ascending, SelectedSide side> - inline - bool sortByFileSize(const FileSystemObject& a, const FileSystemObject& b) - { - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last +template <bool ascending, SelectedSide side> +inline +bool sortByFileSize(const FileSystemObject& a, const FileSystemObject& b) +{ + if (a.isEmpty<side>()) + return false; //empty rows always last + else if (b.isEmpty<side>()) + return true; //empty rows always last - const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); - const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); + const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); + const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); - if (fileObjA == NULL) - return false; //directories last - else if (fileObjB == NULL) - return true; //directories last + if (fileObjA == NULL) + return false; //directories last + else if (fileObjB == NULL) + return true; //directories last - return ascending ? - fileObjA->getFileSize<side>() > fileObjB->getFileSize<side>() : //sortAscending shall result in list beginning with largest files first - fileObjA->getFileSize<side>() < fileObjB->getFileSize<side>(); - } + //sortAscending shall result in list beginning with largest files first + return Compare<!ascending>().isSmallerThan(fileObjA->getFileSize<side>(), fileObjB->getFileSize<side>()); +} - template <bool ascending, SelectedSide side> - inline - bool sortByDate(const FileSystemObject& a, const FileSystemObject& b) - { - if (a.isEmpty<side>()) - return false; //empty rows always last - else if (b.isEmpty<side>()) - return true; //empty rows always last +template <bool ascending, SelectedSide side> +inline +bool sortByDate(const FileSystemObject& a, const FileSystemObject& b) +{ + if (a.isEmpty<side>()) + return false; //empty rows always last + else if (b.isEmpty<side>()) + return true; //empty rows always last - const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); - const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); + const FileMapping* fileObjA = dynamic_cast<const FileMapping*>(&a); + const FileMapping* fileObjB = dynamic_cast<const FileMapping*>(&b); - if (fileObjA == NULL) - return false; //directories last - else if (fileObjB == NULL) - return true; //directories last + if (fileObjA == NULL) + return false; //directories last + else if (fileObjB == NULL) + return true; //directories last - return ascending ? - fileObjA->getLastWriteTime<side>() > fileObjB->getLastWriteTime<side>() : - fileObjA->getLastWriteTime<side>() < fileObjB->getLastWriteTime<side>(); - } + return Compare<!ascending>().isSmallerThan(fileObjA->getLastWriteTime<side>(), fileObjB->getLastWriteTime<side>()); +} - template <bool ascending> - inline - bool sortByCmpResult(const FileSystemObject& a, const FileSystemObject& b) - { - //presort result: equal shall appear at end of list - if (a.getCategory() == FILE_EQUAL) - return false; - if (b.getCategory() == FILE_EQUAL) - return true; +template <bool ascending> +inline +bool sortByCmpResult(const FileSystemObject& a, const FileSystemObject& b) +{ + //presort result: equal shall appear at end of list + if (a.getCategory() == FILE_EQUAL) + return false; + if (b.getCategory() == FILE_EQUAL) + return true; - return ascending ? - a.getCategory() < b.getCategory() : - a.getCategory() > b.getCategory(); - } + return Compare<ascending>().isSmallerThan(a.getCategory(), b.getCategory()); +} - template <bool ascending> - inline - bool sortBySyncDirection(const FileSystemObject& a, const FileSystemObject& b) - { - return ascending ? - getSyncOperation(a) < getSyncOperation(b) : - getSyncOperation(a) > getSyncOperation(b); - } +template <bool ascending> +inline +bool sortBySyncDirection(const FileSystemObject& a, const FileSystemObject& b) +{ + return Compare<ascending>().isSmallerThan(a.getSyncOperation(), b.getSyncOperation()); +} } #endif // SORTING_H_INCLUDED diff --git a/ui/util.cpp b/ui/util.cpp new file mode 100644 index 00000000..9abdf6e8 --- /dev/null +++ b/ui/util.cpp @@ -0,0 +1,236 @@ +#include "util.h" +#include <wx/scrolwin.h> +#include <wx/textctrl.h> +#include <wx/combobox.h> +#include <wx/filepicker.h> +#include "../shared/globalFunctions.h" +#include "../shared/localization.h" +#include "../shared/fileHandling.h" +#include "../shared/stringConv.h" +#include <stdexcept> +#include "../shared/systemFunctions.h" + +#ifdef FFS_WIN +#include <wx/msw/wrapwin.h> //includes "windows.h" +#endif + + +wxString FreeFileSync::formatFilesizeToShortString(const wxLongLong& filesize) +{ + return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); +} + + +wxString FreeFileSync::formatFilesizeToShortString(const wxULongLong& filesize) +{ + return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); +}; + + +wxString FreeFileSync::formatFilesizeToShortString(const double filesize) +{ + if (filesize < 0) + return _("Error"); + + if (filesize <= 999) + return wxString::Format(wxT("%i"), static_cast<int>(filesize)) + _(" Byte"); //no decimal places in case of bytes + + double nrOfBytes = filesize; + + nrOfBytes /= 1024; + wxString unit = _(" kB"); + if (nrOfBytes > 999) + { + nrOfBytes /= 1024; + unit = _(" MB"); + if (nrOfBytes > 999) + { + nrOfBytes /= 1024; + unit = _(" GB"); + if (nrOfBytes > 999) + { + nrOfBytes /= 1024; + unit = _(" TB"); + if (nrOfBytes > 999) + { + nrOfBytes /= 1024; + unit = _(" PB"); + } + } + } + } + + //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111 + + const unsigned int leadDigitCount = globalFunctions::getDigitCount(static_cast<unsigned int>(nrOfBytes)); //number of digits before decimal point + if (leadDigitCount == 0 || leadDigitCount > 3) + return _("Error"); + + if (leadDigitCount == 3) + return wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes)) + unit; + else if (leadDigitCount == 2) + { + wxString output = wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes * 10)); + output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); + return output + unit; + } + else //leadDigitCount == 1 + { + wxString output = wxString::Format(wxT("%03i"), static_cast<int>(nrOfBytes * 100)); + output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); + return output + unit; + } + + //return wxString::Format(wxT("%.*f"), 3 - leadDigitCount, nrOfBytes) + unit; +} + + +wxString FreeFileSync::includeNumberSeparator(const wxString& number) +{ + wxString output(number); + for (int i = output.size() - 3; i > 0; i -= 3) + output.insert(i, FreeFileSync::THOUSANDS_SEPARATOR); + + return output; +} + + +template <class T> +void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker) +{ + using namespace FreeFileSync; + + txtCtrl->SetValue(dirname); + const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(wxToZ(dirname)); + if (FreeFileSync::dirExists(leftDirFormatted)) + dirPicker->SetPath(zToWx(leftDirFormatted)); +} + + +void FreeFileSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) +{ + setDirectoryNameImpl(dirname, txtCtrl, dirPicker); +} + + +void FreeFileSync::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) +{ + txtCtrl->SetSelection(wxNOT_FOUND); + setDirectoryNameImpl(dirname, txtCtrl, dirPicker); +} + + +void FreeFileSync::scrollToBottom(wxScrolledWindow* scrWindow) +{ + int height = 0; + scrWindow->GetClientSize(NULL, &height); + + int pixelPerLine = 0; + scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine); + + if (height > 0 && pixelPerLine > 0) + { + const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL); + const int scrollLinesOnScreen = height / pixelPerLine; + const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen; + + if (0 <= scrollPosBottom) + scrWindow->Scroll(0, scrollPosBottom); + } +} + + + + + +inline +void writeTwoDigitNumber(unsigned int number, wxString& string) +{ + assert (number < 100); + + string += '0' + number / 10; + string += '0' + number % 10; +} + + +inline +void writeFourDigitNumber(unsigned int number, wxString& string) +{ + assert (number < 10000); + + string += '0' + number / 1000; + number %= 1000; + string += '0' + number / 100; + number %= 100; + string += '0' + number / 10; + number %= 10; + string += '0' + number; +} + + +wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename) +{ +#ifdef FFS_WIN + //convert ansi C time to FILETIME + wxLongLong fileTimeLong(utcTime); + + fileTimeLong += wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s + fileTimeLong *= 10000000; + + FILETIME lastWriteTimeUtc; + lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); //GetLo() returns unsigned + lastWriteTimeUtc.dwHighDateTime = unsigned(fileTimeLong.GetHi()); //GetHi() returns signed + + + FILETIME localFileTime; + if (::FileTimeToLocalFileTime( //convert to local time + &lastWriteTimeUtc, //pointer to UTC file time to convert + &localFileTime //pointer to converted file time + ) == 0) + throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + + wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") + + filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); + + if (localFileTime.dwHighDateTime > 0x7fffffff) + return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever! + //Testcase (UTC): dateHigh = 2147483647 (=0x7fffffff) -> year 30000 + // dateLow = 4294967295 + + SYSTEMTIME time; + if (::FileTimeToSystemTime( + &localFileTime, //pointer to file time to convert + &time //pointer to structure to receive system time + ) == 0) + throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" local FILETIME -> SYSTEMTIME: ") + + wxT("(") + wxULongLong(localFileTime.dwHighDateTime, localFileTime.dwLowDateTime).ToString() + wxT(") ") + + filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); + + //assemble time string (performance optimized) + wxString formattedTime; + formattedTime.reserve(20); + + writeFourDigitNumber(time.wYear, formattedTime); + formattedTime += wxChar('-'); + writeTwoDigitNumber(time.wMonth, formattedTime); + formattedTime += wxChar('-'); + writeTwoDigitNumber(time.wDay, formattedTime); + formattedTime += wxChar(' '); + formattedTime += wxChar(' '); + writeTwoDigitNumber(time.wHour, formattedTime); + formattedTime += wxChar(':'); + writeTwoDigitNumber(time.wMinute, formattedTime); + formattedTime += wxChar(':'); + writeTwoDigitNumber(time.wSecond, formattedTime); + + return formattedTime; + +#elif defined FFS_LINUX + tm* timeinfo; + const time_t fileTime = utcTime.ToLong(); + timeinfo = localtime(&fileTime); //convert to local time + char buffer[50]; + strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", timeinfo); + + return zToWx(buffer); +#endif +} diff --git a/ui/util.h b/ui/util.h new file mode 100644 index 00000000..f7680418 --- /dev/null +++ b/ui/util.h @@ -0,0 +1,30 @@ +#ifndef UTIL_H_INCLUDED +#define UTIL_H_INCLUDED + +#include "../shared/zstring.h" +#include <wx/string.h> +#include <wx/longlong.h> + +class wxComboBox; +class wxTextCtrl; +class wxDirPickerCtrl; +class wxScrolledWindow; + + +namespace FreeFileSync +{ +wxString formatFilesizeToShortString(const wxLongLong& filesize); +wxString formatFilesizeToShortString(const wxULongLong& filesize); +wxString formatFilesizeToShortString(const double filesize); + +wxString includeNumberSeparator(const wxString& number); + +void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker); +void setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker); +void scrollToBottom(wxScrolledWindow* scrWindow); + +wxString utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename); +} + + +#endif // UTIL_H_INCLUDED diff --git a/version/version.h b/version/version.h index 15fb7512..f1170e20 100644 --- a/version/version.h +++ b/version/version.h @@ -2,5 +2,5 @@ namespace FreeFileSync { - static const wxString currentVersion = wxT("2.3"); //internal linkage! + static const wxString currentVersion = wxT("3.0"); //internal linkage! } |