diff options
-rw-r--r-- | Application.cpp | 516 | ||||
-rw-r--r-- | Application.h | 78 | ||||
-rw-r--r-- | Changelog.txt | 23 | ||||
-rw-r--r-- | FreeFileSync.cbp (renamed from FreeFileSync - Unicode.cbp) | 23 | ||||
-rw-r--r-- | FreeFileSync.h | 10 | ||||
-rw-r--r-- | Languages/chinese_simple.lng (renamed from chinese_simple.lng) | 100 | ||||
-rw-r--r-- | Languages/dutch.lng (renamed from dutch.lng) | 70 | ||||
-rw-r--r-- | Languages/french.lng (renamed from french.lng) | 110 | ||||
-rw-r--r-- | Languages/german.lng (renamed from german.lng) | 278 | ||||
-rw-r--r-- | Languages/italian.lng | 588 | ||||
-rw-r--r-- | Languages/japanese.lng (renamed from japanese.lng) | 108 | ||||
-rw-r--r-- | Languages/polish.lng | 584 | ||||
-rw-r--r-- | Languages/portuguese.lng | 588 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | Makefile_Win.cmd (renamed from Makefile_Win_Unicode.cmd) | 3 | ||||
-rw-r--r-- | Readme.txt | 6 | ||||
-rw-r--r-- | Resources.a01 | bin | 4335 -> 0 bytes | |||
-rw-r--r-- | Resources.a02 | bin | 1702 -> 0 bytes | |||
-rw-r--r-- | Resources.dat | bin | 143518 -> 150657 bytes | |||
-rw-r--r-- | algorithm.cpp | 114 | ||||
-rw-r--r-- | algorithm.h | 11 | ||||
-rw-r--r-- | comparison.cpp | 537 | ||||
-rw-r--r-- | comparison.h | 22 | ||||
-rw-r--r-- | library/CustomGrid.cpp | 879 | ||||
-rw-r--r-- | library/CustomGrid.h | 118 | ||||
-rw-r--r-- | library/customButton.cpp | 293 | ||||
-rw-r--r-- | library/customButton.h | 40 | ||||
-rw-r--r-- | library/fileHandling.cpp | 82 | ||||
-rw-r--r-- | library/fileHandling.h | 8 | ||||
-rw-r--r-- | library/globalFunctions.cpp | 20 | ||||
-rw-r--r-- | library/globalFunctions.h | 22 | ||||
-rw-r--r-- | library/misc.cpp | 32 | ||||
-rw-r--r-- | library/misc.h | 5 | ||||
-rw-r--r-- | library/multithreading.cpp | 1 | ||||
-rw-r--r-- | library/processXml.cpp | 320 | ||||
-rw-r--r-- | library/processXml.h | 79 | ||||
-rw-r--r-- | library/resources.cpp | 12 | ||||
-rw-r--r-- | library/resources.h | 9 | ||||
-rw-r--r-- | library/sorting.h | 21 | ||||
-rw-r--r-- | library/statusHandler.h | 8 | ||||
-rw-r--r-- | library/zstring.cpp | 68 | ||||
-rw-r--r-- | library/zstring.h | 197 | ||||
-rw-r--r-- | synchronization.cpp | 101 | ||||
-rw-r--r-- | synchronization.h | 21 | ||||
-rw-r--r-- | ui/MainDialog.cpp | 688 | ||||
-rw-r--r-- | ui/MainDialog.h | 48 | ||||
-rw-r--r-- | ui/SmallDialogs.cpp | 203 | ||||
-rw-r--r-- | ui/SmallDialogs.h | 47 | ||||
-rw-r--r-- | ui/SyncDialog.cpp | 47 | ||||
-rw-r--r-- | ui/SyncDialog.h | 8 | ||||
-rw-r--r-- | ui/guiGenerated.cpp | 345 | ||||
-rw-r--r-- | ui/guiGenerated.h | 105 |
52 files changed, 5332 insertions, 2274 deletions
diff --git a/Application.cpp b/Application.cpp index ad56f9ca..0ae28d66 100644 --- a/Application.cpp +++ b/Application.cpp @@ -60,7 +60,7 @@ bool Application::OnInit() { if (wxFileExists(FreeFileSync::GLOBAL_CONFIG_FILE)) { //show messagebox and quit program immediately - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); return false; } //else: globalSettings already has default values @@ -94,9 +94,9 @@ void Application::initialize() { runBatchMode(argv[1], globalSettings); - if (applicationRunsInBatchWithoutWindows) - ExitMainLoop(); //exit programm on next main loop iteration - return; //program will exit automatically if a main window is present and is closed + if (wxApp::GetTopWindow() == NULL) //if no windows are shown program won't exit automatically + ExitMainLoop(); + return; } else { @@ -115,7 +115,7 @@ void Application::initialize() bool Application::OnExceptionInMainLoop() { - throw; //just pass exceptions and avoid display of additional exception messagebox: they will be caught in OnRun() + throw; //just re-throw exception and avoid display of additional exception messagebox: it will be caught in OnRun() } @@ -151,7 +151,7 @@ int Application::OnExit() } catch (const FileError& error) { - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); } return 0; @@ -165,12 +165,16 @@ public: { wxString tmp = wxDateTime::Now().FormatISOTime(); tmp.Replace(wxT(":"), wxEmptyString); - wxString logfileName = wxString(wxT("FFS_")) + wxDateTime::Now().FormatISODate() + wxChar('_') + tmp + wxT(".log"); + + //create subfolder "log" to hold logfiles + if (!wxDirExists(wxT("Logs"))) + wxMkdir(wxT("Logs")); + wxString logfileName = wxString(wxT("Logs")) + GlobalResources::FILE_NAME_SEPARATOR + wxT("FFS_") + wxDateTime::Now().FormatISODate() + wxChar('_') + tmp + wxT(".log"); logFile.Open(logfileName.c_str(), wxT("w")); readyToWrite = logFile.IsOpened(); if (readyToWrite) - { + { //"Date" is used at other places too wxString headerLine = wxString(wxT("FreeFileSync (")) + _("Date") + wxT(": ") + wxDateTime::Now().FormatDate() + wxT(" ") + _("Time:") + wxT(" ") + wxDateTime::Now().FormatTime() + wxT(")"); logFile.Write(headerLine + wxChar('\n')); logFile.Write(wxString().Pad(headerLine.Len(), wxChar('-')) + wxChar('\n') + wxChar('\n')); @@ -185,7 +189,11 @@ public: } } - ~LogFile() {} + ~LogFile() + { + if (readyToWrite) + close(); + } bool isOkay() { @@ -194,55 +202,36 @@ public: void write(const wxString& logText, const wxString& problemType = wxEmptyString) { - if (readyToWrite) - { - logFile.Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); + logFile.Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); - if (problemType != wxEmptyString) - logFile.Write(problemType + wxT(": ")); + if (problemType != wxEmptyString) + logFile.Write(problemType + wxT(": ")); - logFile.Write(logText + wxChar('\n')); - } + logFile.Write(logText + wxChar('\n')); } - void close(const wxString& finalText) +private: + + void close() { - if (readyToWrite) - { - logFile.Write(wxChar('\n')); + logFile.Write(wxChar('\n')); - long time = totalTime.Time(); //retrieve total time - write(finalText + wxT(" (") + _("Total time:") + wxT(" ") + (wxTimeSpan::Milliseconds(time)).Format() + wxT(")"), _("Stop")); + long time = totalTime.Time(); //retrieve total time - //logFile.close(); <- not needed - } + logFile.Write(wxString(wxT("[")) + wxDateTime::Now().FormatTime() + wxT("] ")); + logFile.Write(wxString(_("Stop")) + wxT(" (") + _("Total time:") + wxT(" ") + (wxTimeSpan::Milliseconds(time)).Format() + wxT(")")); + + //logFile.close(); <- not needed } -private: bool readyToWrite; wxFFile logFile; wxStopWatch totalTime; }; -class DeleteOnExit -{ -public: - DeleteOnExit(LogFile* log) : m_log(log) {} - ~DeleteOnExit() - { - if (m_log) delete m_log; - } - -private: - LogFile* m_log; -}; - - void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSettings& globalSettings) { - applicationRunsInBatchWithoutWindows = false; //default value - //load XML settings XmlBatchConfig batchCfg; //structure to receive gui settings try @@ -251,59 +240,51 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet } catch (const FileError& error) { - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); return; } - //all settings have been read successfully... - applicationRunsInBatchWithoutWindows = batchCfg.silent; //this value is needed for the application to decide whether to wait for all windows to close or not //format directory names - for (vector<FolderPair>::iterator i = batchCfg.directoryPairs.begin(); i != batchCfg.directoryPairs.end(); ++i) + for (std::vector<FolderPair>::iterator i = batchCfg.directoryPairs.begin(); i != batchCfg.directoryPairs.end(); ++i) { i->leftDirectory = FreeFileSync::getFormattedDirectoryName(i->leftDirectory); i->rightDirectory = FreeFileSync::getFormattedDirectoryName(i->rightDirectory); } //init logfile - LogFile* log = NULL; + std::auto_ptr<LogFile> log; //delete log object on exit (if not NULL) if (batchCfg.silent) - log = new LogFile; - DeleteOnExit dummy(log); //delete log object on exit (if not NULL) - - if (log && !log->isOkay()) - { //handle error: file load - wxMessageBox(_("Unable to create logfile!"), _("Error"), wxOK | wxICON_ERROR); - return; + { + log = std::auto_ptr<LogFile>(new LogFile); + if (!log->isOkay()) + { //handle error: file load + wxMessageBox(_("Unable to create logfile!"), _("Error"), wxOK | wxICON_ERROR); + return; + } } - //begin of synchronization process (all in one try-catch block) try { - FileCompareResult currentGridData; //class handling status updates and error messages - BatchStatusUpdater statusUpdater(batchCfg.mainCfg.ignoreErrors, batchCfg.silent, log); + std::auto_ptr<BatchStatusHandler> statusHandler; //delete object automatically + if (batchCfg.silent) + statusHandler = std::auto_ptr<BatchStatusHandler>(new BatchStatusHandlerSilent(batchCfg.mainCfg.ignoreErrors, log.get(), returnValue)); + else + statusHandler = std::auto_ptr<BatchStatusHandler>(new BatchStatusHandlerGui(batchCfg.mainCfg.ignoreErrors, returnValue)); //test existence of Recycle Bin if (batchCfg.mainCfg.useRecycleBin) { if (!FreeFileSync::recycleBinExists()) - { - statusUpdater.setFinalStatus(_("Unable to initialize Recycle Bin!"), SyncStatus::ABORTED); - returnValue = -2; - return; - } + statusHandler->exitAndSetStatus(_("Unable to initialize Recycle Bin!"), BatchStatusHandler::ABORTED); } //check if directories are valid wxString errorMessage; if (!FreeFileSync::foldersAreValidForComparison(batchCfg.directoryPairs, errorMessage)) - { - statusUpdater.setFinalStatus(errorMessage, SyncStatus::ABORTED); - returnValue = -2; - return; - } + statusHandler->exitAndSetStatus(errorMessage, BatchStatusHandler::ABORTED); //check if folders have dependencies @@ -314,11 +295,7 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet { //abort if in silent mode if (batchCfg.silent) - { - statusUpdater.setFinalStatus(warningMessage, SyncStatus::ABORTED); - returnValue = -2; - return; - } + statusHandler->exitAndSetStatus(warningMessage, BatchStatusHandler::ABORTED); //non silent mode: offer possibility to ignore issue bool hideThisDialog = false; @@ -326,13 +303,11 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet _("Consider this when setting up synchronization rules: You might want to avoid write access to these directories so that synchronization of both does not interfere."); //show popup and ask user how to handle warning - WarningDlg* warningDlg = new WarningDlg(statusUpdater.getWindow(), WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, messageText, hideThisDialog); - if (warningDlg->ShowModal() == WarningDlg::BUTTON_ABORT) - { - statusUpdater.setFinalStatus(warningMessage, SyncStatus::ABORTED); - returnValue = -2; - return; - } + WarningDlg* warningDlg = new WarningDlg(NULL, WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, messageText, hideThisDialog); + const int rv = warningDlg->ShowModal(); + warningDlg->Destroy(); + if (rv == WarningDlg::BUTTON_ABORT) + statusHandler->exitAndSetStatus(warningMessage, BatchStatusHandler::ABORTED); else globalSettings.global.folderDependCheckActive = !hideThisDialog; } @@ -340,263 +315,246 @@ void Application::runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSet //COMPARE DIRECTORIES + FileCompareResult currentGridData; bool lineBreakOnMessages = !batchCfg.silent; - FreeFileSync::CompareProcess comparison(lineBreakOnMessages, &statusUpdater); + + #ifdef FFS_WIN + FreeFileSync::CompareProcess comparison(lineBreakOnMessages, globalSettings.global.handleDstOnFat32, statusHandler.get()); + #elif defined FFS_LINUX + FreeFileSync::CompareProcess comparison(lineBreakOnMessages, false, statusHandler.get()); + #endif comparison.startCompareProcess(batchCfg.directoryPairs, batchCfg.mainCfg.compareVar, currentGridData); -#ifdef FFS_WIN - //check if DST time correction needs to be applied - if (globalSettings.global.dstCheckActive) - { - int timeShift = 0; - wxString driveName; - FreeFileSync::checkForDSTChange(currentGridData, batchCfg.directoryPairs, timeShift, driveName); - if (timeShift) - { - //abort if in silent mode - if (batchCfg.silent) - { - statusUpdater.setFinalStatus(_("Daylight saving time change detected for FAT/FAT32 drive."), SyncStatus::ABORTED); - returnValue = -2; - return; - } - - //non silent mode: offer possibility to resolve issue - bool hideThisDialog = false; - wxString errorMessage = wxString(_("A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive.")) + wxT("\n") - + _("You can adjust the file times accordingly to resolve the issue:"); - errorMessage+= wxString(wxT("\n\n")) + _("Drive:") + wxT(" ") + driveName + wxT("\n") - + _("Time shift:") + wxT(" ") + globalFunctions::numberToWxString(timeShift); - - //show popup and ask user how to handle the DST change - WarningDlg* warningDlg = new WarningDlg(statusUpdater.getWindow(), WarningDlg::BUTTON_RESOLVE | WarningDlg::BUTTON_IGNORE, errorMessage, hideThisDialog); - warningDlg->m_bitmap10->SetBitmap(*globalResource.bitmapClock); - - if (warningDlg->ShowModal() == WarningDlg::BUTTON_RESOLVE) - { - ModifyFilesDlg* modifyDlg = new ModifyFilesDlg(NULL, driveName, timeShift); - modifyDlg->ShowModal(); - delete modifyDlg; - - //exit batch processing - statusUpdater.setFinalStatus(wxString(_("Daylight saving time change detected for FAT/FAT32 drive.")) + wxT("\n\n") - + _("Please restart synchronization!"), SyncStatus::ABORTED); - returnValue = -2; - return; - } - else - globalSettings.global.dstCheckActive = !hideThisDialog; - } - } -#endif //FFS_WIN - - //APPLY FILTERS if (batchCfg.mainCfg.filterIsActive) FreeFileSync::filterCurrentGridData(currentGridData, batchCfg.mainCfg.includeFilter, batchCfg.mainCfg.excludeFilter); //check if there are files/folders to be sync'ed at all - int objectsToCreate = 0; - int objectsToOverwrite = 0; - int objectsToDelete = 0; - double dataToProcess = 0; - FreeFileSync::calcTotalBytesToSync(objectsToCreate, - objectsToOverwrite, - objectsToDelete, - dataToProcess, - currentGridData, - batchCfg.mainCfg.syncConfiguration); - if (objectsToCreate + objectsToOverwrite + objectsToDelete == 0) - { - statusUpdater.setFinalStatus(_("Nothing to synchronize according to configuration!"), SyncStatus::FINISHED_WITH_SUCCESS); //inform about this special case - returnValue = 0; - return; - } + if (!synchronizationNeeded(currentGridData, batchCfg.mainCfg.syncConfiguration)) + statusHandler->exitAndSetStatus(_("Nothing to synchronize according to configuration!"), BatchStatusHandler::FINISHED); //inform about this special case //START SYNCHRONIZATION - FreeFileSync::SyncProcess synchronization(batchCfg.mainCfg.useRecycleBin, lineBreakOnMessages, &statusUpdater); + FreeFileSync::SyncProcess synchronization(batchCfg.mainCfg.useRecycleBin, lineBreakOnMessages, statusHandler.get()); synchronization.startSynchronizationProcess(currentGridData, batchCfg.mainCfg.syncConfiguration); } - catch (AbortThisProcess& theException) //exit used by statusUpdater - { - returnValue = -4; + catch (AbortThisProcess&) //exit used by statusHandler + { //don't set returnValue here! Program flow may arrive here in non-error situations also! E.g. "nothing to synchronize" return; } return; //exit program } -//###################################################################################################### -BatchStatusUpdater::BatchStatusUpdater(bool ignoreAllErrors, bool silent, LogFile* log) : - m_log(log), +//###################################################################################################### +BatchStatusHandlerSilent::BatchStatusHandlerSilent(bool ignoreAllErrors, LogFile* log, int& returnVal) : ignoreErrors(ignoreAllErrors), - silentMode(silent), - currentProcess(StatusHandler::PROCESS_NONE) + currentProcess(StatusHandler::PROCESS_NONE), + returnValue(returnVal), + m_log(log) {} + + +BatchStatusHandlerSilent::~BatchStatusHandlerSilent() { - if (!silentMode) - { - syncStatusFrame = new SyncStatus(this, NULL); - syncStatusFrame->Show(); - } + unsigned int failedItems = unhandledErrors.GetCount(); + if (failedItems) + returnValue = -5; + + //write result + if (abortRequested) + m_log->write(_("Synchronization aborted!"), _("Error")); + else if (failedItems) + m_log->write(_("Synchronization completed with errors!"), _("Error")); + else + m_log->write(_("Synchronization completed successfully!"), _("Info")); } -BatchStatusUpdater::~BatchStatusUpdater() +inline +void BatchStatusHandlerSilent::updateStatusText(const Zstring& text) { - unsigned int failedItems = unhandledErrors.GetCount(); + if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) + m_log->write(text.c_str(), _("Info")); +} + - //output the result - if (silentMode) +inline +void BatchStatusHandlerSilent::initNewProcess(int objectsTotal, double dataTotal, StatusHandler::Process processID) +{ + currentProcess = processID; +} + + +ErrorHandler::Response BatchStatusHandlerSilent::reportError(const Zstring& text) +{ + if (ignoreErrors) { - if (!customStatusMessage.IsEmpty()) - m_log->close(customStatusMessage); - else if (abortRequested) - m_log->close(_("Synchronization aborted!")); - else if (failedItems) - m_log->close(_("Synchronization completed with errors!")); - else - m_log->close(_("Synchronization completed successfully.")); + unhandledErrors.Add(text.c_str()); + m_log->write(text.c_str(), _("Error")); + return ErrorHandler::IGNORE_ERROR; } else { - wxString finalMessage; - if (failedItems) - { - finalMessage = wxString(_("Warning: Synchronization failed for %x item(s):")) + wxT("\n\n"); - finalMessage.Replace(wxT("%x"), globalFunctions::numberToWxString(failedItems), false); + unhandledErrors.Add(text.c_str()); + m_log->write(text.c_str(), _("Error")); + abortRequested = true; + throw AbortThisProcess(); + } +} - for (unsigned int j = 0; j < failedItems; ++j) - finalMessage+= unhandledErrors[j] + wxT("\n"); - finalMessage+= wxT("\n"); - } - //notify to syncStatusFrame that current process has ended - if (!customStatusMessage.IsEmpty()) //custom status message written by service consumer - { - finalMessage+= customStatusMessage; - syncStatusFrame->setStatusText_NoUpdate(finalMessage); - syncStatusFrame->processHasFinished(customStatusId); - } - else if (abortRequested) - { - finalMessage+= _("Synchronization aborted!"); - syncStatusFrame->setStatusText_NoUpdate(finalMessage); - syncStatusFrame->processHasFinished(SyncStatus::ABORTED); //enable okay and close events - } - else if (failedItems) - { - finalMessage+= _("Synchronization completed with errors!"); - syncStatusFrame->setStatusText_NoUpdate(finalMessage); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR); - } - else - { - finalMessage+= _("Synchronization completed successfully."); - syncStatusFrame->setStatusText_NoUpdate(finalMessage); - syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS); - } - } +void BatchStatusHandlerSilent::abortThisProcess() //not used in this context! +{ + abortRequested = true; + throw AbortThisProcess(); } -inline -void BatchStatusUpdater::updateStatusText(const wxString& text) +void BatchStatusHandlerSilent::exitAndSetStatus(const wxString& message, ExitCode code) //abort externally { - if (silentMode) + switch (code) { - if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) - m_log->write(text, _("Info")); + case BatchStatusHandler::ABORTED: + unhandledErrors.Add(message); + m_log->write(message, _("Error")); + abortRequested = true; + throw AbortThisProcess(); + break; + + case BatchStatusHandler::FINISHED: + m_log->write(message, _("Info")); + throw AbortThisProcess(); + break; + default: + assert(false); } - else - syncStatusFrame->setStatusText_NoUpdate(text); } -void BatchStatusUpdater::initNewProcess(int objectsTotal, double dataTotal, StatusHandler::Process processID) +//###################################################################################################### +BatchStatusHandlerGui::BatchStatusHandlerGui(bool ignoreAllErrors, int& returnVal) : + ignoreErrors(ignoreAllErrors), + currentProcess(StatusHandler::PROCESS_NONE), + returnValue(returnVal) +{ + syncStatusFrame = new SyncStatus(this, NULL); + syncStatusFrame->Show(); +} + + +BatchStatusHandlerGui::~BatchStatusHandlerGui() { - currentProcess = processID; + //display result + wxString finalMessage; - if (!silentMode) + unsigned int failedItems = unhandledErrors.GetCount(); + if (failedItems) { - if (currentProcess == StatusHandler::PROCESS_SCANNING) - syncStatusFrame->setCurrentStatus(SyncStatus::SCANNING); + returnValue = -5; - else if (currentProcess == StatusHandler::PROCESS_COMPARING_CONTENT) - { - syncStatusFrame->resetGauge(objectsTotal, dataTotal); - syncStatusFrame->setCurrentStatus(SyncStatus::COMPARING); - } + finalMessage = wxString(_("Warning: Synchronization failed for %x item(s):")) + wxT("\n\n"); + finalMessage.Replace(wxT("%x"), globalFunctions::numberToWxString(failedItems), false); - else if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) - { - syncStatusFrame->resetGauge(objectsTotal, dataTotal); - syncStatusFrame->setCurrentStatus(SyncStatus::SYNCHRONIZING); - } - else assert(false); + for (unsigned int j = 0; j < failedItems; ++j) + finalMessage+= unhandledErrors[j] + wxT("\n"); + finalMessage+= wxT("\n"); + } + + if (!additionalStatusInfo.IsEmpty()) + finalMessage += additionalStatusInfo + wxT("\n\n"); + + //notify to syncStatusFrame that current process has ended + if (abortRequested) + { + finalMessage+= _("Synchronization aborted!"); + syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); + syncStatusFrame->processHasFinished(SyncStatus::ABORTED); //enable okay and close events + } + else if (failedItems) + { + finalMessage+= _("Synchronization completed with errors!"); + syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR); + } + else + { + finalMessage+= _("Synchronization completed successfully!"); + syncStatusFrame->setStatusText_NoUpdate(finalMessage.c_str()); + syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS); } } inline -void BatchStatusUpdater::updateProcessedData(int objectsProcessed, double dataProcessed) +void BatchStatusHandlerGui::updateStatusText(const Zstring& text) +{ + syncStatusFrame->setStatusText_NoUpdate(text); +} + + +void BatchStatusHandlerGui::initNewProcess(int objectsTotal, double dataTotal, StatusHandler::Process processID) { - if (!silentMode) + currentProcess = processID; + + if (currentProcess == StatusHandler::PROCESS_SCANNING) + syncStatusFrame->setCurrentStatus(SyncStatus::SCANNING); + + else if (currentProcess == StatusHandler::PROCESS_COMPARING_CONTENT) { - if (currentProcess == StatusHandler::PROCESS_SCANNING) - syncStatusFrame->m_gauge1->Pulse(); - else if (currentProcess == StatusHandler::PROCESS_COMPARING_CONTENT) - syncStatusFrame->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); - else if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) - syncStatusFrame->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); - else assert(false); + syncStatusFrame->resetGauge(objectsTotal, dataTotal); + syncStatusFrame->setCurrentStatus(SyncStatus::COMPARING); } + + else if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) + { + syncStatusFrame->resetGauge(objectsTotal, dataTotal); + syncStatusFrame->setCurrentStatus(SyncStatus::SYNCHRONIZING); + } + else assert(false); } -ErrorHandler::Response BatchStatusUpdater::reportError(const wxString& text) +inline +void BatchStatusHandlerGui::updateProcessedData(int objectsProcessed, double dataProcessed) { - if (silentMode) //write error message log and abort the complete session if necessary - { - unhandledErrors.Add(text); - m_log->write(text, _("Error")); + if (currentProcess == StatusHandler::PROCESS_SCANNING) + ; + else if (currentProcess == StatusHandler::PROCESS_COMPARING_CONTENT) + syncStatusFrame->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); + else if (currentProcess == StatusHandler::PROCESS_SYNCHRONIZING) + syncStatusFrame->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); + else assert(false); +} - if (ignoreErrors) // /|\ before return, the logfile is written!!! - return ErrorHandler::IGNORE_ERROR; - else - { - abortRequested = true; - throw AbortThisProcess(); - } + +ErrorHandler::Response BatchStatusHandlerGui::reportError(const Zstring& text) +{ + if (ignoreErrors) //this option can be set from commandline or by the user in the error dialog on UI + { + unhandledErrors.Add(text.c_str()); + return ErrorHandler::IGNORE_ERROR; } - else //show dialog to user who can decide how to continue + else { - if (ignoreErrors) //this option can be set from commandline or by the user in the error dialog on UI - { - unhandledErrors.Add(text); - return ErrorHandler::IGNORE_ERROR; - } - syncStatusFrame->updateStatusDialogNow(); bool ignoreNextErrors = false; - wxString errorMessage = text + wxT("\n\n") + _("Ignore this error, retry or abort?"); + wxString errorMessage = wxString(text) + wxT("\n\n") + _("Ignore this error, retry or abort?"); ErrorDlg* errorDlg = new ErrorDlg(syncStatusFrame, errorMessage, ignoreNextErrors); - int rv = errorDlg->ShowModal(); - switch (rv) + switch (errorDlg->ShowModal()) { case ErrorDlg::BUTTON_IGNORE: ignoreErrors = ignoreNextErrors; - unhandledErrors.Add(text); + unhandledErrors.Add(text.c_str()); return ErrorHandler::IGNORE_ERROR; case ErrorDlg::BUTTON_RETRY: return ErrorHandler::RETRY; case ErrorDlg::BUTTON_ABORT: { - unhandledErrors.Add(text); + unhandledErrors.Add(text.c_str()); abortRequested = true; throw AbortThisProcess(); } @@ -609,31 +567,37 @@ ErrorHandler::Response BatchStatusUpdater::reportError(const wxString& text) inline -void BatchStatusUpdater::forceUiRefresh() +void BatchStatusHandlerGui::forceUiRefresh() { - if (!silentMode) - syncStatusFrame->updateStatusDialogNow(); -} - + if (currentProcess == StatusHandler::PROCESS_SCANNING) + syncStatusFrame->m_gauge1->Pulse(); //expensive! So put it here! -void BatchStatusUpdater::abortThisProcess() -{ - throw AbortThisProcess(); //abort can be triggered by syncStatusFrame + syncStatusFrame->updateStatusDialogNow(); } -void BatchStatusUpdater::setFinalStatus(const wxString& message, SyncStatus::SyncStatusID id) +void BatchStatusHandlerGui::abortThisProcess() { - customStatusMessage = message; - customStatusId = id; + abortRequested = true; + throw AbortThisProcess(); //abort can be triggered by syncStatusFrame } -wxWindow* BatchStatusUpdater::getWindow() +void BatchStatusHandlerGui::exitAndSetStatus(const wxString& message, ExitCode code) //abort externally { - assert(!silentMode); - if (!silentMode) - return syncStatusFrame; - else - return NULL; + switch (code) + { + case BatchStatusHandler::ABORTED: + unhandledErrors.Add(message); + abortRequested = true; + throw AbortThisProcess(); + break; + + case BatchStatusHandler::FINISHED: + additionalStatusInfo = message; + throw AbortThisProcess(); + break; + default: + assert(false); + } } diff --git a/Application.h b/Application.h index fbb46f4b..e1b12172 100644 --- a/Application.h +++ b/Application.h @@ -24,49 +24,87 @@ public: bool OnExceptionInMainLoop(); void initialize(); - bool ProcessIdle(); //virtual method! + + bool ProcessIdle(); //virtual impl. private: void runBatchMode(const wxString& filename, xmlAccess::XmlGlobalSettings& globalSettings); - bool applicationRunsInBatchWithoutWindows; CustomLocale programLanguage; int returnValue; xmlAccess::XmlGlobalSettings globalSettings; //settings used by GUI, batch mode or both }; -class LogFile; -class BatchStatusUpdater : public StatusHandler +class BatchStatusHandler : public StatusHandler +{ +public: + BatchStatusHandler() {} + virtual ~BatchStatusHandler() {} + + enum ExitCode + { + NONE, + ABORTED, + FINISHED + }; + virtual void exitAndSetStatus(const wxString& message, ExitCode code) = 0; //overwrite final status message text +}; + + +class LogFile; +class BatchStatusHandlerSilent : public BatchStatusHandler { public: - BatchStatusUpdater(bool ignoreAllErrors, bool silent, LogFile* log); - ~BatchStatusUpdater(); + BatchStatusHandlerSilent(bool ignoreAllErrors, LogFile* log, int& returnVal); + ~BatchStatusHandlerSilent(); + - virtual void updateStatusText(const wxString& text); - virtual void initNewProcess(int objectsTotal, double dataTotal, Process processID); - virtual void updateProcessedData(int objectsProcessed, double dataProcessed); - virtual ErrorHandler::Response reportError(const wxString& text); - virtual void forceUiRefresh(); + void updateStatusText(const Zstring& text); //virtual impl. + void initNewProcess(int objectsTotal, double dataTotal, Process processID); //virtual impl. + void updateProcessedData(int objectsProcessed, double dataProcessed) {} //virtual impl. + ErrorHandler::Response reportError(const Zstring& text); //virtual impl. + void forceUiRefresh() {} //virtual impl. - wxWindow* getWindow(); - void setFinalStatus(const wxString& message, SyncStatus::SyncStatusID id); //overwrite final status message text + void exitAndSetStatus(const wxString& message, ExitCode code); //abort externally //virtual impl. private: - virtual void abortThisProcess(); + void abortThisProcess(); //virtual impl. - LogFile* m_log; - SyncStatus* syncStatusFrame; bool ignoreErrors; - bool silentMode; - wxArrayString unhandledErrors; //list of non-resolved errors Process currentProcess; + int& returnValue; - wxString customStatusMessage; //final status message written by service consumer - SyncStatus::SyncStatusID customStatusId; + LogFile* m_log; }; +class BatchStatusHandlerGui : public BatchStatusHandler +{ +public: + BatchStatusHandlerGui(bool ignoreAllErrors, int& returnVal); + ~BatchStatusHandlerGui(); + + void updateStatusText(const Zstring& text); //virtual impl. + void initNewProcess(int objectsTotal, double dataTotal, Process processID); //virtual impl. + void updateProcessedData(int objectsProcessed, double dataProcessed); //virtual impl. + ErrorHandler::Response reportError(const Zstring& text); //virtual impl. + void forceUiRefresh(); //virtual impl. + + void exitAndSetStatus(const wxString& message, ExitCode code); //abort externally //virtual impl. + +private: + void abortThisProcess(); //virtual impl. + + bool ignoreErrors; + wxArrayString unhandledErrors; //list of non-resolved errors + Process currentProcess; + int& returnValue; + + SyncStatus* syncStatusFrame; + wxString additionalStatusInfo; //workaround to display "Nothing to synchronize..." +}; + #endif // FREEFILESYNCAPP_H diff --git a/Changelog.txt b/Changelog.txt index ae932a36..5ccec069 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,29 @@ FreeFileSync ------------ +Changelog v1.15 +--------------- +Fixed performance bottleneck in batch mode (non-silent) +Improved performance of comparison by another 10% +Configure column settings by right-click context menu +Remember column positions on main grid +Hide/Show individual columns +Added "sort by comparison result" +Sort file list by relative name after comparison (GUI mode only) +Removed Windows registry usage for portable version +Restored linebreaks in status texts for better readability +Revised German translation. Thanks to Latino! +Created custom button control to finally translate "compare" and "synchronize" +Allow manual setup of file manager integration (Windows and Linux) +Added Step-By-Step guide for manual compilation (Windows and Linux) +Added checkboxes to manually select/deselect rows +New option: Treat files with time deviation of less-equal 1 hour as equal (FAT/FAT32 drives only) +Added Polish translation +Added Portuguese translation +Added Italian translation +Updated translation files + + Changelog v1.14 --------------- Massive performance improvements: diff --git a/FreeFileSync - Unicode.cbp b/FreeFileSync.cbp index 1354a49e..0374bbd6 100644 --- a/FreeFileSync - Unicode.cbp +++ b/FreeFileSync.cbp @@ -13,7 +13,6 @@ <Option compiler="gcc" /> <Option projectLinkerOptionsRelation="2" /> <Compiler> - <Add option="-pg" /> <Add option="-g" /> <Add option="-D__WXDEBUG__" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswud" /> @@ -22,7 +21,6 @@ <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib\mswud" /> </ResourceCompiler> <Linker> - <Add option="-pg -lgmon" /> <Add library="libwxmsw28ud_adv.a" /> <Add library="libwxmsw28ud_core.a" /> <Add library="libwxbase28ud.a" /> @@ -96,17 +94,12 @@ <Add option="-mthreads" /> <Add library="libkernel32.a" /> <Add library="libuser32.a" /> - <Add library="libgdi32.a" /> - <Add library="libwinspool.a" /> - <Add library="libcomdlg32.a" /> - <Add library="libadvapi32.a" /> - <Add library="libshell32.a" /> - <Add library="libole32.a" /> - <Add library="liboleaut32.a" /> <Add library="libuuid.a" /> <Add library="libcomctl32.a" /> - <Add library="libwsock32.a" /> - <Add library="libodbc32.a" /> + <Add library="libole32.a" /> + <Add library="liboleaut32.a" /> + <Add library="libgdi32.a" /> + <Add library="libcomdlg32.a" /> <Add directory="C:\Programme\C++\wxWidgets\lib\gcc_lib" /> </Linker> <Unit filename="FreeFileSync.h"> @@ -132,6 +125,14 @@ <Option target="Debug" /> <Option target="Release" /> </Unit> + <Unit filename="library\customButton.cpp"> + <Option target="Debug" /> + <Option target="Release" /> + </Unit> + <Unit filename="library\customButton.h"> + <Option target="Debug" /> + <Option target="Release" /> + </Unit> <Unit filename="library\customGrid.cpp"> <Option target="Debug" /> <Option target="Release" /> diff --git a/FreeFileSync.h b/FreeFileSync.h index 4b269863..c4771171 100644 --- a/FreeFileSync.h +++ b/FreeFileSync.h @@ -97,13 +97,13 @@ namespace FreeFileSync if (aLength != bLength) return aLength < bLength; #ifdef FFS_WIN //Windows does NOT distinguish between upper/lower-case - return relativeName.CmpNoCase(b.relativeName) < 0; + return relativeName.CmpNoCase(b.relativeName) < 0; //implementing a (reverse) comparison manually is a lot slower! #elif defined FFS_LINUX //Linux DOES distinguish between upper/lower-case return relativeName.Cmp(b.relativeName) < 0; #endif } }; - typedef vector<FileDescrLine> DirectoryDescrType; + typedef std::vector<FileDescrLine> DirectoryDescrType; enum CompareFilesResult @@ -129,11 +129,11 @@ namespace FreeFileSync CompareFilesResult cmpResult; bool selectedForSynchronization; }; - typedef vector<FileCompareLine> FileCompareResult; + typedef std::vector<FileCompareLine> FileCompareResult; typedef int GridViewLine; - typedef vector<GridViewLine> GridView; //vector of references to lines in FileCompareResult + typedef std::vector<GridViewLine> GridView; //vector of references to lines in FileCompareResult struct FolderPair @@ -150,7 +150,7 @@ namespace FreeFileSync ~AbortThisProcess() {} }; - const int FILE_TIME_PRECISION = 2; //file times have precision of 2 seconds due to FAT/FAT32 file systems + const time_t FILE_TIME_PRECISION = 2; //file times have precision of 2 seconds due to FAT/FAT32 file systems const wxString LAST_CONFIG_FILE = wxT("LastRun.ffs_gui"); const wxString GLOBAL_CONFIG_FILE = wxT("GlobalSettings.xml"); } diff --git a/chinese_simple.lng b/Languages/chinese_simple.lng index 198f479a..2f10d89e 100644 --- a/chinese_simple.lng +++ b/Languages/chinese_simple.lng @@ -14,12 +14,18 @@ kB != files are different\n != 文件不同\n +%x directories +%x 目录 +%x files, +%x 文件, +%x of %y rows in view +%x of %y 横向视图 +%x of 1 row in view +%x of 1 行视图 &Abort 取消(&A) &About... 关于(&A)... -&Adjust file times -调整文件时间(&A) &Advanced 高级(&A) &Back @@ -28,8 +34,6 @@ 撒消(&C) &Compare 比较(&C) -&Create -创建(&C) &Create batch job 创建批处理作业(&C) &Default @@ -58,10 +62,8 @@ 重试(&R) &Start 开始(&S) -&Synchronize -同步(&S) -(-) filtered out from sync-process\n -(-) 从同步進程中过滤出\n +&Synchronize... +同步(&S)... , . - different @@ -88,8 +90,14 @@ -开源文件同步器- . , +1 directory +1 目录 +1 file, +1 文件, 1. &Compare 1. 比较(&C) +1. Enter full file or directory names separated by ';' or a new line. +1. 输入完整的文件名或目录名(用";"号或一个新行) 2. &Synchronize... 2. 同步(&S)... 2. Use wildcard characters '*' and '?'. @@ -122,20 +130,10 @@ Action 动作 Add folder pair 添加成对文件夹 -Add to exclude filter: -添加到排除过滤: -Adjust file times -调整文件时间 -Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article: -调整修改时,所有的文件载于指定的文件夹及其子文件夹。\n这本手册适应可能需要如果您是同步对FAT32驱动器和夏令时的情况。\n概述的问题参阅此文章: -All file times have been adjusted successfully! -所有文件时间已经调整成功! All items have been synchronized! 所有项目已经同步完成! An exception occured! 发生异常! -Apply -应用 As a result the files are separated into the following categories: 由该文件分为以下几类: As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller: @@ -162,6 +160,8 @@ Compare by... 比较选项... Comparing content 正在比较内容 +Comparing content of files %x +正在比较档案内容的百分比 %x Comparing... 比较中... Completed @@ -186,6 +186,8 @@ Consider this when setting up synchronization rules: You might want to avoid wri 设置同步规则时审核:您可能要避免写入权限能存取到这些目录,以便同步时两个不干预 Continue 继续 +Conversion error: +转换错误: Copy from left to right 从左侧复制到右侧 Copy from left to right overwriting @@ -198,12 +200,20 @@ Copy new or updated files to right folder. 复制新的或修改过的文件到右侧文件夹 Copy to clipboard\tCTRL+C 复制到剪贴板\t使用CTRL+C键 +Copying file %x overwriting %y +正复制文件 %x 正覆盖 %y +Copying file %x to %y +正复制文件 %x 到 %y Could not retrieve file info for: 无法检索下列文件信息: +Could not set working directory: +无法设置工作目录: Create a batch job 创建一个批工作 Create: 创建: +Creating folder %x +正创建文件夹 %x Current operation: 当前操作: Custom @@ -216,8 +226,6 @@ Data: 数据: Date 日期 -Daylight saving time change detected for FAT/FAT32 drive. -改变时间(FAT/FAT32驱动器) Delete files/folders existing on left side only 仅从左侧中删除文件/方件夹 Delete files/folders existing on right side only @@ -226,6 +234,10 @@ Delete files\tDEL 删除文件\t使用DEL键 Delete: 删除: +Deleting file %x +正删除文件 %x +Deleting folder %x +正删除文件夹 %x Directories are dependent: 目录已经存在: Directory does not exist: @@ -248,8 +260,12 @@ Email: 电子邮件: Error 错误 +Error changing modification time: +修改时间出错: Error copying file: 复制文件出错: +Error creating directory: +创建目录出错: Error deleting directory: 删除目录出错: Error deleting file: @@ -262,16 +278,18 @@ Error reading file: 读取文件出错: Error traversing directory: 遍历目录出错: +Error writing file: +写入文件出错: Error: Source directory does not exist anymore: 错误:源目录根本不存在: Example 例如 Exclude 例外 -Exclude temporarily -暂时例外 Feedback and suggestions are welcome at: 欢迎在下面提出反馈意见和建议: +File already exists. Overwrite? +文件已经存在.覆盖? File content 文件内容 File list exported! @@ -304,6 +322,10 @@ Files/folders that exist on right side only 仅在左侧存在的档案/文件夹 Filter 过滤 +Filter active: Press again to deactivate +过滤激活: 请按键以关闭激活 +Filter files +过滤文件 Filter view 过滤查看 Folder pair @@ -350,10 +372,10 @@ Ignore next errors 忽略下一个错误 Ignore this error, retry or abort synchronization? 忽略这个错误,重试或取消同步? +Ignore this error, retry or abort? +忽略这个错误,重试或取消? Include 包括 -Include temporarily -暂时包括 Include: *.doc;*.zip;*.exe\nExclude: *\\temp\\* 包括:*.doc;*.zip;*.exe 除外:*\\temp\\* Info @@ -362,6 +384,8 @@ Information 信息 Information: If you ignore the error or abort a re-compare will be necessary! 信息:如果你忽略或取消这个错误则有必要作再次比较! +Initialization of Recycle Bin failed! +初始化回收站失败! It was not possible to initialize the Recycle Bin!\n\nIt's likely that you are not using Windows.\nIf you want this feature included, please contact the author. :) 初始化回收站是不大可能了!估计你使用的不是Windows系统.如果你想未来在此系统上应用请联系作者. :) Left folder: @@ -372,22 +396,26 @@ Load configuration via...\n - this list (press DEL to delete items)\n - 加载配置(通过)...\n - 这个列表(用DEL键删除项目)\n - 拖拽到这个窗口\n - 启动参数 Load from file... 从文件加载... +Log-messages: +日志信息: Mirror ->> 镜像 ->> Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. 左侧文件夹镜像备份: 同步后右侧文件夹将被覆盖(完全匹配左边的文件夹). Not all items were synchronized! Have a look at the list. 不是所有项目被同步!看一下列表 +Nothing to synchronize according to configuration! +根据配置没有任何同步! Number of files and directories that will be created 一些文件和目录将被创建 Number of files and directories that will be deleted 一些文件和目录将被删除 Number of files that will be overwritten 一些文件和目录将被覆盖 +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. +只有过滤的文件/目录将选定做同步.该过滤器将被应用到全称包括路径前缀. Open synchronization dialog 打开同步对话框 -Open with Explorer\tD-Click -随资源管理器打开\t使用双击D-Click Operation aborted! 操作已取消! Operation: @@ -396,8 +424,6 @@ Pause 暂停 Please fill all empty directory fields. 请填满所有空的目录区域. -Please restart synchronization! -请重新开始同步! Press button to activate filter 请按键以激活过滤 Preview @@ -416,6 +442,8 @@ Right folder: 右侧文件夹: S&ave configuration 保存配置(&A) +Save aborted! +保存失败! Save current configuration to file 保存当前配置到文件 Scanning... @@ -426,8 +454,6 @@ Select a folder 选择一个文件夹 Select variant: 选择变化的: -Set filter for synchronization -为同步设置过滤 Show files that are different 显示不同的文件 Show files that are equal @@ -456,8 +482,8 @@ Swap sides 换边 Synchronization aborted! 同步已放弃! -Synchronization completed successfully. -同步成功完成. +Synchronization completed successfully! +同步成功完成! Synchronization completed with errors! 同步已完成但有错误. Synchronization settings @@ -472,14 +498,14 @@ Synchronizing... 同步中... System out of memory! 系统内在溢出! +The file does not contain a valid configuration: +该文件不包含有效的配置: The selected file does not exist: 选定的文件不存在: 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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. 这两个同样变异评估命名文件时,在同等条件下,\n他们有同样的文件大小相同的最后收件日期和时间.\n请注意,该文件的时间允许偏差的2秒钟.\n这可确保同步较低文件系统FAT32的精密正常工作. Time elapsed: 已用时间: -Time shift in seconds -几秒内的时间偏移 Time: 时间: Total amount of data that will be transferred @@ -492,8 +518,6 @@ Unable to create logfile! 无法创建日志! Unable to initialize Recycle Bin! 无法初始化回收站! -Unresolved errors occured during operation! -操作中出现异常错误! Update -> 升级 -> Update: @@ -504,10 +528,10 @@ Use Recycle Bin when deleting or overwriting files during synchronization 当同步时使用回收站删除或覆盖档案 Warning 警告 +Warning: Synchronization failed for %x item(s): +警告:同步失败 %x (某些)项目: When \"Compare\" is triggered with this option set the following decision tree is processed: 当"比较" 被触发则按照决定树这个办法规定了做以下处理: -You can adjust the file times accordingly to resolve the issue: -您可以调整相应的文件时间来解决这个问题: You may try to synchronize remaining items again (WITHOUT having to re-compare)! 您可能会尝试再次同步,其余的项目(而不必再比较)! different diff --git a/dutch.lng b/Languages/dutch.lng index e1e0a52e..a731bb32 100644 --- a/dutch.lng +++ b/Languages/dutch.lng @@ -26,8 +26,6 @@ &Afbreken &About... &Informatie... -&Adjust file times -&Pas bestandstijden aan &Advanced &Geavanceerd &Back @@ -36,8 +34,6 @@ &Annuleren &Compare &Vergelijken -&Create -&Creëer &Create batch job &Creëer batchjob &Default @@ -66,10 +62,6 @@ &Opnieuw proberen &Start &Start -&Synchronize -&Synchroniseer -(-) filtered out from sync-process\n -(-) wordt niet gesynchroniseerd\n , . - different @@ -124,8 +116,6 @@ == bestanden zijn gelijk\n\n >> right file is newer\n >> rechter bestand is nieuwer\n -A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive. -Een time shift, van een bestand, door zomertijd is gedetecteerd op een FAT/FAT32 schijf. Abort Afbreken Abort requested: Waiting for current operation to finish... @@ -138,20 +128,10 @@ Action Actie Add folder pair Voeg 1 paar gekoppelde mappen toe -Add to exclude filter: -Voeg toe om filter uit te sluiten: -Adjust file times -Pas bestandstijden aan -Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article: -Past de bewerkingstijden aan van alle bestanden in de gespecificeerde map en onderliggende mappen. Deze handeling is misschien nodig als u synchroniseerd naar een FAT32-schijf en de zomertijd is ingeschakeld. Voor meer informatie hierover kunt u terecht bij het volgende artikel: -All file times have been adjusted successfully! -Alle bestandstijden zijn succesvol aangepast! All items have been synchronized! Alle bestanden zijn gesynchroniseerd! An exception occured! Er heeft een uitzondering plaatsgevonden! -Apply -Toepassen As a result the files are separated into the following categories: Hierdoor worden de bestanden gescheiden in de volgende categorieën: 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: @@ -178,8 +158,8 @@ Compare by... Vergelelijk met... Comparing content Vergelijken van inhoud -Comparing content of files \"%x\" -De inhoud van \"%x\" bestanden wordt vergeleken +Comparing content of files %x +De inhoud van %x bestanden wordt vergeleken Comparing... Vergelijken... Completed @@ -218,10 +198,10 @@ Copy new or updated files to right folder. Kopieer nieuwe of geupdate bestanden naar de rechter map. Copy to clipboard\tCTRL+C Kopieer naar het klembord\tCTRL+C -Copying file \"%x\" overwriting \"%y\" -Bestand \"%y\" wordt overschreven door een kopie van \"%x\" -Copying file \"%x\" to \"%y\" -Bestand \"%x\" wordt gekopieerd naar \"%y\" +Copying file %x overwriting %y +Bestand %y wordt overschreven door een kopie van %x +Copying file %x to %y +Bestand %x wordt gekopieerd naar %y Could not retrieve file info for: Fout bij het verkrijgen van bestandsinformatie van: Could not set working directory: @@ -230,8 +210,8 @@ Create a batch job Creëer batchjob Create: Aanmaken: -Creating folder \"%x\" -Map \"%x\" wordt aangemaakt +Creating folder %x +Map %x wordt aangemaakt Current operation: Huidige operatie: Custom @@ -244,8 +224,6 @@ Data: Data: Date Datum -Daylight saving time change detected for FAT/FAT32 drive. -Zomertijdverandering gedetecteerd voor een FAT/FAT32 schijf. Delete files/folders existing on left side only Verwijder bestanden/folders die alleen links bestaan Delete files/folders existing on right side only @@ -254,10 +232,10 @@ Delete files\tDEL Verwijder bestanden\tDEL Delete: Verwijderen: -Deleting file \"%x\" -Bestand \"%x\" wordt verwijderd -Deleting folder \"%x\" -Map \"%x\" wordt verwijderd +Deleting file %x +Bestand %x wordt verwijderd +Deleting folder %x +Map %x wordt verwijderd Directories are dependent: De volgende paden zijn afhankelijk van elkaar: Directory does not exist: @@ -276,8 +254,6 @@ Donate with PayPal Doneer met PayPal Drag && drop Drag en drop -Drive: -Schijf: Email: Email: Error @@ -308,8 +284,6 @@ Example Voorbeeld Exclude Uitsluiten -Exclude temporarily -Tijdelijk uitsluiten Feedback and suggestions are welcome at: Tips en suggesties zijn welkom op: File already exists. Overwrite? @@ -400,8 +374,6 @@ Ignore this error, retry or abort? Negeer deze fout, opnieuw proberen of de handeling afbreken? Include Gebruiken -Include temporarily -Gebruik tijdelijk Include: *.doc;*.zip;*.exe\nExclude: *\\temp\\* Gebruiken: *.doc;*.zip;*.exe\nUitsluiten: *\\temp\\* Info @@ -442,8 +414,6 @@ Only files/directories that pass filtering will be selected for synchronization. Alleen de niet gefilterde bestanden worden geselecteerd voor synchronisatie. Het filter wordt toegepast op de volledige naam inclusief pad-voorvoegsel. Open synchronization dialog Open de synchronisatie-instellingen -Open with Explorer\tD-Click -Open met Verkenner\tD-Click Operation aborted! Operatie afgebroken! Operation: @@ -452,8 +422,6 @@ Pause Pause Please fill all empty directory fields. Vul alstublieft aan beide kanten een pad in. -Please restart synchronization! -Herstart het synchroniseren alstublieft! Press button to activate filter Druk op de knop om het filter te activeren. Preview @@ -484,8 +452,6 @@ Select a folder Selecteer een map Select variant: Selecteer een variant: -Set filter for synchronization -Filter instellen Show files that are different Geef bestanden die verschillend zijn weer Show files that are equal @@ -514,8 +480,8 @@ Swap sides Verwissel van kant Synchronization aborted! Synchronisatie afgebroken! -Synchronization completed successfully. -Synchronisatie succesvol afgerond. +Synchronization completed successfully! +Synchronisatie succesvol afgerond! Synchronization completed with errors! Synchronisatie afgerond. Er zijn fouten opgetreden. Synchronization settings @@ -538,10 +504,6 @@ This variant evaluates two equally named files as being equal when they have the Deze variant ziet twee gelijknamige bestanden als gelijk wanneer ze dezelfde bestandsgrootte EN tijdstempel hebben. Merk op dat tijdstempel 2 seconden mag verschillen. Dit zorgt ervoor dat het minder nauwkeurige FAT-32 ook kan worden gesynchroniseerd. Time elapsed: Verstreken tijd: -Time shift in seconds -Timeshift in seconden -Time shift: -Timeshift: Time: Tijd: Total amount of data that will be transferred @@ -554,8 +516,6 @@ Unable to create logfile! Niet mogelijk om een logbestand aan te maken! Unable to initialize Recycle Bin! De prullenbak kon niet worden geïnitialiseerd! -Unresolved errors occured during operation! -Er zijn niet oplosbare fouten opgetreden tijdens de handeling! Update -> Overschrijven -> Update: @@ -570,8 +530,6 @@ Warning: Synchronization failed for %x item(s): Let op: %x item(s) konden niet worden gesynchroniseerd: When \"Compare\" is triggered with this option set the following decision tree is processed: Wanneer \"Compare\" met deze instelling aan wordt gebruikt zal de volgende beslissingsboom gebruikt worden: -You can adjust the file times accordingly to resolve the issue: -U kunt de bestandstijden aanpassen om het probleem op te lossen: 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/french.lng b/Languages/french.lng index 854dbd34..c4f6207c 100644 --- a/french.lng +++ b/Languages/french.lng @@ -26,8 +26,6 @@ &Abandon &About... &A propos de... -&Adjust file times -&Ajuster les dates de fichiers &Advanced &Avancé &Back @@ -36,8 +34,6 @@ &Annuler &Compare &Comparer -&Create -&Créer &Create batch job &Créer un fichier de commandes &Default @@ -46,6 +42,8 @@ &Exportation de la liste des fichiers &File &Fichier +&Global settings +&Paramètres généraux &Help &Aide &Ignore @@ -64,12 +62,12 @@ &Résoudre &Retry &Réessayer +&Save +&Sauvegarder &Start -&Démarrage -&Synchronize -&Synchronisation -(-) filtered out from sync-process\n -(-) non synchronisés\n +&Démarrer +&Synchronize... +&Synchroniser... , - different @@ -124,8 +122,6 @@ == Les fichiers sont identiques\n\n >> right file is newer\n >> le fichier de droite est plus récent\n -A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive. -Un décalage horaire du fichier du à l'heure d'été a été détecté sur un lecteur FAT/FAT32. Abort Abandon Abort requested: Waiting for current operation to finish... @@ -136,22 +132,14 @@ About A propos de Action Action +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +Valable seulement pour les disques FAT/FAT32: Les fichiers de même nom et dont l'heure de création diffèrent de moins d'une heure sont considérés comme identiques. Cela garantit que l'heure d'été est traitée correctement. Add folder pair Ajout d'un couple de dossiers -Add to exclude filter: -Ajout au filtre exclure: -Adjust file times -Ajuster les dates de fichiers -Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article: -Ajuster les dates de modification de tous les fichiers contenus dans le dossier spécifié et ses sous-dossiers. Ce règlage manuel pourrait s'avérer nécessaire si vous synchroniser de nouveau un lecteur en FAT32 avec l'option heure d'été sectionnée. Pour plus d'informations, lire cet article : -All file times have been adjusted successfully! -Toutes les dates de fichiers ont été ajustées avec succès! All items have been synchronized! Tous les éléments ont été synchronisés! An exception occured! Une violation s'est produite! -Apply -Apliquer As a result the files are separated into the following categories: En conclusion, les fichiers sont répartis dans les catégories suivantes: As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller: @@ -160,10 +148,14 @@ Assemble a batch file with the following settings. To start synchronization in b Créer un fichier de commandes avec les paramètres suivants. Pour lancer la synchronisation en mode batch, exécutez ce fichier ou paramétrez-le dans le planificateur de tâches. Batch file created successfully! Fichier de commandes créé avec succès! +Batch job +Fichier de commandes Big thanks for localizing FreeFileSync goes out to: Pour les traductions de FreeFileSync, un grand merci à: Build: Créé: +Cancel +Annuler Choose to hide filtered files/directories from list Masquer les fichiers/répertoires filtrés Comma separated list @@ -178,8 +170,8 @@ Compare by... Comparaison par... Comparing content Comparaison du contenu -Comparing content of files \"%x\" -comparaison du contenu des fichiers \"%x\" +Comparing content of files %x +comparaison du contenu des fichiers %x Comparing... Comparaison en cours... Completed @@ -218,10 +210,10 @@ Copy new or updated files to right folder. Copie de fichiers nouveaux ou modifiés dans le dossier de droite. Copy to clipboard\tCTRL+C Copier dans le presse-papiers\tCTRL+C -Copying file \"%x\" overwriting \"%y\" -Copie fichier \"%x\" écrasant \"%y\" -Copying file \"%x\" to \"%y\" -Copie fichier \"%x\" vers \"%y\" +Copying file %x overwriting %y +Copie fichier %x écrasant %y +Copying file %x to %y +Copie fichier %x vers %y Could not retrieve file info for: Erreur lors de la lecture des attributs de fichier de : Could not set working directory: @@ -230,12 +222,14 @@ Create a batch job Création du fichier de commandes Create: Créations: -Creating folder \"%x\" -Création du dossier \"%x\" +Creating folder %x +Création du dossier %x Current operation: Opération en cours: Custom Personnaliser +Customize columns +Personnaliser les colonnes DECISION TREE ARBRE DE DECISION Data remaining: @@ -244,8 +238,6 @@ Data: Données: Date Date -Daylight saving time change detected for FAT/FAT32 drive. -Changement Heure d'été détecté sur un lecteur FAT/FAT32. Delete files/folders existing on left side only Suppression des fichiers/répertoires n'existant que sur le côté gauche Delete files/folders existing on right side only @@ -254,10 +246,10 @@ Delete files\tDEL Suppression des fichiers\tDEL Delete: Suppressions: -Deleting file \"%x\" -Suppression du fichier \"%x\" -Deleting folder \"%x\" -Suppression du dossier \"%x\" +Deleting file %x +Suppression du fichier %x +Deleting folder %x +Suppression du dossier %x Directories are dependent: Les dossiers sont liés: Directory does not exist: @@ -276,8 +268,6 @@ Donate with PayPal Faites un don avec PayPal Drag && drop Glisser && Déposer -Drive: -Lecteur: Email: Email: Error @@ -310,8 +300,14 @@ Exclude Exclure Exclude temporarily Exclure temporairement +Exclude via filter: +Exclure à l'aide du filtre: +FAT32: Handle Daylight Saving Time +FAT32: Traitement de l'heure d'été Feedback and suggestions are welcome at: Commentaires et suggestions sont les bienvenus à: +File Manager integration: +Choix du Gestionnaire de Fichiers: File already exists. Overwrite? Le fichier existe déjà. Voulez-vous le remplacer? File content @@ -364,6 +360,10 @@ FreeFileSync batch file FreeFileSync fichier de commandes FreeFileSync configuration FreeFileSync configuration +Generating file list... +Génération de la liste des fichiers... +Global settings +Paramètres généraux Help Aide Hide files that are different @@ -428,6 +428,10 @@ Mirror ->> Mirroir ->> Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. Sauvegarde miroir du répertoire de gauche : Le répertoire de droite sera écrasé et exactement identique au répertoire de gauche après la synchronisation. +Move column down +Déplacer la colonne vers le bas +Move column up +Déplacer la colonne vers le haut Not all items were synchronized! Have a look at the list. Tous les éléments n'ont pas été synchronisés! Veuillez vérifier la liste. Nothing to synchronize according to configuration! @@ -438,12 +442,14 @@ Number of files and directories that will be deleted Nombre de fichiers et de répertoires qui seront supprimés Number of files that will be overwritten Nombre de fichiers qui seront remplacés +OK +OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. -Seuls les fichiers/dossiers filtrés seront sélectionnés pour la synchronisation. Le filtre s'appliquera au nom complet incluant le chemin. +Seuls les fichiers/dossiers filtrés seront sélectionnés pour la synchronisation.\nLe filtre s'appliquera au nom complet incluant le chemin. Open synchronization dialog Ouvrir la boîte de dialogue de la synchronisation -Open with Explorer\tD-Click -Ouvrir dans l'explorateur\tD-Click +Open with File Manager\tD-Click +Ouvrir avec le Gestionnaire de Fichiers\tClick droit Operation aborted! Opération abandonnée! Operation: @@ -452,8 +458,6 @@ Pause Pause Please fill all empty directory fields. Veuillez remplir tous les champs vides du répertoire. -Please restart synchronization! -Veuillez, s'il vous plaît, relancer la synchronisation! Press button to activate filter Cliquez pour activer le filtrage Preview @@ -484,8 +488,6 @@ Select a folder Choisissez un répertoire Select variant: Choisissez une variante: -Set filter for synchronization -Définir le filtrage Show files that are different Afficher les fichiers différents Show files that are equal @@ -499,9 +501,11 @@ Afficher les fichiers existants seulement à gauche Show files that exist on right side only Afficher les fichiers existants seulement à droite Silent mode -Mode silence +Mode silencieux Size Taille +Sorting file list... +Tri de la liste des fichiers... Source code written completely in C++ utilizing: Code source écrit totalement en C++ et utilisant: Start @@ -514,10 +518,12 @@ Swap sides Permuter les côtés Synchronization aborted! Synchronisation abandonnée! -Synchronization completed successfully. -Synchronisation terminée avec succès. +Synchronization completed successfully! +Synchronisation terminée avec succès! Synchronization completed with errors! Synchronisation terminée avec des erreurs! +Synchronization filter +Filtre de synchronisation Synchronization settings Paramétrage de la synchronisation Synchronization status @@ -534,14 +540,12 @@ The file does not contain a valid configuration: Le fichier ne contient pas de configuration valide The selected file does not exist: Le fichier sélectionné n'existe pas: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +Cette commande sera exécutée à chaque fois que vous double-cliquez sur un nom de fichier. %x est un espace réservé pour le fichier sélectionné. This variant evaluates two equally named files as being equal when they have the same file size AND the same last write date and time. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. Cette variante définit comme identiques deux fichiers de même nom lorsqu'ils ont la même taille et le même date et heure de modification. Attention : la précision de l'heure est mesurée à 2 secondes près. Cela permet d'assurer la synchronisation avec la précision du systéme de fichiers FAT32. Time elapsed: Temps écoulé: -Time shift in seconds -Décalage horaire en secondes -Time shift: -Décalage horaire: Time: Heure: Total amount of data that will be transferred @@ -554,8 +558,6 @@ Unable to create logfile! Impossible de créer un fichier log! Unable to initialize Recycle Bin! Impossible d'initialiser la corbeille! -Unresolved errors occured during operation! -Des erreurs inattendues se sont produites pendant le traitement! Update -> Mise à Jour -> Update: @@ -570,8 +572,6 @@ Warning: Synchronization failed for %x item(s): Attention: La synchronisation a échouée pour %x élément(s): When \"Compare\" is triggered with this option set the following decision tree is processed: Quand \"Compare\" est lancé avec cette option, l'arbre de décision suivant est éxécuté: -You can adjust the file times accordingly to resolve the issue: -Vous pouvez modifier l'heure des fichiers pour résoudre le problème: 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/german.lng b/Languages/german.lng index 02419a9f..9df728a1 100644 --- a/german.lng +++ b/Languages/german.lng @@ -19,33 +19,31 @@ %x files, %x Dateien, %x of %y rows in view -%x von %y Zeilen zur Ansicht +%x von %y Zeilen in Ansicht %x of 1 row in view -%x von 1 Zeile zur Ansicht +%x von 1 Zeile in Ansicht &Abort -&Abbruch +&Abbrechen &About... &Über... -&Adjust file times -&Dateizeiten ändern &Advanced &Erweitert &Back &Zurück &Cancel -&Abbruch +&Abbrechen &Compare &Vergleichen -&Create -&Erzeugen &Create batch job -&Erstelle Batch-Job +&Batch-Job erstellen &Default &Standard &Export file list -E&xportiere Dateiliste +Dateiliste e&xportieren &File &Datei +&Global settings +&Globale Einstellungen &Help &Hilfe &Ignore @@ -53,7 +51,7 @@ E&xportiere Dateiliste &Language &Sprache &Load configuration -&Lade Konfiguration +Konfiguration &laden &OK &OK &Pause @@ -64,12 +62,12 @@ E&xportiere Dateiliste &Beheben &Retry &Wiederholen +&Save +&Speichern &Start &Start -&Synchronize +&Synchronize... &Synchronisieren -(-) filtered out from sync-process\n -(-) nicht synchronisieren\n , . - different @@ -103,7 +101,7 @@ E&xportiere Dateiliste 1. &Compare 1. &Vergleichen 1. Enter full file or directory names separated by ';' or a new line. -1. Komplette Datei- und Verzeichnisnamen getrennt durch ';' oder eine Neuzeile eingeben. +1. Ganze Datei- und Verzeichnisnamen getrennt durch ';' oder eine Neuzeile eingeben. 2. &Synchronize... 2. &Synchronisieren... 2. Use wildcard characters '*' and '?'. @@ -113,7 +111,7 @@ E&xportiere Dateiliste 4. Keep the number of entries small for best performance. 4. Für beste Performance möglichst wenige Einträge filtern. << left file is newer\n -<< linke Datei ist neuer\n +<< Linke Datei ist neuer\n <Directory> <Verzeichnis> <multiple selection> @@ -123,11 +121,9 @@ E&xportiere Dateiliste == files are equal\n\n == Dateien sind gleich\n\n >> right file is newer\n ->> rechte Datei ist neuer\n -A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive. -Eine Verschiebung der Dateiänderungszeiten aufgrund der Sommer-/Winterzeitumstellung wurde auf einem FAT/FAT32 Laufwerk erkannt. +>> Rechte Datei ist neuer\n Abort -Abbruch +Abbrechen Abort requested: Waiting for current operation to finish... Abbruch initiiert: Warte, bis aktuelle Operation beendet ist... Aborted @@ -136,36 +132,32 @@ About Über Action Aktion +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +Nur für FAT/FAT32-Laufwerke aktiv: Dateien mit einem Zeitunterschied von kleiner oder gleich einer Stunde werden als gleich angesehen. Dadurch ist sichergestellt, dass die Sommer-/Winterzeitumstellung korrekt behandelt wird. Add folder pair Verzeichnispaar hinzufügen -Add to exclude filter: -Über Filter ausschließen: -Adjust file times -Dateizeiten ändern -Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article: -Passt die Änderungszeiten aller Dateien im angegebenen Ordner einschließlich Unterordner an. Diese manuelle Änderung kann nötig sein, wenn gegen ein FAT32-Laufwerk synchronisiert und zwischen Sommer- und Winterzeit umgestellt wurde. Für eine Übersicht der Problematik siehe: -All file times have been adjusted successfully! -Alle Dateien wurden erfolgreich angepasst! All items have been synchronized! Alle Elemente wurden synchronisiert! An exception occured! Eine Ausnahme ist aufgetreten! -Apply -Anwenden As a result the files are separated into the following categories: Das Ergebnis ist eine Aufteilung in folgende Kategorien: 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: -Wie der Name bereits sagt, werden zwei Dateien mit gleichem Namen genau dann als gleich angesehen, wenn sie den gleichen Dateiinhalt haben. Diese Einstellung ist eher für Konsistenzprüfungen geeignet als für Backup-Operationen. Aus diesem Grund wird der Zeitpunkt der letzten Änderung der Dateien nicht berücksichtigt.\n\nDer Entscheidungsbaum ist in diesem Fall kleiner: +Wie der Name andeutet, werden zwei Dateien mit gleichem Namen genau dann als gleich angesehen, wenn sie den gleichen Dateiinhalt haben. Diese Einstellung ist eher für Konsistenzprüfungen geeignet als für Backup-Operationen. Aus diesem Grund wird der Zeitpunkt der letzten Änderung der Dateien nicht berücksichtigt.\n\nDer Entscheidungsbaum ist in diesem Fall kleiner: Assemble a batch file with the following settings. To start synchronization in batch mode simply execute this file or schedule it in your operating system's task planner. -Erzeuge eine Batch-Datei mit den folgenden Parametern. Um im Batch-Modus zu synchronisieren, kann diese einfach gestartet oder in den Task-Planer des Betriebssystems eingetragen werden. +Erzeuge eine Batchdatei mit den folgenden Parametern. Um im Batch-Modus zu synchronisieren, kann diese einfach gestartet oder in den Task-Planer des Betriebssystems eingetragen werden. Batch file created successfully! -Batch-Datei wurde erfolgreich erstellt! +Batchdatei wurde erfolgreich erstellt! +Batch job +Batch-Job Big thanks for localizing FreeFileSync goes out to: Vielen Dank für die Lokalisation von FreeFileSync an: Build: Build: +Cancel +Abbrechen Choose to hide filtered files/directories from list -Gefilterte Dateien ein-/ausblenden +Gefilterte Dateien bzw. Verzeichnisse ein-/ausblenden Comma separated list Kommagetrennte Liste Compare both sides @@ -178,8 +170,8 @@ Compare by... Vergleichen nach... Comparing content Vergleiche Dateiinhalt -Comparing content of files \"%x\" -Vergleiche Inhalt der Dateien \"%x\" +Comparing content of files %x +Vergleiche Inhalt der Dateien %x Comparing... Vergleiche... Completed @@ -189,7 +181,7 @@ Konfiguration Configuration loaded! Konfiguration geladen! Configuration overview: -Übersicht der Parameter: +Konfigurationsübersicht: Configuration saved! Konfiguration gespeichert! Configure filter @@ -215,27 +207,29 @@ Von rechts nach links kopieren Copy from right to left overwriting Von rechts nach links kopieren und überschreiben Copy new or updated files to right folder. -Kopiere neue oder aktualisierte Dateien in den rechten Ordner. +Neue oder aktualisierte Dateien vom linken in das rechte Verzeichnis kopieren. Copy to clipboard\tCTRL+C -Kopiere in Zwischenablage\tCTRL+C -Copying file \"%x\" overwriting \"%y\" -Kopiere Datei \"%x\" und überschreibe \"%y\" -Copying file \"%x\" to \"%y\" -Kopiere Datei \"%x\" nach \"%y\" +In die Zwischenablage kopieren\tCTRL+C +Copying file %x overwriting %y +Kopiere Datei %x und überschreibe %y +Copying file %x to %y +Kopiere Datei %x nach %y Could not retrieve file info for: -Fehler beim Lesen der Dateiattribute von: +Dateiattribute konnten nicht gelesen werden: Could not set working directory: -Fehler beim Setzen des Arbeitsverzeichnisses: +Das Arbeitsverzeichnis konnte nicht gesetzt werden: Create a batch job -Erstelle Batch-Job +Batch-Job erstellen Create: Erstellen: -Creating folder \"%x\" -Erstelle Verzeichnis \"%x\" +Creating folder %x +Erstelle Verzeichnis %x Current operation: Aktuelle Operation: Custom Eigene +Customize columns +Spalten anpassen DECISION TREE ENTSCHEIDUNGSBAUM Data remaining: @@ -244,40 +238,36 @@ Data: Daten: Date Datum -Daylight saving time change detected for FAT/FAT32 drive. -Sommer-/Winterzeitumstellung wurde für ein FAT/FAT32 Laufwerk erkannt. Delete files/folders existing on left side only -Lösche Dateien/Ordner, die nur links existieren +Nur links existierende Dateien/Verzeichnisse löschen Delete files/folders existing on right side only -Lösche Dateien/Ordner, die nur rechts existieren +Nur rechts existierende Dateien/Verzeichnisse löschen Delete files\tDEL -Lösche Dateien\tDEL +Dateien löschen\tDEL Delete: Löschen: -Deleting file \"%x\" -Lösche Datei \"%x\" -Deleting folder \"%x\" -Lösche Verzeichnis \"%x\" +Deleting file %x +Lösche Datei %x +Deleting folder %x +Lösche Verzeichnis %x Directories are dependent: Die Verzeichnisse sind voneinander abhängig: Directory does not exist: Das Verzeichnis existiert nicht: Do not show graphical status and error messages but write to a logfile instead -Keine graphischen Status- und Fehlermeldungen anzeigen, sondern eine Logdatei erstellen +Keine graphischen Status- und Fehlermeldungen anzeigen, sondern eine Protokolldatei erstellen Do not show this warning again Diese Warnung nicht mehr anzeigen Do nothing Nichts tun Do you really want to delete the following objects(s)? -Sollen die folgenden Elemente wirklich gelöscht werden? +Sollen folgende Elemente wirklich gelöscht werden? Do you really want to move the following objects(s) to the recycle bin? -Sollen die folgenden Elemente wirklich in den Papierkorb verschoben werden? +Sollen folgende Elemente wirklich in den Papierkorb verschoben werden? Donate with PayPal -Spenden mit PayPal +Mit PayPal spenden Drag && drop Drag && Drop -Drive: -Laufwerk: Email: Email: Error @@ -295,13 +285,17 @@ Fehler beim Löschen der Datei: Error moving to recycle bin: Fehler beim Verschieben in den Papierkorb: Error parsing configuration file: -Fehler beim Auswerten der Konfigurationsdatei: +Fehler beim Lesen der Konfigurationsdatei: Error reading file: Fehler beim Lesen der Datei: +Error reading folder attributes: +Fehler beim Lesen der Verzeichnisattribute: Error traversing directory: Fehler beim Durchsuchen des Verzeichnisses: Error writing file: Fehler beim Schreiben der Datei: +Error writing folder attributes: +Fehler beim Schreiben der Verzeichnisattribute: Error: Source directory does not exist anymore: Fehler: Quellverzeichnis existiert nicht mehr: Example @@ -310,8 +304,14 @@ Exclude Ausschließen Exclude temporarily Temporär ausschließen +Exclude via filter: +Über Filter ausschließen: +FAT32: Handle Daylight Saving Time +FAT32: Sommer-/Winterzeitumstellung berücksichtigen Feedback and suggestions are welcome at: Feedback und Vorschläge sind willkommen unter: +File Manager integration: +Einbinden des Dateimanagers: File already exists. Overwrite? Die Datei existiert bereits. Überschreiben? File content @@ -329,25 +329,25 @@ Dateien gelten als gleich, wenn\n - die Größe\n - Datum und Uhrzeit de Files remaining: Verbliebene Dateien: Files that exist on both sides and have different content -Dateien, die auf beiden Seiten existieren und unterschiedlichen Inhalt haben +Auf beiden Seiten existierende Dateien mit unterschiedlichem Inhalt Files that exist on both sides, have same date but different filesizes -Dateien, die auf beiden Seiten existieren; gleiches Datum aber unterschiedliche Dateigrößen +Auf beiden Seiten existierende Dateien mit gleichem Datum aber verschiedenen Dateigrößen Files that exist on both sides, left one is newer -Dateien, die auf beiden Seiten existieren; linke Datei ist neuer +Auf beiden Seiten existierende Dateien; linke Datei ist neuer Files that exist on both sides, right one is newer -Dateien, die auf beiden Seiten existieren; rechte Datei ist neuer +Auf beiden Seiten existierende Dateien; rechte Datei ist neuer Files/folders remaining: Verbliebene Dateien/Ordner: Files/folders scanned: Eingelesene Dateien/Ordner: Files/folders that exist on left side only -Dateien/Ordner, die nur links existieren +Nur links exisitierende Dateien/Verzeichnisse Files/folders that exist on right side only -Dateien/Ordner, die nur rechts existieren +Nur rechts exisitierende Dateien/Verzeichnisse Filter Filter Filter active: Press again to deactivate -Filter aktiv: Zum Deaktivieren erneut auswählen +Filter aktiviert: Zum Deaktivieren erneut anwählen Filter files Dateien filtern Filter view @@ -357,33 +357,37 @@ Verzeichnispaar FreeFileSync - Folder Comparison and Synchronization FreeFileSync - Verzeichnisvergleich und -synchronisation FreeFileSync Batch Job -FreeFileSync Batchdatei +FreeFileSync Batch-Job FreeFileSync at Sourceforge FreeFileSync auf Sourceforge FreeFileSync batch file FreeFileSync Batchdatei FreeFileSync configuration FreeFileSync Konfiguration +Generating file list... +Erzeuge Dateiliste... +Global settings +Globale Einstellungen Help Hilfe Hide files that are different -Blende unterschiedliche Dateien aus +Ungleiche Dateien ausblenden Hide files that are equal -Blende gleiche Dateien aus +Gleiche Dateien ausblenden Hide files that are newer on left -Blende Dateien aus, die auf beiden Seiten existieren; linke Datei ist neuer +Auf beiden Seiten existierende Dateien ausblenden; linke Datei ist neuer Hide files that are newer on right -Blende Dateien aus, die auf beiden Seiten existieren; rechte Datei ist neuer +Auf beiden Seiten existierende Dateien ausblenden; rechte Datei ist neuer Hide files that exist on left side only -Blende Dateien aus, die nur links existieren +Nur links existierende Dateien ausblenden Hide files that exist on right side only -Blende Dateien aus, die nur rechts existieren +Nur rechts existierende Dateien ausblenden Hide filtered items Gefilterte Elemente ausblenden Hide further error messages during the current process -Weitere Fehlermeldungen während des aktuellen Prozesses ausblenden +Weitere Fehlermeldungen während des laufenden Prozesses ausblenden Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process -Verhindert das Anzeigen von Fehlermeldungen während der Synchronisation:\nSie werden jedoch gesammelt und nach dem Vorgang als Liste angezeigt +Verhindert das Anzeigen von Fehlermeldungen während der Synchronisation:\nSie werden jedoch gesammelt und nach Vorgangsende als Liste angezeigt Hints: Tipps: Homepage: @@ -409,53 +413,57 @@ Info Information Information Information: If you ignore the error or abort a re-compare will be necessary! -Information: Wenn der Fehler nicht behoben wird, muss der Vergleich erneut gestartet werden! +Information: Wenn der Fehler ignoriert oder der Vorgang abgebrochen wird, ist ein neuer Vergleich erforderlich! Initialization of Recycle Bin failed! Die Initialisierung des Papierkorbs ist fehlgeschlagen! 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. :) -Die Papierkorbfunktion steht nicht zur Verfügung!\n\nWahrscheinlich ist das aktuelle Betriebssystem nicht Windows.\nWenn Sie diese Funktion wirklich benötigen, kontaktieren Sie bitte den Autor. :) +Die Papierkorbfunktion steht nicht zur Verfügung!\n\nWahrscheinlich benutzen Sie nicht Microsoft Windows.\nWenn Sie diese Funktion wirklich benötigen, kontaktieren Sie bitte den Autor. :) Left folder: -Linker Ordner: +Linkes Verzeichnis: Legend Legende Load configuration via...\n - this list (press DEL to delete items)\n - drag & drop to this window\n - startup parameter -Lade Konfiguration über...\n - diese Liste (DEL-Taste löscht Einträge)\n - Drag & Drop auf dieses Fenster\n - Startupparameter +Konfiguration laden über...\n - diese Liste (DEL-Taste löscht Einträge)\n - Drag & Drop auf dieses Fenster\n - Startupparameter Load from file... -Lade aus Datei... +Von Datei laden... Log-messages: -Lognachrichten: +Protokollmitteilungen: Mirror ->> -Spiegel ->> +Spiegeln ->> Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. -Spiegel-Backup des linken Ordners erstellen: Der rechte Ordner wird dabei überschrieben und nach der Synchronisation dem linken exakt gleichen. +Spiegelkopie des linken Verzeichnisses erstellen: Das rechte Verzeichnis wird dabei überschrieben und nach der Synchronisation dem linken exakt entsprechen. +Move column down +Spalte nach unten verschieben +Move column up +Spalte nach oben verschieben Not all items were synchronized! Have a look at the list. -Nicht alle Objekte wurden synchronisiert! Siehe die verbliebenen Elemente im Hauptfenster. +Nicht alle Elemente wurden synchronisiert! Siehe verbliebene Elemente im Hauptfenster. Nothing to synchronize according to configuration! -Es gibt nichts zu synchronisieren gemäß aktueller Einstellungen! +Nichts zu synchronisieren gemäß den aktuellen Einstellungen! Number of files and directories that will be created -Anzahl der Dateien und Verzeichnisse, die erstellt werden +Anzahl der zu erstellenden Dateien und Verzeichnisse Number of files and directories that will be deleted -Anzahl der Dateien und Verzeichnisse, die gelöscht werden +Anzahl der zu löschenden Dateien und Verzeichnisse Number of files that will be overwritten -Anzahl der Dateien, die überschrieben werden +Anzahl der zu überschreibenden Dateien +OK +OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. -Bei der Synchronisation werden nur die Dateien/Ordner berücksichtigt, die zu den Filtereinstellungen passen. Der Filter wird dabei auf den kompletten Dateinamen einschließlich Pfadprefix angewandt. +Für die Synchronisation werden nur die Dateien/Verzeichnisse berücksichtigt, die den Filtereinstellungen entsprechen. Der Filter wird dabei auf den kompletten Dateinamen einschließlich Pfadprefix angewandt. Open synchronization dialog Zeige Synchronisationseinstellungen -Open with Explorer\tD-Click -Im Explorer öffnen\tD-Click +Open with File Manager\tD-Click +Mit Dateimanager öffnen\tD-Click Operation aborted! -Aktion abgebrochen! +Vorgang abgebrochen! Operation: Vorgang: Pause Pause Please fill all empty directory fields. Bitte alle leeren Verzeichnisfelder füllen. -Please restart synchronization! -Synchronisation bitte erneut ausführen! Press button to activate filter -Auswählen, um Filter zu aktivieren +Taste drücken, um Filter zu aktivieren Preview Vorschau Published under the GNU General Public License: @@ -469,63 +477,65 @@ Verzeichnispaar entfernen Result Ergebnis Right folder: -Rechter Ordner: +Rechtes Verzeichnis: S&ave configuration -S&peichere Konfiguration +Konfiguration s&peichern Save aborted! Speicherung abgebrochen! Save current configuration to file -Aktuelle Konfiguration in Datei sichern +Aktuelle Konfiguration in Datei speichern Scanning... -Suche Dateien... +Suchvorgang... Scanning: -Lese Datei: +Suchvorgang: Select a folder -Verzeichnis wählen +Verzeichnis auswählen Select variant: Variante auswählen: -Set filter for synchronization -Filter einstellen Show files that are different -Zeige unterschiedliche Dateien +Ungleiche Dateien anzeigen Show files that are equal -Zeige gleiche Dateien +Gleiche Dateien anzeigen Show files that are newer on left -Zeige Dateien, die auf beiden Seiten existieren; linke Datei ist neuer +Auf beiden Seiten existierende Dateien anzeigen; linke Datei ist neuer Show files that are newer on right -Zeige Dateien, die auf beiden Seiten existieren; rechte Datei ist neuer +Auf beiden Seiten existierende Dateien anzeigen; rechte Datei ist neuer Show files that exist on left side only -Zeige Dateien, die nur links existieren +Nur links existierende Dateien anzeigen Show files that exist on right side only -Zeige Dateien, die nur rechts existieren +Nur rechts existierende Dateien anzeigen Silent mode Stiller Modus Size Größe +Sorting file list... +Sortiere Dateiliste... Source code written completely in C++ utilizing: Sourcecode komplett in C++ geschrieben mit Hilfe von: Start Start Start synchronization -Starte die Synchronisation +Synchronisation starten Stop Stop Swap sides -Vertausche Seiten +Seiten vertauschen Synchronization aborted! Synchronisation abgebrochen! -Synchronization completed successfully. -Synchronisation erfolgreich abgeschlossen. +Synchronization completed successfully! +Synchronisation erfolgreich abgeschlossen! Synchronization completed with errors! -Synchronisation abgeschlossen. Es sind Fehler aufgetreten. +Synchronisation mit Fehlern abgeschlossen! +Synchronization filter +Filter für Synchronisation Synchronization settings Synchronisationseinstellungen Synchronization status -Synchronisation: Status +Synchronisationsstatus Synchronize all .doc, .zip and .exe files except everything from folder \"temp\". -Synchronisiere alle .doc, .zip und .exe Dateien mit Ausnahme des Ordners \"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 auf die jeweils andere Seite kopiert. +Beide Seiten gleichzeitig synchronisieren: Neue oder aktualisierte Dateien werden in beide Richtungen kopiert. Synchronizing... Synchronisiere... System out of memory! @@ -534,50 +544,44 @@ The file does not contain a valid configuration: Die Datei enthält keine gültige Konfiguration: The selected file does not exist: Die ausgewählte Datei existiert nicht: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +Diese Befehlszeile wird ausgeführt, wenn ein Doppelklick auf einen Dateinamen erfolgt. %x ist hierbei der Platzhalter für die ausgewählte Datei. 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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. Diese Variante identifiziert zwei gleichnamige Dateien als gleich, wenn sie die gleiche Dateigröße haben UND der Zeitpunkt der letzten Änderung derselbe ist. Dabei wird eine Abweichung von bis zu zwei Sekunden toleriert. So ist sichergestellt, dass eine Synchronisation gegen ein FAT32 Dateisystem korrekt funktioniert. Time elapsed: Vergangene Zeit: -Time shift in seconds -Zeitverschiebung in Sekunden -Time shift: -Zeitverschiebung: Time: Zeit: Total amount of data that will be transferred -Gesamtmenge der Daten, die übertragen werden +Gesamtmenge der zu übertragenden Daten Total time: Gesamtzeit: Two way <-> Beidseitig <-> Unable to create logfile! -Fehler beim Erstellen der Logdatei! +Die Protokolldatei konnte nicht erstellt werden! Unable to initialize Recycle Bin! Der Papierkorb konnte nicht initialisiert werden! -Unresolved errors occured during operation! -Es sind nichtbehobene Fehler aufgetreten! -Update -> Update -> +Aktualisieren -> Update: -Überschreiben: +Aktualisieren: Use Recycle Bin Papierkorb verwenden Use Recycle Bin when deleting or overwriting files during synchronization -Papierkorb für zu löschende oder überschreibende Dateien nutzen +Papierkorb für zu löschende oder zu überschreibende Dateien nutzen Warning Warnung Warning: Synchronization failed for %x item(s): Warnung: Synchronisation fehlgeschlagen für %x Element(e): When \"Compare\" is triggered with this option set the following decision tree is processed: -Nachdem \"Compare\" mit dieser Einstellung gestartet wurde, wird der folgende Entscheidungsbaum abgearbeitet: -You can adjust the file times accordingly to resolve the issue: -Die Dateizeiten können entsprechend angepasst werden, um den Fehler zu beheben: +Wenn \"Compare\" mit dieser Option eingestellt wurde, wird folgender Entscheidungsbaum abgearbeitet: You may try to synchronize remaining items again (WITHOUT having to re-compare)! Verbliebene Elemente können nochmals synchronisiert werden (OHNE dass ein erneuter Vergleich notwendig ist)! different verschieden file exists on both sides -Datei ex. auf beiden Seiten +Datei existiert auf beiden Seiten on one side only nur auf einer Seite |> file on right side only\n diff --git a/Languages/italian.lng b/Languages/italian.lng new file mode 100644 index 00000000..54a84bf9 --- /dev/null +++ b/Languages/italian.lng @@ -0,0 +1,588 @@ + 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 della GNU Compiler Collection\n wxWidgets \t- Open-Source GUI framework\n wxFormBuilder\t- wxWidgets GUI-builder\n CodeBlocks \t- Open-Source IDE + Byte + Byte + GB + GB + MB + MB + PB + PB + TB + TB + kB + kB +!= files are different\n +!= i file sono diversi\n +%x directories +%x directories +%x files, +%x files, +%x of %y rows in view +%x di %y righe visualizzate +%x of 1 row in view +%x di 1 riga visualizzata +&Abort +&Abbandona +&About... +&A proposito di... +&Advanced +&Avanzate +&Back +&Indietro +&Cancel +&Annulla +&Compare +&Compara +&Create batch job +&Crea un job in batch +&Default +&Default +&Export file list +&Esporta la lista dei file +&File +&File +&Global settings +&Preferenze +&Help +&Aiuto +&Ignore +&Ignora +&Language +&Lingua +&Load configuration +&Carica la configurazione +&OK +&OK +&Pause +&Pausa +&Quit +&Esci +&Resolve +&Risolvi +&Retry +&Riprova +&Save +&Salva +&Start +&Avvia +&Synchronize... +&Sincronizzazione... +, +, +- different +- file diversi +- different (same date, different size) +- file diversi (stessa data, diversa dimensione) +- equal +- file identici +- exists left only +- il file esiste solo a sinistra +- exists right only +- il file esiste solo a destra +- left +- a sinistra +- left newer +- file di sinistra più recente +- right +- a destra +- right newer +- file di destra più recente +- same date (different size) +- stessa data (diversa dimensione) +-Open-Source file synchronization- +-Sincronizzazione Open-Source- +. +, +1 directory +1 directory +1 file, +1 file, +1. &Compare +1. &Compara +1. Enter full file or directory names separated by ';' or a new line. +1. Inserisci il nome completo dei file o delle directory separati da ';' o da un 'a capo'. +2. &Synchronize... +2. &Sincronizza... +2. Use wildcard characters '*' and '?'. +2. Sono ammessi i caratteri generici '*' e '?'. +3. Exclude files directly on main grid via context menu. +3. Escludi i file direttamente sul main grid tramite il menu contestuale. +4. Keep the number of entries small for best performance. +4. Riduci il numero di ingressi per migliorare le performances. +<< left file is newer\n +<< il file di sinistra è più recente\n +<Directory> +<Directory> +<multiple selection> +<selezione multipla> +<| file on left side only\n +<| il file esiste solo a sinistra\n +== files are equal\n\n +== i file sono identici\n\n +>> right file is newer\n +>> il file di destra è più recente\n +Abort +Abbandona +Abort requested: Waiting for current operation to finish... +Abbandono richiesto: in attesa della fine dell'operazione in corso... +Aborted +Abbandono riuscito +About +A proposito di +Action +Azioni +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +Attivo solo per drive FAT/FAT32: File con lo stesso nome e con ora di modifica differente per 1 ora o meno sono considerati identici. Cio' garantisce la corretta gestione dell'ora di modifica. +Add folder pair +Aggiungi una coppia di cartelle +All items have been synchronized! +Tutti gli elementi sono stati sincronizzati! +An exception occured! +Si è verificato un problema! +As a result the files are separated into the following categories: +I file risultano infine ripartiti nelle seguenti categorie: +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: +Come suggerisce il nome, due file con lo stesso nome sono considerati come identici se, e solamente se, il loro contenuto è identico. Questa opzione è utile sia per i contrlli di coerenza che per le operazioni di backup. Tuttavia, data e ora vengono ignorate.\n\nAbilitando questa opzione l'albero delle decisioni è semplificato: +Assemble a batch file with the following settings. To start synchronization in batch mode simply execute this file or schedule it in your operating system's task planner. +Creare un file batch con i seguenti parametri. Per lanciare la sincronizzazione in modalità batch, eseguire questo file o schedularlo nelle operazioni pianificate del sistema operativo. +Batch file created successfully! +Creazione batch file riuscita! +Batch job +Batch job +Big thanks for localizing FreeFileSync goes out to: +Per la traduzione di FreeFileSync, un grazie va a: +Build: +Build: +Cancel +Annulla +Choose to hide filtered files/directories from list +Nascondi i files/directories dalla lista +Comma separated list +Lista di elementi separati da virgola +Compare both sides +Compara le due liste +Compare by \"File content\" +Compara per \"Contenuto dei file\" +Compare by \"File size and date\" +Compara per \"Data e dimensione\" +Compare by... +Compara per... +Comparing content +Comparazione contenuto +Comparing content of files %x +Comparazione contenuto del file %x +Comparing... +Comparazione in corso... +Completed +Completato +Configuration +Configurazione +Configuration loaded! +Configurazione caricata! +Configuration overview: +Controllo configurazione: +Configuration saved! +Configurazione salvata! +Configure filter +Configurazione dei filtri +Configure filter... +Configurazione dei filtri... +Configure your own synchronization rules. +Configura le tue regole di sincronizzazione. +Confirm +Conferma +Consider this when setting up synchronization rules: You might want to avoid write access to these directories so that synchronization of both does not interfere. +Da considerare per il settaggio delle regole di sincronizzazione: Per non interferire con la sincronizzazione potrebbe essere utile bloccare l'accesso in scrittura a queste directory. +Continue +Continua +Conversion error: +Errore di conversione: +Copy from left to right +Copia da sinistra a destra +Copy from left to right overwriting +Copia sinistra a destra sovrascrivendo +Copy from right to left +Copia da destra a sinistra +Copy from right to left overwriting +Copia da destra a sinistra sovrascrivendo +Copy new or updated files to right folder. +Copia file nuovi o aggiornati nella cartella di destra. +Copy to clipboard\tCTRL+C +Copia nella clipboard\tCTRL+C +Copying file %x overwriting %y +Copia di %x file sovrascrivendone %y +Copying file %x to %y +Copia di file da %x a %y +Could not retrieve file info for: +Errore durante la lettura degli attributi file per: +Could not set working directory: +Impossibile definire la directory di lavoro: +Create a batch job +Creazione di un job batch +Create: +Crea: +Creating folder %x +Creazione cartella %x +Current operation: +Operazione corrente: +Custom +Personalizza +Customize columns +Personalizza colonne +DECISION TREE +ALBERO DELLE DECISIONI +Data remaining: +Dati rimanenti: +Data: +Dati: +Date +Data +Delete files/folders existing on left side only +Elimina files/cartelle esistenti solo a sinistra +Delete files/folders existing on right side only +Elimina files/cartelle esistenti solo a destra +Delete files\tDEL +Elimina file\tDEL +Delete: +Elimina: +Deleting file %x +Eliminazione file %x +Deleting folder %x +Eliminazione cartella %x +Directories are dependent: +Le directory sono dipendenti: +Directory does not exist: +La directory non esiste: +Do not show graphical status and error messages but write to a logfile instead +Non mostrare lo stato grafico nè i messaggi d'errore ma scrivi un file log +Do not show this warning again +Non mostrare più questo messaggio +Do nothing +Non fare nulla +Do you really want to delete the following objects(s)? +Vuoi veramente eliminare i seguenti oggetti? +Do you really want to move the following objects(s) to the recycle bin? +Vuoi veramente eliminare i seguenti oggetti dal cestino? +Donate with PayPal +Fai una donazione con PayPal +Drag && drop +Drag && drop +Email: +Email: +Error +Errore +Error changing modification time: +Errore durante la modifica della data: +Error copying file: +Errore durante la copia del file: +Error creating directory: +Errore durante la creazione della directory: +Error deleting directory: +Errore durante l'eliminazione delle directory: +Error deleting file: +Errore durante l'eliminazione del file: +Error moving to recycle bin: +Errore durante lo spostamento nel cestino: +Error parsing configuration file: +Errore durante l'analisi del file di configurazione: +Error reading file: +Errore durante la lettura del file: +Error reading folder attributes: +Errore durante la lettura attributi della cartella: +Error traversing directory: +Errore nel percorso della directory: +Error writing file: +Errore durante la scrittura del file: +Error writing folder attributes: +Errore in scrittura attributi della cartella: +Error: Source directory does not exist anymore: +Errore: la directory sorgente non è più esistente: +Example +Esempio +Exclude +Escludi +Exclude temporarily +Escludi temporaneamente +Exclude via filter: +Escludi tramite filtro: +FAT32: Handle Daylight Saving Time +FAT32: Gestisci Ora di Modifica +Feedback and suggestions are welcome at: +Commenti e suggerimenti sono i benvenuti: +File Manager integration: +Integrazione File Manager: +File already exists. Overwrite? +Il file esiste già. Lo vuoi sovrascrivere? +File content +Contenuto del file +File list exported! +Lista dei file esportata! +File size and date +Dimensione e data del file +Filename +Nome del file +Files are found equal if\n - file content\nis the same. +I file sono considerati identici se\n - il contenuto\nè identico. +Files are found equal if\n - filesize\n - last write time and date\nare the same. +I file sono considerati identici se\n - dimensione\n - data e ora sono identici. +Files remaining: +File rimanenti: +Files that exist on both sides and have different content +Files esistenti su entrambi i lati e aventi differente contenuto +Files that exist on both sides, have same date but different filesizes +Files esistenti su entrambi i lati e aventi la stessa data ma dimensioni differenti +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 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 +Files/cartelle esistenti solo a destra +Filter +Filtro +Filter active: Press again to deactivate +Filtro attivo: Clicca nuovamente per disattivare +Filter files +Filtro dei files +Filter view +Filtro della vista +Folder pair +Coppia di cartelle +FreeFileSync - Folder Comparison and Synchronization +FreeFileSync - Comparazione e sincronizzazione di directory +FreeFileSync Batch Job +FreeFileSync Batch Job +FreeFileSync at Sourceforge +FreeFileSync su Sourceforge +FreeFileSync batch file +FreeFileSync batch file +FreeFileSync configuration +FreeFileSync configurazione +Generating file list... +Generazione lista dei file... +Global settings +Preferenze +Help +Aiuto +Hide files that are different +Nascondi i file differenti +Hide files that are equal +Nascondi i file identici +Hide files that are newer on left +Nascondi i file più recenti a sinistra +Hide files that are newer on right +Nascondi i file più recenti a destra +Hide files that exist on left side only +Nascondi i file esistenti solo a sinistra +Hide files that exist on right side only +Nascondi i file esistenti solo a destra +Hide filtered items +Nascondi gli elementi filtrati +Hide further error messages during the current process +Non mostrare i successivi messaggi d'errore durante il processo corrente +Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process +Non mostrare i messaggi d'errore durante la sincronizzazione:\nVerranno raccolti e mostrati alla fine del processo +Hints: +Consigli: +Homepage: +Homepage: +If you like FFS: +Se ti piace FFS: +Ignore errors +Ignora gli errori +Ignore next errors +Ignora gli errori successivi +Ignore this error, retry or abort synchronization? +Ignora questo errore, riprova o abbandona la sincronizzazione? +Ignore this error, retry or abort? +Ignora questo errore, riprova o abbandona? +Include +Includi +Include temporarily +Includi temporaneamente +Include: *.doc;*.zip;*.exe\nExclude: *\\temp\\* +Includi: *.doc;*.zip;*.exe\nEscludi: *\\temp\\* +Info +Info +Information +Informazioni +Information: If you ignore the error or abort a re-compare will be necessary! +Informazioni: Ignorando l'errore o abbandonando, sarà necessario far ripartire la comparazione! +Initialization of Recycle Bin failed! +Inizializzazione del Cestino fallita! +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. :) +Impossibile inizializzare il Cestino!\n\nE'probabile che non si stia utilizzando Windows.\nSe si vuole usare questa funzionalità, contattare l'autore. :) +Left folder: +Cartella di sinistra: +Legend +Legenda +Load configuration via...\n - this list (press DEL to delete items)\n - drag & drop to this window\n - startup parameter +Carica la configurazione da...\n - questa lista (premi DEL per eliminare elementi),\n - trascina e rilascia in questa finestra,\n - i parametri di partenza. +Load from file... +Carica da file... +Log-messages: +Log-messages: +Mirror ->> +Mirror ->> +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Mirror backup della cartella di sinistra: La cartella di destra sarà sovrascritta e resa identica alla cartella di sinistra dopo la sincronizzazione. +Move column down +Sposta colonna giu' +Move column up +Sposta colonna su' +Not all items were synchronized! Have a look at the list. +Alcuni elementi non sono stati sincronizzati! Controllare la lista. +Nothing to synchronize according to configuration! +Niente da sincronizzare in questa configurazione! +Number of files and directories that will be created +Numero di file e cartelle che verranno creati +Number of files and directories that will be deleted +Numero di file e cartelle che verranno eliminati +Number of files that will be overwritten +Numero di file che verranno sovrascritti +OK +OK +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. +Solo i files/cartelle filtrati saranno selezionati per la sincronizzazione. Il filtro verrà applicato al nome completo incluso il percorso. +Open synchronization dialog +Apri la finestra di dialogo della sincronizzazione +Open with File Manager\tD-Click +Apri con File Manager\tD-Click +Operation aborted! +Operazione abortita! +Operation: +Operazione: +Pause +Pausa +Please fill all empty directory fields. +Compilare tutti i campi di directory vuoti. +Press button to activate filter +Cliccare per attivare il filtro +Preview +Anteprima +Published under the GNU General Public License: +Pubblicato sotto licenza GNU General Public: +Quit +Esci +Relative path +Percorso relativo +Remove folder pair +Elimina la coppia di cartelle +Result +Risultato +Right folder: +Cartella Destra: +S&ave configuration +S&alva la configurazione +Save aborted! +Salvataggio abortito! +Save current configuration to file +Salva su file la configurazione corrente +Scanning... +Analisi in corso... +Scanning: +Analisi in corso: +Select a folder +Selezionare una cartella +Select variant: +Selezionare una variante: +Show files that are different +Mostra file differenti +Show files that are equal +Mostra file identici +Show files that are newer on left +Mostra file di sinistra più recenti che a destra +Show files that are newer on right +Mostra file di destra più recenti che a sinistra +Show files that exist on left side only +Mostra file esistenti solo a sinistra +Show files that exist on right side only +Mostra file esistenti solo a destra +Silent mode +Modalità Silenziosa +Size +Dimensione +Sorting file list... +Ordinamento lista file... +Source code written completely in C++ utilizing: +Codice sorgente scritto completamente in C++ \ne utilizzando: +Start +Avvia +Start synchronization +Avvia sincronizzazione +Stop +Stop +Swap sides +Inverti i lati +Synchronization aborted! +Sincronizzazione abortita! +Synchronization completed successfully! +Sincronizzazione completata con successo! +Synchronization completed with errors! +Sincronizzazione terminata con errori! +Synchronization filter +Filtro di sincronizzazione +Synchronization settings +Parametri di sincronizzazione +Synchronization status +Stato della sincronizzazione +Synchronize all .doc, .zip and .exe files except everything from folder \"temp\". +Sincronizza tutti i file .doc, .zip e .exe eccetto la 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. +Synchronizing... +Sincronizzazione in corso... +System out of memory! +Memoria di sistema esaurita! +The file does not contain a valid configuration: +Il file non contiene una configurazione valida +The selected file does not exist: +Il file selezionato non esiste: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +Questa commandline verrà eseguita ad ogni doppio click sul nome di un file. %x é lo spazio riservato per il file selezionato. +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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. +Questa variante definisce identici due file con lo stesso nome quando hanno la stessa dimensione E la stessa data e ora. Attenzione: la precisione dell'ora è di circa 2 secondi. Ciò assicura il corretto funzionamneto della sincronizzazione con la precisione del file system FAT32. +Time elapsed: +Tempo trascorso: +Time: +Ora: +Total amount of data that will be transferred +Volume dei dati che verranno trasferiti +Total time: +Tempo totale: +Two way <-> +Dai 2 lati <-> +Unable to create logfile! +Impossibile creaer il file di log! +Unable to initialize Recycle Bin! +Impossibile inizializzare il Cestino! +Update -> +Aggiorna -> +Update: +Aggiorna: +Use Recycle Bin +Usa il Cestino +Use Recycle Bin when deleting or overwriting files during synchronization +Usa il Cestino quando si cancella o sovrascrivono file durante la sincronizzazione +Warning +Attenzione +Warning: Synchronization failed for %x item(s): +Attenzione: Sincronizzazione fallita per %x elementi: +When \"Compare\" is triggered with this option set the following decision tree is processed: +Quando \"Compara\" è usato con questa opzione, viene eseguito il seguente albero delle decisioni: +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 +file differenti +file exists on both sides +il file esiste su entrambi i lati +on one side only +il file esiste su un solo lato +|> file on right side only\n +|> Il file esiste solo sul lato destro\n diff --git a/japanese.lng b/Languages/japanese.lng index 9146cdab..ede371f5 100644 --- a/japanese.lng +++ b/Languages/japanese.lng @@ -26,8 +26,6 @@ 情報(&A) &About... 情報(&A)... -&Adjust file times -ファイル時間の調整(&A) &Advanced 拡張(&A) &Back @@ -36,8 +34,6 @@ キャンセル(&C) &Compare 比較(&C) -&Create -作成(&C) &Create batch job 一括ジョブを作成(&C) &Default @@ -46,6 +42,8 @@ ファイル一覧をエクスポート(&E) &File ファイル(&F) +&Global settings +全般的な設定(&G) &Help ヘルプ(&H) &Ignore @@ -64,12 +62,12 @@ 決定(&R) &Retry 再試行(&R) +&Save +保存(&S) &Start 開始(&S) -&Synchronize -同期(&S) -(-) filtered out from sync-process\n -(-) 同期処理対象から除外\n +&Synchronize... +同期(&S)... , . - different @@ -119,13 +117,11 @@ <multiple selection> <複数選択> <| file on left side only\n -<| 左側のみに存在するファイル\n +<| 左側のみに存在\n == files are equal\n\n == 同じ内容のファイル\n\n >> right file is newer\n >> 右側の方が新しい\n -A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive. -FAT/FAT32 ドライブにおいて、夏時間の変更に伴う時間のシフトが検出されました。 Abort 中断 Abort requested: Waiting for current operation to finish... @@ -136,22 +132,14 @@ About 情報 Action 操作 +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +FAT/FAT32 ドライブのみ有効: ファイルの時間を比較するとき、差異が 1 時間未満より少ないか同等かで判断します。これにより、夏時間の切り替えが適切に行われるようになります。 Add folder pair フォルダのペアを追加 -Add to exclude filter: -除外フィルターを追加 -Adjust file times -ファイル時間の調整 -Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article: -指定したフォルダとそのサブフォルダに存在する、すべてのファイルの更新時間を調整します。\nFAT32ドライブを同期に使用している場合は、\nここで最適化しておく必要があるかもしれません(夏時間は切り替えられます)\n\n この機能に関する詳細については、こちらをご覧ください: -All file times have been adjusted successfully! -ファイルの時間調整が完了しました! All items have been synchronized! すべてのアイテムは同期されました! An exception occured! 例外が発生しました! -Apply -適用 As a result the files are separated into the following categories: ファイルは以下のカテゴリに分類されます: As the name suggests, two files which share the same name are marked as equal if and only if they have the same content. This option is useful for consistency checks rather than backup operations. Therefore the file times are not taken into account at all.\n\nWith this option enabled the decision tree is smaller: @@ -160,10 +148,14 @@ Assemble a batch file with the following settings. To start synchronization in b 以下の設定で一括処理(バッチ)ファイルを作成します。使用方法は、そのままファイルを実行するか、OS のタスクスケジューラを利用して実行することもできます。 Batch file created successfully! バッチファイルが作成されました! +Batch job +一括処理 Big thanks for localizing FreeFileSync goes out to: FreeFileSync のローカライズへの協力に感謝します: Build: ビルド: +Cancel +中止 Choose to hide filtered files/directories from list リストから除外したいファイル/ディレクトリを選択 Comma separated list @@ -178,8 +170,8 @@ Compare by... 比較対象... Comparing content 内容の比較中 -Comparing content of files \"%x\" -ファイル \"%x\" の内容を比較中 +Comparing content of files %x +ファイル %x の内容を比較中 Comparing... 比較中... Completed @@ -218,10 +210,10 @@ Copy new or updated files to right folder. 新しい(更新)ファイルを右フォルダにコピー Copy to clipboard\tCTRL+C クリップボードにコピー\tCTRL+C -Copying file \"%x\" overwriting \"%y\" -ファイル \"%x\" をコピー、\"%y\" に上書き中 -Copying file \"%x\" to \"%y\" -ファイル \"%x\" を \"%y\" にコピー中 +Copying file %x overwriting %y +ファイル %x をコピー、%y に上書き中 +Copying file %x to %y +ファイル %x を %y にコピー中 Could not retrieve file info for: ファイル情報を取得できません: Could not set working directory: @@ -230,12 +222,14 @@ Create a batch job 一括ジョブを作成 Create: 作成: -Creating folder \"%x\" -フォルダ \"%x\" を作成中 +Creating folder %x +フォルダ %x を作成中 Current operation: 現在の操作: Custom カスタム +Customize columns +列の調整 DECISION TREE [判定ツリー] Data remaining: @@ -244,8 +238,6 @@ Data: データ: Date データ -Daylight saving time change detected for FAT/FAT32 drive. -FAT/FAT32 ドライブで検出された夏時間の変更 Delete files/folders existing on left side only 左側のみに存在するファイル/フォルダを削除 Delete files/folders existing on right side only @@ -254,10 +246,10 @@ Delete files\tDEL ファイルを削除\tDEL Delete: 削除: -Deleting file \"%x\" -ファイル \"%x\" を削除中 -Deleting folder \"%x\" -フォルダ \"%x\" を削除中 +Deleting file %x +ファイル %x を削除中 +Deleting folder %x +フォルダ %x を削除中 Directories are dependent: ディレクトリの依存関係: Directory does not exist: @@ -276,8 +268,6 @@ Donate with PayPal PayPal から寄付する Drag && drop ドラッグ && ドロップ -Drive: -ドライブ: Email: E-メール: Error @@ -310,8 +300,14 @@ Exclude 除外 Exclude temporarily 一時フォルダを除外 +Exclude via filter: +フィルターを通して除外 +FAT32: Handle Daylight Saving Time +FAT32: 夏時間の取り扱いを有効 Feedback and suggestions are welcome at: フィードバック、提案など: +File Manager integration: +ファイラとの統合: File already exists. Overwrite? ファイルは存在します、上書きしますか? File content @@ -364,6 +360,10 @@ FreeFileSync batch file FreeFileSync バッチファイル FreeFileSync configuration FreeFileSync 構成設定 +Generating file list... +ファイル一覧を作成中... +Global settings +全般的な設定 Help ヘルプ Hide files that are different @@ -428,6 +428,10 @@ Mirror ->> ミラー >> Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. 左側フォルダをミラーリングバックアップ: 同期完了後は、左側フォルダに合わせて右側フォルダは上書きされます。 +Move column down +列を下に移動 +Move column up +列を上に移動 Not all items were synchronized! Have a look at the list. すべてのアイテムは同期されていません! 詳細はリストをご覧ください。 Nothing to synchronize according to configuration! @@ -438,12 +442,14 @@ Number of files and directories that will be deleted 削除されたファイルとディレクトリ数 Number of files that will be overwritten 上書きされたファイル数 +OK +OK Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. 選択されたファイル/ディレクトリを同期処理する時だけフィルタリングされます。\nこのフィルターは、接頭語を含むパスと完全な名前にのみ適用されます。 Open synchronization dialog 同期ダイアログを開く -Open with Explorer\tD-Click -エクスプローラで開く\tD-Click +Open with File Manager\tD-Click +ファイラーから開く\tD-クリック Operation aborted! 操作の中断! Operation: @@ -452,8 +458,6 @@ Pause 一時停止 Please fill all empty directory fields. アイテムが選択されていません! -Please restart synchronization! -同期処理を再スタートしてください! Press button to activate filter ボタンをクリックで有効化 Preview @@ -484,8 +488,6 @@ Select a folder フォルダを選択 Select variant: 変数を選択: -Set filter for synchronization -同期フィルターを設定 Show files that are different 差異のあるファイルを表示 Show files that are equal @@ -502,6 +504,8 @@ Silent mode サイレントモード Size サイズ +Sorting file list... +一覧のソート中... Source code written completely in C++ utilizing: ソースコードは C++ で書かれ、コンパイルされています: Start @@ -514,10 +518,12 @@ Swap sides パネルを入れ替え Synchronization aborted! 同期処理を中断! -Synchronization completed successfully. -同期処理はすべて正常に完了しました。 +Synchronization completed successfully! +同期処理はすべて正常に完了しました! Synchronization completed with errors! 同期処理は、エラーで終了しています! +Synchronization filter +同期フィルター Synchronization settings 同期処理設定 Synchronization status @@ -534,14 +540,12 @@ The file does not contain a valid configuration: このファイルには有効な構成が含まれていません: The selected file does not exist: 選択されたファイルは存在しません: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +ファイル名をダブルクリックする度に、このコマンドが実行されます。%x は選択ファイルのプレースフォルダとして機能します。 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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. この変数では、ふたつの同名ファイルが存在した場合、 それぞれのファイルサイズと最終更新日付/時間を比較します。\nファイル時間の差異が 2 秒以内の場合は検出されないということに注意してください。 (これは、FAT32システムで正確に同期を行うことができる最小値です) Time elapsed: 経過時間: -Time shift in seconds -タイムシフト(秒) -Time shift: -タイムシフト: Time: 時間: Total amount of data that will be transferred @@ -554,8 +558,6 @@ Unable to create logfile! ログファイルを作成出来ません! Unable to initialize Recycle Bin! ゴミ箱の初期化が出来ません! -Unresolved errors occured during operation! -例外エラーが発生しました! Update -> 更新 -> Update: @@ -570,8 +572,6 @@ Warning: Synchronization failed for %x item(s): 警告: %x アイテムの同期に失敗しました: When \"Compare\" is triggered with this option set the following decision tree is processed: この設定で \"比較\" トリガが実行された場合は、以下のツリーに従って処理されていきます。 -You can adjust the file times accordingly to resolve the issue: -この問題を解決するために、ファイルの時間を調整できます: You may try to synchronize remaining items again (WITHOUT having to re-compare)! 残っているファイルは、再び同期することができます (再比較とは別の動作)! different @@ -581,4 +581,4 @@ file exists on both sides on one side only 片側のみ |> file on right side only\n -|> 右側のみに存在するファイル\n +|> 右側のみに存在\n diff --git a/Languages/polish.lng b/Languages/polish.lng new file mode 100644 index 00000000..803b7a48 --- /dev/null +++ b/Languages/polish.lng @@ -0,0 +1,584 @@ + 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 + Bajt + GB + GB + MB + MB + PB + PB + TB + TB + kB + kB +!= files are different\n +!= pliki są różne\n +%x directories +%x katalogi +%x files, +%x pliki, +%x of %y rows in view +%x z %y wierszy w widoku +%x of 1 row in view +%x z 1 wiersza w widoku +&Abort +&Przerwij +&About... +&O Programie... +&Advanced +&Zaawansowane +&Back +&Cofnij +&Cancel +&Anuluj +&Compare +&Porównaj +&Create batch job +&Twórz zadanie batch +&Default +&Domyślne +&Export file list +&Eksportuj listę plików +&File +&Plik +&Global settings +&Ustawienia globalne +&Help +&Pomoc +&Ignore +&Ignoruj +&Language +&Język +&Load configuration +&Ładuj konfigurację +&OK +&OK +&Pause +&Pauza +&Quit +&Zamnkij +&Resolve +&Rozwiąż +&Retry +&Powtórz +&Save +&Zapisz +&Start +&Start +&Synchronize... +&Synchronizuj... +, +. +- different +- różny +- different (same date, different size) +- różnica (jednakowa data, różny rozmiar) +- equal +- równy +- exists left only +- istnieje tylko po lewej stronie +- exists right only +- istnieje tylko po prawej stronie +- left +- lewy +- left newer +- lewy jest nowszy +- right +- prawy +- right newer +- prawy jest nowszy +- same date (different size) +- jednakowa data (różny rozmiar) +-Open-Source file synchronization- +-synchronizacja plików Open-Source- +. +, +1 directory +1 katalog +1 file, +1 plik, +1. &Compare +1. &Porównaj +1. Enter full file or directory names separated by ';' or a new line. +1. Wprowadź pełne ścieżki do plików lub katalogów oddzielone ';' albo nową linią. +2. &Synchronize... +2. &Synchronizuj... +2. Use wildcard characters '*' and '?'. +2. Użyj wieloznacznika (wildcard) '*' i '?'. +3. Exclude files directly on main grid via context menu. +3. Wyklucz pliki i foldery urzywając prawego przycisku myszki. +4. Keep the number of entries small for best performance. +4. Przechowuj małą listę wpisów dla lepszej wydajności. +<< left file is newer\n +<< lewy plik jest nowszy\n +<Directory> +<Katalog> +<multiple selection> +<zaznaczone elementy> +<| file on left side only\n +<| istnieje tylko po lewej stronie\n +== files are equal\n\n +== pliki są równe\n\n +>> right file is newer\n +>> prawy plik jest nowszy\n +Abort +Przerwij +Abort requested: Waiting for current operation to finish... +Rządanie przerwania: Czekaj na koniec aktualnie wykonywanego zadania... +Aborted +Przerwana +About +O Programie +Action +Akcja +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +Aktywne dla dysków FAT/FAT32: pliki, których czasy modyfikacji różnią się nie więcej niż godzinę, zostaną potraktowane jako równe. Zapewnia to poprawną synchronizację po zmianie czasu letniego. +Add folder pair +Dodaj foldery do porównania +All items have been synchronized! +Wszystkie elementy zsynchronizowane! +An exception occured! +Wystąpił wyjątek! +As a result the files are separated into the following categories: +W rezultacie pliki zostały podzielone na następujące kategorie: +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: +Jak wskazuje nazwa, dwa pliki o tej samej nazwie są równe tylko i wyłącznie jeżeli ich zawartość jest jednakowa. Czas modyfikacji nie jest brany pod uwagę. Ta opcja jest raczej użyteczna do sprawdzania spójności plików niż zadań kopii zapasowej.\n\nDrzewko decyzyjne dla tej opcji jest mniejsze: +Assemble a batch file with the following settings. To start synchronization in batch mode simply execute this file or schedule it in your operating system's task planner. +Utwórz zadanie batch z tymi ustawieniami. Aby rozpocząć synchronizację w tym trybie zwyczajnie uruchom plik lub dodaj go do zadań zaplanowanych Twojego systemu. +Batch file created successfully! +Plik Batch utworzony pomyślnie! +Batch job +Zadanie batch +Big thanks for localizing FreeFileSync goes out to: +Podziękowania za tłumaczenia FreeFileSync: +Build: +Buduj: +Cancel +Anuluj +Choose to hide filtered files/directories from list +Zaznacz aby ukryć przefiltrowane pliki/katalogi z listy +Comma separated list +Lista oddzielona przecinkami +Compare both sides +Porównaj foldery +Compare by \"File content\" +Porównaj przez \"Zawartość pliku\" +Compare by \"File size and date\" +Porównaj przez \"Rozmiar i data pliku\" +Compare by... +Porównaj przez... +Comparing content +Porównuję zawartość +Comparing content of files %x +Porównywanie zawartości plików %x +Comparing... +Porównuje... +Completed +Zakończono +Configuration +Konfiguracja +Configuration loaded! +Konfiguracja załadowana! +Configuration overview: +Przegląd konfiguracji: +Configuration saved! +Konfiguracja zapisana! +Configure filter +Konfiguruj filtr +Configure filter... +Konfiguruj filtr... +Configure your own synchronization rules. +Skonfiguruj swoje własne zasady synchronizacji. +Confirm +Potwierdź +Consider this when setting up synchronization rules: You might want to avoid write access to these directories so that synchronization of both does not interfere. +Pamiętaj: Możesz zastrzec prawo do zapisu dla tych katalogów aby uniknąć ewentualej kolizji podczas synchronizacji. +Continue +Kontynuuj +Conversion error: +Błąd konwersji: +Copy from left to right +Kopiuj z lewej do prawej +Copy from left to right overwriting +Kopiuj z lewej do prawej nadpisując +Copy from right to left +Kopiuj z prawej do lewej +Copy from right to left overwriting +Kopij z prawej do lewej nadpisując +Copy new or updated files to right folder. +Kopiuj nowe lub aktualniejsze pliki na prawą stronę. +Copy to clipboard\tCTRL+C +Kopiuj do pamięci\tCTRL+C +Copying file %x overwriting %y +Kopiowanie pliku %x nadpisywanie %y +Copying file %x to %y +Kopiowanie pliku %x do %y +Could not retrieve file info for: +Nie można uzyskać informacji o pliku dla: +Could not set working directory: +Nie można ustawić poprawnego folderu: +Create a batch job +Twórz zadanie Batch +Create: +Utwórz: +Creating folder %x +Tworzenie foldery %x +Current operation: +Aktualna operacja: +Custom +Własne +Customize columns +Dostosuj kolumny +DECISION TREE +DRZEWO DECYZYJNE +Data remaining: +Pozostałe dane: +Data: +Dane: +Date +Data +Delete files/folders existing on left side only +Usuń pliki/foldery istniejące tylko po lewej stronie +Delete files/folders existing on right side only +Usuń pliki/foldery istniejące tylko po prawej stronie +Delete files\tDEL +Usuń\tDEL +Delete: +Usuń: +Deleting file %x +Usuwanie pliku %x +Deleting folder %x +Usuwanie folderu %x +Directories are dependent: +Katalogi są zależne: +Directory does not exist: +Katalog nie istnieje: +Do not show graphical status and error messages but write to a logfile instead +Nie pokazuj statusu graficznego oraz informacji o błędach ale zapisz je w logach +Do not show this warning again +Nie pokazuj tego ostrzeżenia ponownie +Do nothing +Nic nie rób +Do you really want to delete the following objects(s)? +Czy na pewno chcesz usunąć wybrane obiekty? +Do you really want to move the following objects(s) to the recycle bin? +Czy na pewno chesz przenieść wybrane obiekty do kosza? +Donate with PayPal +Wesprzyj z PayPal +Drag && drop +Drag && Drop +Email: +Email: +Error +Błąd +Error changing modification time: +Błąd zmiany godziny modyfikacji: +Error copying file: +Błąd podczas kopiowania pliku: +Error creating directory: +Błąd podczas tworzenia katalogu: +Error deleting directory: +Błąd podczas usuwania katalogu: +Error deleting file: +Błąd podczas usuwania pliku: +Error moving to recycle bin: +Błąd podczas przenoszenia do kosza: +Error parsing configuration file: +Błąd podczas parsowania pliku konfiguracyjnego: +Error reading file: +Błąd podczas odczytu pliku: +Error traversing directory: +Błąd podczas odczytywania katalogu: +Error writing file: +Błąd podczas zapisu do pliku: +Error: Source directory does not exist anymore: +Błąd: Katalog źródłowy nie istnieje: +Example +Przykład +Exclude +Wyklucz +Exclude temporarily +Wyklucz tymczasowo +Exclude via filter: +Dodaj filtr: +FAT32: Handle Daylight Saving Time +FAT32: Uwzględnij przesunięcie czasu +Feedback and suggestions are welcome at: +Komentarze i sugestie mile widziane na: +File Manager integration: +Menadżer plików: +File already exists. Overwrite? +Nadpisać istniejący już plik? +File content +Zawartość pliku +File list exported! +Lista plików wyeksportowana! +File size and date +Rozmiar i data pliku +Filename +Nazwa pliku +Files are found equal if\n - file content\nis the same. +Pliki są jednakowe jeżeli\n - zawartość pliku\njest identyczna. +Files are found equal if\n - filesize\n - last write time and date\nare the same. +Pliki są jednakowe jeżeli\n - rozmiar pliku\n - czas i data modyfikacji\nsą identyczne. +Files remaining: +Pozostałe pliki: +Files that exist on both sides and have different content +Pliki, które istnieją po obu stronach i różnią się zawartością +Files that exist on both sides, have same date but different filesizes +Pliki, które istnieją po obu stronach, mają tą samą datę ale inny rozmiar +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 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 +Pliki/katalogi istniejące tylko po prawej stronie +Filter +Filtr +Filter active: Press again to deactivate +Filtr aktywny: Kliknij ponownie aby wyłączyć +Filter files +Filtruj pliki +Filter view +Filtr podglądu +Folder pair +Para folderów +FreeFileSync - Folder Comparison and Synchronization +FreeFileSync - Porównywanie i Synchronizacja folderów +FreeFileSync Batch Job +FreeFileSync Batch +FreeFileSync at Sourceforge +FreeFileSync na Sourceforge +FreeFileSync batch file +FreeFileSync plik batch +FreeFileSync configuration +Konfiguracja FreeFileSync +Generating file list... +Generowanie listy plików... +Global settings +Ustawienia globalne +Help +Pomoc +Hide files that are different +Ukryj pliki, które są różne +Hide files that are equal +Ukryj pliki, które są równe +Hide files that are newer on left +Ukryj pliki, które są nowsze po lewej stronie +Hide files that are newer on right +Ukryj pliki, które są nowsze po prawej stronie +Hide files that exist on left side only +Ukryj pliki, które istnieją tylko po lewej stronie +Hide files that exist on right side only +Ukryj pliki, które istnieją tylko po prawej stronie +Hide filtered items +Ukryj elementy przefiltrowane +Hide further error messages during the current process +Ukryj kolejne informacje o błędach dla tego zadania +Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process +Ukryj informacje o błędach podczas synchronizacji:\nZostaną wyświetlone pod koniec procesu +Hints: +Wskazówki: +Homepage: +Strona domowa: +If you like FFS: +Jeżeli Ci się podoba: +Ignore errors +Ignoruj błędy +Ignore next errors +Ignoruj kolejne błędy +Ignore this error, retry or abort synchronization? +Ignoruj, powtórz albo przerwij synchronizacje. +Ignore this error, retry or abort? +Ignorować błąd, powtórzć albo zakończyć? +Include +Dołącz +Include temporarily +Dołącz tymczasowo +Include: *.doc;*.zip;*.exe\nExclude: *\\temp\\* +Dołącz: *.doc;*.zip;*.exe\nWyklucz: *\\temp\\* +Info +Info +Information +Informacja +Information: If you ignore the error or abort a re-compare will be necessary! +Informacja: Jeśli zignorujesz błąd albo zakończysz konieczne będzie ponowne porównanie! +Initialization of Recycle Bin failed! +Niepowodzenie inicjalizacji Kosza! +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. :) +Inicjalizacja Kosza nie była możliwa!\n\nPrawdopodobnie nie używasz Windowsa.\nJeżeli chcesz dołączyć tą cechę, skontaktuj się z autorem. :) +Left folder: +Lewy folder: +Legend +Legenda +Load configuration via...\n - this list (press DEL to delete items)\n - drag & drop to this window\n - startup parameter +Ładuj konfigurację przez...\n - ta lista (DEL aby usunąć element)\n - przeciągnij i upuść na to okno\n - parametry startowe +Load from file... +Ładuj z pliku... +Log-messages: +Logi: +Mirror ->> +Lustrzana ->> +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Kopia lustrzana lewego folderu: Prawy folder będzie nadpisany zawartością lewego folderu. +Move column down +Przesuń kolumnę w dół +Move column up +Przesuń kolumnę do góry +Not all items were synchronized! Have a look at the list. +Nie wszysktkie elementy zostały zsynchronizowane! Lista pominiętych plików. +Nothing to synchronize according to configuration! +Brak elementów do synchronizacji! +Number of files and directories that will be created +Liczba plików i katalogów, które zostaną utworzone +Number of files and directories that will be deleted +Liczba plików i katalogów, które zostaną usunięte +Number of files that will be overwritten +Liczba plików, które zostaną nadpisane +OK +OK +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. +Tylko pliki/katalogi, które nie zostaną odrzucone przez filtr zostaną zsynchronizowane. Filtr jest stosowany tylko dla pełnej nazwy pliku. +Open synchronization dialog +Przejdź do ustawień zaawansowanych synchronizacji +Open with File Manager\tD-Click +Exploruj +Operation aborted! +Operacja przerwana! +Operation: +Operacja: +Pause +Pauza +Please fill all empty directory fields. +Podaj foldery do synchronizacji. +Press button to activate filter +Kliknij aby aktywować filtr +Preview +Podgląd +Published under the GNU General Public License: +Udostępnione na zasadach licencji GNU General Public License: +Quit +Zakończ +Relative path +Relatywna ścieżka +Remove folder pair +Usuń parę folderów +Result +Rezultat +Right folder: +Prawy folder: +S&ave configuration +Z&apisz konfigurację +Save aborted! +Speicherung abgebrochen! +Save current configuration to file +Zapisz aktualny plik konfiguracyjny +Scanning... +Skanowanie... +Scanning: +Skanowanie: +Select a folder +Wybierz folder +Select variant: +Wybierz wariant: +Show files that are different +Pokaż pliki, które się różnią +Show files that are equal +Pokaż pliki, ktore są równe +Show files that are newer on left +Pokaż pliki nowsze po lewej stronie +Show files that are newer on right +Pokaż pliki nowsze po prawej stronie +Show files that exist on left side only +Pokaż pliki istniejące tylko po lewej stronie +Show files that exist on right side only +Pokaż pliki istniejące tylko po prawej stronie +Silent mode +Tryb Cichy +Size +Rozmiar +Sorting file list... +Sortowanie listy plików... +Source code written completely in C++ utilizing: +Kod źródłowy napisany całkowicie w C++ z wykorzystaniem: +Start +Rozpocznij +Start synchronization +Rozpocznij synchronizację +Stop +Zatrzymaj +Swap sides +Zamień stronami +Synchronization aborted! +Synchronizacja przerwana! +Synchronization completed successfully! +Synchronizacja zakończona pomyślnie! +Synchronization completed with errors! +Synchronizacja zakończona z błędami. +Synchronization filter +Filtr synchronizacji +Synchronization settings +Ustawienia synchronizacji +Synchronization status +Status synchronizacji +Synchronize all .doc, .zip and .exe files except everything from folder \"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. +Synchronizing... +Synchronizuje... +System out of memory! +Brak pamięci! +The file does not contain a valid configuration: +Nieprawidłowy format pliku: +The selected file does not exist: +Zaznaczony plik nie istnieje: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +Ta linia będzie wykonywana za każdym razem jak będziesz eksplorował plik. %x jest wskaźnikiem na katalog zaznaczonego pliku. +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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. +Ten wariant traktuje dwa pliki jako równe w przypadku gdy mają jednakowy rozmiar oraz tą samą datę i czas ostatniej modyfikacji. Miej na uwadzę, że czas pliku może odbiegać od rzeczywistego o 2 sekundy. Jest to konieczne podczas synchronizacji dla plików w systemie FAT32. +Time elapsed: +Czas: +Time: +Czas: +Total amount of data that will be transferred +Liczba danych do przekopiowania +Total time: +Całkowity czas: +Two way <-> +Obustronna <-> +Unable to create logfile! +Nie można utworzyć pliku z logami! +Unable to initialize Recycle Bin! +Nie można zainicjalizować Kosz! +Update -> +Uaktualnij -> +Update: +Uaktualnij: +Use Recycle Bin +Użyj kosza +Use Recycle Bin when deleting or overwriting files during synchronization +Użyj Kosza podczas usuwania bądź nadpisywania plików w trakcie synchronizacji +Warning +Uwaga +Warning: Synchronization failed for %x item(s): +Uwaga: Błąd synchronizacji dla \"%x\" elementów: +When \"Compare\" is triggered with this option set the following decision tree is processed: +Gdy \"Porównywanie\" z zaznaczoną opcją jest w toku, podejmowane są następujące dezycje: +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 +różny +file exists on both sides +plik istnieje po obu stronach +on one side only +tylko po jednej stronie +|> file on right side only\n +|> istnieje tylko po prawej stronie\n diff --git a/Languages/portuguese.lng b/Languages/portuguese.lng new file mode 100644 index 00000000..818ef2f7 --- /dev/null +++ b/Languages/portuguese.lng @@ -0,0 +1,588 @@ + 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 + Byte + GB + GB + MB + MB + PB + PB + TB + TB + kB + kB +!= files are different\n +!= ficheiros diferentes\n +%x directories +%x pastas +%x files, +%x ficheiros, +%x of %y rows in view +%x de %y ficheiros +%x of 1 row in view +%x de 1 linha +&Abort +&Abortar +&About... +&Sobre... +&Advanced +&Avançado +&Back +&Atrás +&Cancel +&Cancelar +&Compare +&Comparar +&Create batch job +&Criar um ficheiro batch +&Default +&Config. Iniciais +&Export file list +&Exportar lista de ficheiros +&File +&Ficheiro +&Global settings +&Opções... +&Help +&Ajuda +&Ignore +&Ignorar +&Language +&Língua +&Load configuration +&Carregar configuração +&OK +&OK +&Pause +&Pausa +&Quit +&Sair +&Resolve +&Resolve +&Retry +&Tentar de Novo +&Save +&Guardar +&Start +&Arrancar +&Synchronize... +&Sincronizar... +, + +- different +- ficheiros diferentes +- different (same date, different size) +- ficheiros diferentes (mesma data, tamanho diferente) +- equal +- ficheiros iguais +- exists left only +- existe apenas à esquerda +- exists right only +- existe apenas à direita +- left +- esquerda +- left newer +- mais novo à esquerda +- right +- direita +- right newer +- mais novo à direita +- same date (different size) +- mesma data (tamanho diferente) +-Open-Source file synchronization- +-Sincronização de ficheiros Open-Source- +. +, +1 directory +1 pastas +1 file, +1 ficheiro, +1. &Compare +1. &Comparar +1. Enter full file or directory names separated by ';' or a new line. +1. Introduzir nome completo dos ficheiros ou pastas separados por ';' ou uma nova linha. +2. &Synchronize... +2. &Sincronizar... +2. Use wildcard characters '*' and '?'. +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. +4. Keep the number of entries small for best performance. +4. Manter um número baixo de entradas para melhor performance. +<< left file is newer\n +<< ficheiro à esquerda mais recente\n +<Directory> +<Directório> +<multiple selection> +<Selecção Múltipla> +<| file on left side only\n +<| ficheiro apenas à esquerda\n +== files are equal\n\n +== ficheiros iguais\n\n +>> right file is newer\n +>> ficheiro à direita mais recente\n +Abort +Abortar +Abort requested: Waiting for current operation to finish... +Abortar pedido: À espera do fim da operação... +Aborted +Abortado +About +Sobre +Action +Acção +Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly. +Activo apenas para drives FAT/FAT32: ao comparar as datas de ficheiros, tratar como iguais ficheiros com diferença de 1 hora ou menos. Esta opção assegura que as mudanças de Hora de Verão são tratadas correctamente. +Add folder pair +Adicionar um par de pastas +All items have been synchronized! +Todos os itens sincronizados! +An exception occured! +Ocorreu uma excepção! +As a result the files are separated into the following categories: +Como resultado, os ficheiros foram separados nas seguintes categorias: +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: +Como o nome sugere, dois ficheiros com o mesmo nome são assinalados iguais se e só se o seu conteúdo for idêntico. Esta opção é útil para controles de consistência mais do que para efeitos de backup. Portanto, a data dos ficheiros não é tomada em conta.\n\nCom esta opção, a arvoré de decisão é menor: +Assemble a batch file with the following settings. To start synchronization in batch mode simply execute this file or schedule it in your operating system's task planner. +Criar um ficheiro batch com as seguintes opções. Para iniciar a sincronização no modo batch, execute o ficheiro ou junte-o ao programador de tarefas do sistema operativo. +Batch file created successfully! +Ficheiro batch criado com sucesso! +Batch job +Ficheiro Batch +Big thanks for localizing FreeFileSync goes out to: +Pela tradução de FreeFileSync, um agradecimento a: +Build: +Criado: +Cancel +Cancelar +Choose to hide filtered files/directories from list +Ocultar itens filtrados da lista +Comma separated list +Lista de itens separados por virgula +Compare both sides +Comparar listas +Compare by \"File content\" +Comparar por \"Conteúdo dos ficheiros\" +Compare by \"File size and date\" +Comparar por \"Data e tamanho dos ficheiros\" +Compare by... +Comparar por... +Comparing content +A comparar conteúdo +Comparing content of files %x +A comparar o conteúdo do ficheiro %x +Comparing... +A comparar... +Completed +Terminado +Configuration +Configuração +Configuration loaded! +Configuração carregada! +Configuration overview: +Parâmetros de configuração: +Configuration saved! +Configuração guardada! +Configure filter +Configuração dos filtros +Configure filter... +Configurar filtros... +Configure your own synchronization rules. +Configure as suas regras de sincronização. +Confirm +Confirmar +Consider this when setting up synchronization rules: You might want to avoid write access to these directories so that synchronization of both does not interfere. +A considerar ao escolher as regras de sincronização: Pode querer evitar escrever sobre estas pastas para que a sincronização ocorra sem problemas. +Continue +Continuar +Conversion error: +Erro de conversão: +Copy from left to right +Copiar da esquerda para a direita +Copy from left to right overwriting +Copiar da esquerda para a direita com sobreposição +Copy from right to left +Copiar da direita para a esquerda +Copy from right to left overwriting +Copiar da direita para a esquerda com sobreposição +Copy new or updated files to right folder. +Copiar ficheiros novos ou actualizados para a direita +Copy to clipboard\tCTRL+C +Copiar para a Área de transferência\tCTRL+C +Copying file %x overwriting %y +Copiar ficheiro %x substituindo %y +Copying file %x to %y +Copiar ficheiro %x para %y +Could not retrieve file info for: +Não pode obter informação do ficheiro: +Could not set working directory: +Não pode definir pasta de trabalho: +Create a batch job +Criar ficheiro batch +Create: +Criar: +Creating folder %x +Criar pasta %x +Current operation: +Operação actual: +Custom +Personalizado +Customize columns +Personalizar colunas +DECISION TREE +ÁRVORE DE DECISÃO +Data remaining: +Dados em falta: +Data: +Dados: +Date +Data +Delete files/folders existing on left side only +Eliminar itens existentes apenas no lado esquerdo +Delete files/folders existing on right side only +Eliminar itens existentes apenas no lado direito +Delete files\tDEL +Eliminar ficheiros\tDEL +Delete: +Eliminar: +Deleting file %x +Apagar ficheiro %x +Deleting folder %x +Apagar pasta %x +Directories are dependent: +As pastas são dependentes: +Directory does not exist: +A pasta não existe: +Do not show graphical status and error messages but write to a logfile instead +Escrever para um ficheiro log em vez de mostrar status ou mensagens de erro +Do not show this warning again +Não voltar a mostrar este aviso +Do nothing +Não fazer nada +Do you really want to delete the following objects(s)? +Quer mesmo eliminar o(s) seguinte(s) item(s) ? +Do you really want to move the following objects(s) to the recycle bin? +Quer mesmo enviar o(s) seguinte(s) item(s) para a Reciclagem? +Donate with PayPal +Doar usando PayPal +Drag && drop +Pegar && largar +Email: +Email: +Error +Erro +Error changing modification time: +Erro ao mudar a hora de modificação: +Error copying file: +Erro ao copiar ficheiro: +Error creating directory: +Erro ao criar a pasta: +Error deleting directory: +Erro ao eliminar a pasta: +Error deleting file: +Erro ao eliminar o ficheiro: +Error moving to recycle bin: +Erro ao mover para a Reciclagem: +Error parsing configuration file: +Erro de leitura do ficheiro de configuração: +Error reading file: +Erro de leitura de ficheiro: +Error reading folder attributes: +Erro de leitura de atributos de pasta: +Error traversing directory: +Erro ao percorrer a pasta: +Error writing file: +Erro de escrita no ficheiro: +Error writing folder attributes: +Erro de escrita de atributos de pasta: +Error: Source directory does not exist anymore: +Erro: A pasta de origem já não existe: +Example +Exemplo +Exclude +Excluir +Exclude temporarily +Excluir temporariamente +Exclude via filter: +Excluir por filtro: +FAT32: Handle Daylight Saving Time +FAT32: Tratar Hora de Verão +Feedback and suggestions are welcome at: +Comentários e sugestões são benvindos em: +File Manager integration: +Integração c/ Gestor de Ficheiros: +File already exists. Overwrite? +O ficheiro já existe. Deseja substituir? +File content +Conteúdo do ficheiro +File list exported! +Lista dos ficheiros exportada! +File size and date +Data e tamanho do ficheiro +Filename +Nome do ficheiro +Files are found equal if\n - file content\nis the same. +Os ficheiros são considerados iguais se\n - o conteúdo é o mesmo. +Files are found equal if\n - filesize\n - last write time and date\nare the same. +Os ficheiros são considerados iguais se\n - o tamanho\n - data e hora são iguais. +Files remaining: +Ficheiros restantes: +Files that exist on both sides and have different content +Ficheiros existentes dos dois lados e com conteúdo diferente +Files that exist on both sides, have same date but different filesizes +Ficheiros existentes dos dois lados com a mesma data, mas tamnhos diferentes +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 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 +Ficheiros/pastas existentes somente à direita +Filter +Filtro +Filter active: Press again to deactivate +Filtro activo: Clique aqui para desactivar +Filter files +Filtrar ficheiros +Filter view +Filtrar vista +Folder pair +Par de pastas +FreeFileSync - Folder Comparison and Synchronization +FreeFileSync - Comparação e Sincronização de pastas +FreeFileSync Batch Job +FreeFileSync Ficheiro batch +FreeFileSync at Sourceforge +FreeFileSync na Sourceforge +FreeFileSync batch file +FreeFileSync Ficheiro batch +FreeFileSync configuration +FreeFileSync configuração +Generating file list... +A gerar lista ficheiros... +Global settings +Opções +Help +Ajuda +Hide files that are different +Ocultar ficheiros diferentes +Hide files that are equal +Ocultar ficheiros iguais +Hide files that are newer on left +Ocultar ficheiros mais recentes à esquerda +Hide files that are newer on right +Ocultar ficheiros mais recentes à direita +Hide files that exist on left side only +Ocultar ficheiros existentes somente à esquerda +Hide files that exist on right side only +Ocultar ficheiros existentes somente à direita +Hide filtered items +Ocultar itens filtrados +Hide further error messages during the current process +Ocultar próximas mensagens de erro durante este processo +Hides error messages during synchronization:\nThey are collected and shown as a list at the end of the process +Ocultar mensagens de erro durante a sincronização:\nSerão coleccionadas e mostradas numa lista no fim do processo +Hints: +Dicas: +Homepage: +Homepage: +If you like FFS: +SE gosta de FFS: +Ignore errors +Ignorar erros +Ignore next errors +Ignorar erros seguintes +Ignore this error, retry or abort synchronization? +Ignorar erro, tentar de novo ou abortar a sincronização? +Ignore this error, retry or abort? +Ignorar erro, tentar de novo ou abortar? +Include +Incluir +Include temporarily +Incluir temporariamente +Include: *.doc;*.zip;*.exe\nExclude: *\\temp\\* +Incluir: *.doc;*.zip;*.exe\nExcluir: *\\temp\\* +Info +Info +Information +Informação +Information: If you ignore the error or abort a re-compare will be necessary! +Informação: Se ignorar o erro ou abortar, será necessário voltar a comparar! +Initialization of Recycle Bin failed! +Início da Reciclagem falhou! +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ão é possível aceder à Reciclagem!\n\nÉ possível que não esteja a utilizar Windows.\nSe desejar esta opção incluída, é favor contactar o autor. :) +Left folder: +Pasta esquerda: +Legend +Legenda +Load configuration via...\n - this list (press DEL to delete items)\n - drag & drop to this window\n - startup parameter +Carregar configuração via...\n - esta lista (pressione DEL para apagar itens),\n - pegar & largar para esta janela,\n - parâmetros de arranque. +Load from file... +Carregar a partir de ficheiro... +Log-messages: +Log de mensagens: +Mirror ->> +Espelhar ->> +Mirror backup of left folder: Right folder will be overwritten and exactly match left folder after synchronization. +Espelhar pasta da esquerda: A pasta da direita vai ser sobreposta e uma cópia exacta da pasta esquerda após sincronização. +Move column down +Mover coluna para baixo +Move column up +Mover coluna para cima +Not all items were synchronized! Have a look at the list. +Nem todos os itens foram sincronizados! Por favor, verifique a lista. +Nothing to synchronize according to configuration! +Nada a sincronizar de acordo com a configuração! +Number of files and directories that will be created +Número de itens a ser criados +Number of files and directories that will be deleted +Número de itens a ser eliminados +Number of files that will be overwritten +Número de ficheiros substituidos +OK +OK +Only files/directories that pass filtering will be selected for synchronization. The filter will be applied to the full name including path prefix. +Apenas ficheiros/pastas que passem a filtragem serão seleccionados para sincronização. O filtro será aplicado ao nome completo, incluindo o caminho. +Open synchronization dialog +Abrir diálogo de sincronização +Open with File Manager\tD-Click +Abrir c/ Gestor de Ficheiros\tD-Click +Operation aborted! +Operação abortada! +Operation: +Operação: +Pause +Pausa +Please fill all empty directory fields. +Por favor, preencha todos os campos vazios. +Press button to activate filter +Pressione para activar o filtro +Preview +Pré-visualizar +Published under the GNU General Public License: +Publicado sobre GNU General Public License: +Quit +Sair +Relative path +Caminho +Remove folder pair +Remover o par de pastas +Result +Resultado +Right folder: +Pasta da direita: +S&ave configuration +G&uardar a configuração +Save aborted! +Guardar abortado! +Save current configuration to file +Guardar o corrente ficheiro de configuração +Scanning... +A pesquisar... +Scanning: +A pesquisar: +Select a folder +Seleccione uma pasta +Select variant: +Sleccione uma variante: +Show files that are different +Mostrar ficheiros diferentes +Show files that are equal +Mostrar ficheiros iguais +Show files that are newer on left +Mostrar ficheiros mais recentes à esquerda +Show files that are newer on right +Mostrar ficheiros mais recentes à direita +Show files that exist on left side only +Mostrar ficheiros existentes somente à esquerda +Show files that exist on right side only +Mostrar ficheiros existentes somente à direita +Silent mode +Modo silencioso +Size +Tamanho +Sorting file list... +Ordenar lista de ficheiros... +Source code written completely in C++ utilizing: +Código fonte todo escrito em C++ utilizando: +Start +Iniciar +Start synchronization +Iniciar a sincronização +Stop +Parar +Swap sides +Trocar lados +Synchronization aborted! +Sincronização abortada! +Synchronization completed successfully! +Sincronização completa com sucesso! +Synchronization completed with errors! +Sincronização completa com erros! +Synchronization filter +Filtro sincronização +Synchronization settings +Parâmetros de sincronização +Synchronization status +Estado da sincronização +Synchronize all .doc, .zip and .exe files except everything from folder \"temp\". +Sincronizar todos os ficheiros .doc, .zip and .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. +Synchronizing... +A sincronizar... +System out of memory! +Sistema sem memória! +The file does not contain a valid configuration: +O ficheiro não contém uma configuração válida: +The selected file does not exist: +O ficheiro seleccionado não existe: +This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file. +Esta linha de comandos será executada cada vez que fizer duplo click num ficheiro. %x serve para reservar o lugar do ficheiro seleccionado. +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. Notice that the file time is allowed to deviate by up to 2 seconds. This ensures synchronization with the lower-precision file system FAT32 works correctly. +Esta variante avalia dois ficheiros de nome igual como iguais quando têm o mesmo tamanho e a mesma data e hora de modificação. Atenção: É permitido um desvio de 2 segundos na hora, de maneira a assegurar a sincronização com sistema de ficheiros de baixa precisão FAT32. +Time elapsed: +Tempo passado: +Time: +Hora: +Total amount of data that will be transferred +Volume de dados a ser transferido +Total time: +Tempo total: +Two way <-> +2 sentidos <-> +Unable to create logfile! +Não é possível criar ficheiro log! +Unable to initialize Recycle Bin! +Não é possível iniciar a Reciclagem! +Update -> +Actualizar -> +Update: +Actualizar: +Use Recycle Bin +Utilizar Reciclagem +Use Recycle Bin when deleting or overwriting files during synchronization +Utilizar a Reciclagem ao eliminar ou substituir ficheiros durante a sincronização +Warning +Atenção +Warning: Synchronization failed for %x item(s): +Atenção: A sincronização falhou para %x item(s): +When \"Compare\" is triggered with this option set the following decision tree is processed: +Quando \"Compare\" é iniciado com esta opção, é executada a seguinte árvore de decisão: +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 +ficheiros diferentes +file exists on both sides +ficheiro existente em ambos os lados +on one side only +ficheiro existente apenas num lado +|> file on right side only\n +|> ficheiro apenas à direita\n @@ -3,6 +3,9 @@ ENDFLAGS=`wx-config --libs` -lwx_gtk2_aui-2.8 -O3 -pthread all: FreeFileSync +init: + mkdir obj + obj/algorithm.o: algorithm.cpp g++ $(CPPFLAGS) algorithm.cpp -o obj/algorithm.o @@ -65,9 +68,12 @@ obj/processXml.o: library/processXml.cpp obj/zstring.o: library/zstring.cpp g++ $(CPPFLAGS) library/zstring.cpp -o obj/zstring.o + +obj/customButton.o: library/customButton.cpp + g++ $(CPPFLAGS) library/customButton.cpp -o obj/customButton.o - FreeFileSync: obj/application.o obj/algorithm.o obj/comparison.o obj/synchronization.o obj/globalFunctions.o obj/guiGenerated.o obj/mainDialog.o obj/syncDialog.o obj/customGrid.o obj/fileHandling.o obj/resources.o obj/smallDialogs.o obj/multithreading.o obj/statusHandler.o obj/misc.o obj/tinyxml.o obj/tinystr.o obj/tinyxmlerror.o obj/tinyxmlparser.o obj/processXml.o obj/zstring.o - g++ $(ENDFLAGS) -o FreeFileSync obj/application.o obj/algorithm.o obj/comparison.o obj/synchronization.o obj/globalFunctions.o obj/guiGenerated.o obj/mainDialog.o obj/syncDialog.o obj/customGrid.o obj/fileHandling.o obj/resources.o obj/smallDialogs.o obj/multithreading.o obj/statusHandler.o obj/misc.o obj/tinyxml.o obj/tinystr.o obj/tinyxmlerror.o obj/tinyxmlparser.o obj/processXml.o obj/zstring.o +FreeFileSync: init obj/application.o obj/algorithm.o obj/comparison.o obj/customButton.o obj/synchronization.o obj/globalFunctions.o obj/guiGenerated.o obj/mainDialog.o obj/syncDialog.o obj/customGrid.o obj/fileHandling.o obj/resources.o obj/smallDialogs.o obj/multithreading.o obj/statusHandler.o obj/misc.o obj/tinyxml.o obj/tinystr.o obj/tinyxmlerror.o obj/tinyxmlparser.o obj/processXml.o obj/zstring.o + g++ $(ENDFLAGS) -o FreeFileSync obj/application.o obj/algorithm.o obj/comparison.o obj/customButton.o obj/synchronization.o obj/globalFunctions.o obj/guiGenerated.o obj/mainDialog.o obj/syncDialog.o obj/customGrid.o obj/fileHandling.o obj/resources.o obj/smallDialogs.o obj/multithreading.o obj/statusHandler.o obj/misc.o obj/tinyxml.o obj/tinystr.o obj/tinyxmlerror.o obj/tinyxmlparser.o obj/processXml.o obj/zstring.o clean: find obj -type f -exec rm {} \; diff --git a/Makefile_Win_Unicode.cmd b/Makefile_Win.cmd index 04aa61ed..4eb4c97e 100644 --- a/Makefile_Win_Unicode.cmd +++ b/Makefile_Win.cmd @@ -28,7 +28,8 @@ mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I% mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\tinyxml\tinyxmlparser.cpp -o obj\tinyxmlparser.o mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\processXml.cpp -o obj\processXml.o mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\zstring.cpp -o obj\zstring.o +mingw32-g++.exe %parameters% -I%widgets%\include -I%widgets%\contrib\include -I%widgetslib% -c %sources%\library\customButton.cpp -o obj\customButton.o windres.exe -i %sources%\resource.rc -J rc -o obj\resource.res -O coff -I%widgets%\include -I%widgetslib% -mingw32-g++.exe -L%widgets%\lib\gcc_lib -o FreeFileSync.exe obj\application.o obj\algorithm.o obj\comparison.o obj\synchronization.o obj\globalFunctions.o obj\multithreading.o obj\statusHandler.o obj\fileHandling.o obj\misc.o obj\GUI_Generated.o obj\MainDialog.o obj\SyncDialog.o obj\CustomGrid.o obj\Resources.o obj\SmallDialogs.o obj\resource.res obj\tinyxml.o obj\tinystr.o obj\tinyxmlerror.o obj\tinyxmlparser.o obj\processXml.o obj\zstring.o -s -mthreads -lwxmsw28u_adv -lwxmsw28u_core -lwxbase28u -lwxpng -lwxzlib -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 -mwindows +mingw32-g++.exe -L%widgets%\lib\gcc_lib -o FreeFileSync.exe obj\application.o obj\algorithm.o obj\comparison.o obj\synchronization.o obj\globalFunctions.o obj\multithreading.o obj\statusHandler.o obj\fileHandling.o obj\customButton.o obj\misc.o obj\GUI_Generated.o obj\MainDialog.o obj\SyncDialog.o obj\CustomGrid.o obj\Resources.o obj\SmallDialogs.o obj\resource.res obj\tinyxml.o obj\tinystr.o obj\tinyxmlerror.o obj\tinyxmlparser.o obj\processXml.o obj\zstring.o -s -mthreads -lwxmsw28u_adv -lwxmsw28u_core -lwxbase28u -lwxpng -lwxzlib -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 -mwindows pause
\ No newline at end of file @@ -1,4 +1,4 @@ -FreeFileSync v1.14 +FreeFileSync v1.15 ------------------ Usage @@ -34,13 +34,13 @@ Key Features 12. Support for filesizes > 4 GB. 13. Option to move files to Recycle Bin instead of deleting/overwriting them. 14. Automatically ignore directories "\RECYCLER" and "\System Volume Information" when comparing and sync'ing. (Windows only) -15. Localized English, German, French, Dutch, Japanese and Chinese versions available. +15. Localized versions for many languages are available. 16. Delete before copy: Avoid disc space shortages with large sync-operations. 17. Based on wxWidgets framework => Portable to many operating systems. 18. Filter functionality to include/exclude files from synchronization (without re-compare!). 19. Include/exclude specific files from synchronization manually. 20. Create sync jobs via GUI to synchronize automatically (can be scheduled or executed directly). -21. Handle daylight saving time changes on FAT/FAT32 volumes correctly and automatically: No need fr a "ignore +/-1h" option +21. Handle daylight saving time changes on FAT/FAT32 volumes correctly Links diff --git a/Resources.a01 b/Resources.a01 Binary files differdeleted file mode 100644 index 804d3f1f..00000000 --- a/Resources.a01 +++ /dev/null diff --git a/Resources.a02 b/Resources.a02 Binary files differdeleted file mode 100644 index 23b7d209..00000000 --- a/Resources.a02 +++ /dev/null diff --git a/Resources.dat b/Resources.dat Binary files differindex 5dcc9f95..c9df6978 100644 --- a/Resources.dat +++ b/Resources.dat diff --git a/algorithm.cpp b/algorithm.cpp index e608a93b..87f7837f 100644 --- a/algorithm.cpp +++ b/algorithm.cpp @@ -99,19 +99,17 @@ Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname) { //Formatting is needed since functions in FreeFileSync.cpp expect the directory to end with '\' to be able to split the relative names. //Also improves usability. - wxString dirnameTmp = dirname.c_str(); + Zstring dirnameTmp = dirname; dirnameTmp.Trim(true); //remove whitespace characters from right dirnameTmp.Trim(false); //remove whitespace characters from left - if (dirnameTmp.IsEmpty()) //an empty string is interpreted as "\"; this is not desired + if (dirnameTmp.empty()) //an empty string is interpreted as "\"; this is not desired return Zstring(); //let wxWidgets do the directory formatting, e.g. replace '/' with '\' for Windows - wxFileName directory = wxFileName::DirName(dirnameTmp); - wxString result = directory.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); + wxFileName directory = wxFileName::DirName(dirnameTmp.c_str()); - //return Zstring(result.c_str()); - return Zstring(result); + return Zstring(directory.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)); } @@ -148,8 +146,8 @@ void FreeFileSync::adjustModificationTimes(const Zstring& parentDirectory, const if (timeInSeconds == 0) return; - vector<Zstring> fileList; - vector<Zstring> dirList; + std::vector<Zstring> fileList; + std::vector<Zstring> dirList; while (true) //should be executed in own scope so that directory access does not disturb deletion { @@ -180,12 +178,12 @@ void FreeFileSync::adjustModificationTimes(const Zstring& parentDirectory, const { wxFileName file(fileList[j].c_str()); if (!file.GetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(wxString(_("Error changing modification time:")) + wxT(" \"") + fileList[j].c_str() + wxT("\"")); + throw FileError(Zstring(_("Error changing modification time:")) + wxT(" \"") + fileList[j] + wxT("\"")); modTime.Add(wxTimeSpan(0, 0, timeInSeconds, 0)); if (!file.SetTimes(NULL, &modTime, NULL)) //get modification time - throw FileError(wxString(_("Error changing modification time:")) + wxT(" \"") + fileList[j].c_str() + wxT("\"")); + throw FileError(Zstring(_("Error changing modification time:")) + wxT(" \"") + fileList[j] + wxT("\"")); break; } @@ -204,7 +202,7 @@ void FreeFileSync::adjustModificationTimes(const Zstring& parentDirectory, const } -void compoundStringToTable(const Zstring& compoundInput, const defaultChar* delimiter, vector<Zstring>& output) +void compoundStringToTable(const Zstring& compoundInput, const DefaultChar* delimiter, std::vector<Zstring>& output) { output.clear(); Zstring input(compoundInput); @@ -219,12 +217,12 @@ void compoundStringToTable(const Zstring& compoundInput, const defaultChar* deli { if (indexStart != indexEnd) //do not add empty strings { - wxString newEntry = input.substr(indexStart, indexEnd - indexStart); + Zstring newEntry = input.substr(indexStart, indexEnd - indexStart); newEntry.Trim(true); //remove whitespace characters from right newEntry.Trim(false); //remove whitespace characters from left - if (!newEntry.IsEmpty()) + if (!newEntry.empty()) output.push_back(newEntry); } indexStart = indexEnd + 1; @@ -233,23 +231,23 @@ void compoundStringToTable(const Zstring& compoundInput, const defaultChar* deli inline -void mergeVectors(vector<Zstring>& changing, const vector<Zstring>& input) +void mergeVectors(std::vector<Zstring>& changing, const std::vector<Zstring>& input) { - for (vector<Zstring>::const_iterator i = input.begin(); i != input.end(); ++i) + for (std::vector<Zstring>::const_iterator i = input.begin(); i != input.end(); ++i) changing.push_back(*i); } -vector<Zstring> compoundStringToFilter(const Zstring& filterString) +std::vector<Zstring> compoundStringToFilter(const Zstring& filterString) { //delimiters may be ';' or '\n' - vector<Zstring> filterList; - vector<Zstring> filterPreProcessing; + std::vector<Zstring> filterList; + std::vector<Zstring> filterPreProcessing; compoundStringToTable(filterString, wxT(";"), filterPreProcessing); - for (vector<Zstring>::const_iterator i = filterPreProcessing.begin(); i != filterPreProcessing.end(); ++i) + for (std::vector<Zstring>::const_iterator i = filterPreProcessing.begin(); i != filterPreProcessing.end(); ++i) { - vector<Zstring> newEntries; + std::vector<Zstring> newEntries; compoundStringToTable(*i, wxT("\n"), newEntries); mergeVectors(filterList, newEntries); } @@ -279,13 +277,13 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con //load filter into vectors of strings //delimiters may be ';' or '\n' - vector<Zstring> includeList = compoundStringToFilter(includeFilter); - vector<Zstring> excludeList = compoundStringToFilter(excludeFilter); + std::vector<Zstring> includeList = compoundStringToFilter(includeFilter.c_str()); + std::vector<Zstring> excludeList = compoundStringToFilter(excludeFilter.c_str()); //format entries - for (vector<Zstring>::iterator i = includeList.begin(); i != includeList.end(); ++i) + for (std::vector<Zstring>::iterator i = includeList.begin(); i != includeList.end(); ++i) formatFilterString(*i); - for (vector<Zstring>::iterator i = excludeList.begin(); i != excludeList.end(); ++i) + for (std::vector<Zstring>::iterator i = excludeList.begin(); i != excludeList.end(); ++i) formatFilterString(*i); //############################################################## @@ -303,7 +301,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING) { bool includedLeft = false; - for (vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + for (std::vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) if (filenameLeft.Matches(*j)) { includedLeft = true; @@ -320,7 +318,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrRight.objType != FileDescrLine::TYPE_NOTHING) { bool includedRight = false; - for (vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) + for (std::vector<Zstring>::const_iterator j = includeList.begin(); j != includeList.end(); ++j) if (filenameRight.Matches(*j)) { includedRight = true; @@ -338,7 +336,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrLeft.objType != FileDescrLine::TYPE_NOTHING) { bool excluded = false; - for (vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) + for (std::vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) if (filenameLeft.Matches(*j)) { excluded = true; @@ -355,7 +353,7 @@ void FreeFileSync::filterCurrentGridData(FileCompareResult& currentGridData, con if (i->fileDescrRight.objType != FileDescrLine::TYPE_NOTHING) { bool excluded = false; - for (vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) + for (std::vector<Zstring>::const_iterator j = excludeList.begin(); j != excludeList.end(); ++j) if (filenameRight.Matches(*j)) { excluded = true; @@ -383,7 +381,7 @@ void FreeFileSync::removeFilterOnCurrentGridData(FileCompareResult& currentGridD //add(!) all files and subfolder gridlines that are dependent from the directory -void FreeFileSync::addSubElements(set<int>& subElements, const FileCompareResult& grid, const FileCompareLine& relevantRow) +void FreeFileSync::addSubElements(std::set<int>& subElements, const FileCompareResult& grid, const FileCompareLine& relevantRow) { Zstring relevantDirectory; @@ -420,17 +418,17 @@ public: private: FileCompareResult& gridToWrite; - set<int> rowsProcessed; + std::set<int> rowsProcessed; }; -void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const set<int>& rowsToDelete, ErrorHandler* errorHandler, const bool useRecycleBin) throw(AbortThisProcess) +void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const std::set<int>& rowsToDelete, ErrorHandler* errorHandler, const bool useRecycleBin) throw(AbortThisProcess) { //remove deleted rows from grid AlwaysWriteToGrid writeOutput(grid); //ensure that grid is always written to, even if method is exitted via exceptions //remove from hd - for (set<int>::iterator i = rowsToDelete.begin(); i != rowsToDelete.end(); ++i) + for (std::set<int>::iterator i = rowsToDelete.begin(); i != rowsToDelete.end(); ++i) { const FileCompareLine& currentCmpLine = grid[*i]; @@ -452,11 +450,11 @@ void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const set<int>& ro writeOutput.rowProcessedSuccessfully(*i); //retrieve all files and subfolder gridlines that are dependent from this deleted entry - set<int> additionalRowsToDelete; + std::set<int> additionalRowsToDelete; addSubElements(additionalRowsToDelete, grid, grid[*i]); //...and remove them also - for (set<int>::iterator j = additionalRowsToDelete.begin(); j != additionalRowsToDelete.end(); ++j) + for (std::set<int>::iterator j = additionalRowsToDelete.begin(); j != additionalRowsToDelete.end(); ++j) writeOutput.rowProcessedSuccessfully(*j); break; @@ -479,15 +477,6 @@ void FreeFileSync::deleteOnGridAndHD(FileCompareResult& grid, const set<int>& ro } -bool FreeFileSync::sameFileTime(const time_t a, const time_t b) -{ - if (a < b) - return b - a <= FILE_TIME_PRECISION; - else - return a - b <= FILE_TIME_PRECISION; -} - - inline void writeTwoDigitNumber(unsigned int number, wxChar*& position) { @@ -575,30 +564,42 @@ wxString FreeFileSync::utcTimeToLocalString(const time_t utcTime) } +#ifdef FFS_WIN inline -wxString getDriveName(const wxString& directoryName) +Zstring getDriveName(const Zstring& directoryName) //GetVolume() doesn't work under Linux! { - const wxString volumeName = wxFileName(directoryName).GetVolume(); - if (volumeName.IsEmpty()) - return wxEmptyString; + const Zstring volumeName = wxFileName(directoryName.c_str()).GetVolume().c_str(); + if (volumeName.empty()) + return Zstring(); - return volumeName + wxFileName::GetVolumeSeparator() + GlobalResources::FILE_NAME_SEPARATOR; + return volumeName + wxFileName::GetVolumeSeparator().c_str() + GlobalResources::FILE_NAME_SEPARATOR; } +#endif //FFS_WIN #ifdef FFS_WIN -inline -bool isFatDrive(const wxString& directoryName) +bool FreeFileSync::isFatDrive(const Zstring& directoryName) { - const wxString driveName = getDriveName(directoryName); - if (driveName.IsEmpty()) + const Zstring driveName = getDriveName(directoryName); + if (driveName.empty()) return false; - wxChar fileSystem[32] = wxT(""); + wxChar fileSystem[32]; if (!GetVolumeInformation(driveName.c_str(), NULL, 0, NULL, NULL, NULL, fileSystem, 32)) return false; - return wxString(fileSystem).StartsWith(wxT("FAT")); + return Zstring(fileSystem).StartsWith(wxT("FAT")); +} +#endif + + +inline +bool sameFileTime(const time_t a, const time_t b) +{ + if (a < b) + return b - a <= FILE_TIME_PRECISION; + else + return a - b <= FILE_TIME_PRECISION; } @@ -643,6 +644,7 @@ N(M) = */ +#ifdef FFS_WIN unsigned int getThreshold(const unsigned filesWithSameSizeTotal) { if (filesWithSameSizeTotal <= 500) @@ -657,7 +659,7 @@ unsigned int getThreshold(const unsigned filesWithSameSizeTotal) void FreeFileSync::checkForDSTChange(const FileCompareResult& gridData, - const vector<FolderPair>& directoryPairsFormatted, + const std::vector<FolderPair>& directoryPairsFormatted, int& timeShift, wxString& driveName) { driveName.Clear(); @@ -668,7 +670,7 @@ void FreeFileSync::checkForDSTChange(const FileCompareResult& gridData, if (rv == TIME_ZONE_ID_UNKNOWN) return; bool dstActive = rv == TIME_ZONE_ID_DAYLIGHT; - for (vector<FolderPair>::const_iterator i = directoryPairsFormatted.begin(); i != directoryPairsFormatted.end(); ++i) + for (std::vector<FolderPair>::const_iterator i = directoryPairsFormatted.begin(); i != directoryPairsFormatted.end(); ++i) { bool leftDirIsFat = isFatDrive(i->leftDirectory); bool rightDirIsFat = isFatDrive(i->rightDirectory); diff --git a/algorithm.h b/algorithm.h index 7d20e22b..31c7e9ca 100644 --- a/algorithm.h +++ b/algorithm.h @@ -15,14 +15,12 @@ namespace FreeFileSync void adjustModificationTimes(const Zstring& parentDirectory, const int timeInSeconds, ErrorHandler* errorHandler) throw(AbortThisProcess); - void deleteOnGridAndHD(FileCompareResult& grid, const set<int>& rowsToDelete, ErrorHandler* errorHandler, const bool useRecycleBin) throw(AbortThisProcess); - void addSubElements(set<int>& subElements, const FileCompareResult& grid, const FileCompareLine& relevantRow); + void deleteOnGridAndHD(FileCompareResult& grid, const std::set<int>& rowsToDelete, ErrorHandler* errorHandler, const bool useRecycleBin) throw(AbortThisProcess); + void addSubElements(std::set<int>& subElements, const FileCompareResult& grid, const FileCompareLine& relevantRow); void filterCurrentGridData(FileCompareResult& currentGridData, const wxString& includeFilter, const wxString& excludeFilter); void removeFilterOnCurrentGridData(FileCompareResult& currentGridData); - bool sameFileTime(const time_t a, const time_t b); - wxString utcTimeToLocalString(const time_t utcTime); //enhanced binary search template: returns an iterator @@ -37,13 +35,16 @@ namespace FreeFileSync } #ifdef FFS_WIN + bool isFatDrive(const Zstring& directoryName); + //detect if FAT/FAT32 drive needs a +-1h time shift after daylight saving time (DST) switch due to known windows bug: //http://www.codeproject.com/KB/datetime/dstbugs.aspx //NO performance issue: debug build: 50 ms for 200000 files processed in for-loop - void checkForDSTChange(const FileCompareResult& gridData, const vector<FolderPair>& directoryPairsFormatted, int& timeShift, wxString& driveName); + void checkForDSTChange(const FileCompareResult& gridData, const std::vector<FolderPair>& directoryPairsFormatted, int& timeShift, wxString& driveName); #endif //FFS_WIN } + #endif // ALGORITHM_H_INCLUDED diff --git a/comparison.cpp b/comparison.cpp index 6ab8aa69..0ad2e1fb 100644 --- a/comparison.cpp +++ b/comparison.cpp @@ -7,6 +7,7 @@ #include <wx/log.h> #include "library/multithreading.h" #include "algorithm.h" +#include <wx/thread.h> #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -14,12 +15,16 @@ using namespace FreeFileSync; -CompareProcess::CompareProcess(bool lineBreakOnMessages, StatusHandler* handler) : +CompareProcess::CompareProcess(bool lineBreakOnMessages, bool handleDstOnFat32Drives, StatusHandler* handler) : + includeLineBreak(lineBreakOnMessages), + handleDstOnFat32(handleDstOnFat32Drives), statusUpdater(handler), - txtComparingContentOfFiles(_("Comparing content of files \"%x\"")) + txtComparingContentOfFiles(_("Comparing content of files %x")) { - if (lineBreakOnMessages) - optionalLineBreak = wxT("\n"); + if (includeLineBreak) + txtComparingContentOfFiles.Replace(wxT("%x"), wxT("\n\"%x\""), false); + else + txtComparingContentOfFiles.Replace(wxT("%x"), wxT("\"%x\""), false); } @@ -43,25 +48,25 @@ struct MemoryAllocator }; -bool filesHaveSameContent(const wxString& filename1, const wxString& filename2) +bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2) { static MemoryAllocator memory; wxFFile file1(filename1.c_str(), wxT("rb")); if (!file1.IsOpened()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\"")); + throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\"")); wxFFile file2(filename2.c_str(), wxT("rb")); if (!file2.IsOpened()) //NO cleanup necessary for (wxFFile) file1 - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\"")); + throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\"")); do { size_t length1 = file1.Read(memory.buffer1, memory.bufferSize); - if (file1.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\"")); + if (file1.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\"")); size_t length2 = file2.Read(memory.buffer2, memory.bufferSize); - if (file2.Error()) throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\"")); + if (file2.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\"")); if (length1 != length2 || memcmp(memory.buffer1, memory.buffer2, length1) != 0) return false; @@ -82,10 +87,10 @@ public: UpdateWhileComparing() {} ~UpdateWhileComparing() {} - wxString file1; - wxString file2; + Zstring file1; + Zstring file2; bool success; - wxString errorMessage; + Zstring errorMessage; bool result; private: @@ -105,7 +110,7 @@ private: }; -bool filesHaveSameContentMultithreaded(const wxString& filename1, const wxString& filename2, StatusHandler* updateClass) +bool filesHaveSameContentMultithreaded(const Zstring& filename1, const Zstring& filename2, StatusHandler* updateClass) { static UpdateWhileComparing cmpAndUpdate; //single instantiation: thread enters wait phase after each execution @@ -125,11 +130,11 @@ bool filesHaveSameContentMultithreaded(const wxString& filename1, const wxString } -void calcTotalDataForCompare(int& objectsTotal, double& dataTotal, const FileCompareResult& grid, const set<int>& rowsToCompare) +void calcTotalDataForCompare(int& objectsTotal, double& dataTotal, const FileCompareResult& grid, const std::set<int>& rowsToCompare) { dataTotal = 0; - for (set<int>::iterator i = rowsToCompare.begin(); i != rowsToCompare.end(); ++i) + for (std::set<int>::iterator i = rowsToCompare.begin(); i != rowsToCompare.end(); ++i) { const FileCompareLine& gridline = grid[*i]; @@ -152,19 +157,22 @@ void writeText(const wxChar* text, const int length, wxChar*& currentPos) class GetAllFilesFull : public FullDetailFileTraverser { public: - GetAllFilesFull(DirectoryDescrType& output, Zstring dirThatIsSearched, const Zstring& optionalLineBreak, StatusHandler* updateClass) : + GetAllFilesFull(DirectoryDescrType& output, Zstring dirThatIsSearched, const bool includeLineBreak, StatusHandler* updateClass) : m_output(output), directory(dirThatIsSearched), - m_optionalLineBreak(optionalLineBreak), statusUpdater(updateClass) { assert(updateClass); prefixLength = directory.length(); - textScanning = _("Scanning:"); //performance optimization + + if (includeLineBreak) + textScanning = Zstring(_("Scanning:")) + wxT("\n"); //performance optimization + else + textScanning = Zstring(_("Scanning:")) + wxT(" "); //performance optimization } - virtual wxDirTraverseResult GetAllFilesFull::OnFile(const Zstring& fullFileName, const FileInfo& details) + wxDirTraverseResult GetAllFilesFull::OnFile(const Zstring& fullFileName, const FileInfo& details) //virtual impl. { FileDescrLine fileDescr; fileDescr.fullName = fullFileName; @@ -175,15 +183,13 @@ public: fileDescr.objType = FileDescrLine::TYPE_FILE; m_output.push_back(fileDescr); - //assemble status message (performance optimized) = textScanning + wxT(" ") + m_optionalLineBreak + wxT("\"") + fullFileName + wxT("\"") + //assemble status message (performance optimized) = textScanning + wxT("\"") + fullFileName + wxT("\"") const unsigned int statusTextMaxLen = 2000; wxChar statusText[statusTextMaxLen]; wxChar* position = statusText; - if (textScanning.length() + m_optionalLineBreak.length() + fullFileName.length() + 3 < statusTextMaxLen) //leave room for 0 terminating char! + if (textScanning.length() + fullFileName.length() + 2 < statusTextMaxLen) //leave room for 0 terminating char! { writeText(textScanning.c_str(), textScanning.length(), position); - writeText(wxT(" "), 1, position); - writeText(m_optionalLineBreak.c_str(), m_optionalLineBreak.length(), position); writeText(wxT("\""), 1, position); writeText(fullFileName.c_str(), fullFileName.length(), position); writeText(wxT("\""), 1, position); @@ -201,7 +207,7 @@ public: } - virtual wxDirTraverseResult GetAllFilesFull::OnDir(const Zstring& fullDirName) + wxDirTraverseResult GetAllFilesFull::OnDir(const Zstring& fullDirName) //virtual impl. { #ifdef FFS_WIN if ( fullDirName.EndsWith(wxT("\\RECYCLER")) || @@ -218,15 +224,13 @@ public: fileDescr.objType = FileDescrLine::TYPE_DIRECTORY; m_output.push_back(fileDescr); - //assemble status message (performance optimized) = textScanning + wxT(" ") + m_optionalLineBreak + wxT("\"") + fullDirName + wxT("\"") + //assemble status message (performance optimized) = textScanning + wxT("\"") + fullDirName + wxT("\"") const unsigned int statusTextMaxLen = 2000; wxChar statusText[statusTextMaxLen]; wxChar* position = statusText; - if (textScanning.length() + m_optionalLineBreak.length() + fullDirName.length() + 3 < statusTextMaxLen) //leave room for 0 terminating char! + if (textScanning.length() + fullDirName.length() + 2 < statusTextMaxLen) //leave room for 0 terminating char! { writeText(textScanning.c_str(), textScanning.length(), position); - writeText(wxT(" "), 1, position); - writeText(m_optionalLineBreak.c_str(), m_optionalLineBreak.length(), position); writeText(wxT("\""), 1, position); writeText(fullDirName.c_str(), fullDirName.length(), position); writeText(wxT("\""), 1, position); @@ -244,9 +248,9 @@ public: } - virtual wxDirTraverseResult GetAllFilesFull::OnError(const Zstring& errorText) + wxDirTraverseResult GetAllFilesFull::OnError(const Zstring& errorText) //virtual impl. { - wxMessageBox(errorText, _("Error")); + wxMessageBox(errorText.c_str(), _("Error")); return wxDIR_CONTINUE; } @@ -254,24 +258,22 @@ private: DirectoryDescrType& m_output; Zstring directory; int prefixLength; - const Zstring m_optionalLineBreak; - wxString textScanning; + Zstring textScanning; StatusHandler* statusUpdater; }; -void generateFileAndFolderDescriptions(DirectoryDescrType& output, const wxString& directory, const wxString& optionalLineBreak, StatusHandler* updateClass) +void generateFileAndFolderDescriptions(DirectoryDescrType& output, const Zstring& directory, const bool includeLineBreak, StatusHandler* updateClass) { assert (updateClass); output.clear(); //get all files and folders from directory (and subdirectories) + information - const wxString directoryFormatted = FreeFileSync::getFormattedDirectoryName(directory); + const Zstring directoryFormatted = FreeFileSync::getFormattedDirectoryName(directory); + + GetAllFilesFull traverser(output, directoryFormatted, includeLineBreak, updateClass); - //GetAllFilesFull traverser(output, directoryFormatted.c_str(), optionalLineBreak.c_str(), updateClass); - GetAllFilesFull traverser(output, directoryFormatted, optionalLineBreak, updateClass); - //traverseInDetail(directoryFormatted.c_str(), &traverser); traverseInDetail(directoryFormatted, &traverser); } @@ -298,16 +300,16 @@ public: ~DirectoryDescrBuffer() { //clean up - for (set<DescrBufferLine>::iterator i = buffer.begin(); i != buffer.end(); ++i) + for (std::set<DescrBufferLine>::iterator i = buffer.begin(); i != buffer.end(); ++i) delete i->directoryDesc; } - DirectoryDescrType* getDirectoryDescription(const Zstring& directory, const Zstring& optionalLineBreak, StatusHandler* statusUpdater) + DirectoryDescrType* getDirectoryDescription(const Zstring& directory, const bool includeLineBreak, StatusHandler* statusUpdater) { DescrBufferLine bufferEntry; bufferEntry.directoryName = directory; - set<DescrBufferLine>::iterator entryFound; + std::set<DescrBufferLine>::iterator entryFound; if ((entryFound = buffer.find(bufferEntry)) != buffer.end()) { //entry found in buffer; return @@ -321,17 +323,27 @@ public: bufferEntry.directoryDesc->reserve(400000); //reserve space for up to 400000 files to avoid vector reallocations - generateFileAndFolderDescriptions(*bufferEntry.directoryDesc, directory, optionalLineBreak, statusUpdater); //exceptions may be thrown! + generateFileAndFolderDescriptions(*bufferEntry.directoryDesc, directory, includeLineBreak, statusUpdater); //exceptions may be thrown! return bufferEntry.directoryDesc; } } private: - set<DescrBufferLine> buffer; + std::set<DescrBufferLine> buffer; }; -void CompareProcess::startCompareProcess(const vector<FolderPair>& directoryPairsFormatted, +inline +bool sameFileTime(const time_t a, const time_t b, const time_t tolerance) +{ + if (a < b) + return b - a <= tolerance; + else + return a - b <= tolerance; +} + + +void CompareProcess::startCompareProcess(const std::vector<FolderPair>& directoryPairsFormatted, const CompareVariant cmpVar, FileCompareResult& output) throw(AbortThisProcess) { @@ -342,225 +354,318 @@ void CompareProcess::startCompareProcess(const vector<FolderPair>& directoryPair FileCompareResult output_tmp; //write to output not before END of process! try - { //inform about the total amount of data that will be processed from now on - statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects + { + if (cmpVar == CMP_BY_TIME_SIZE) + compareByTimeSize(directoryPairsFormatted, output_tmp); + else if (cmpVar == CMP_BY_CONTENT) + compareByContent(directoryPairsFormatted, output_tmp); + else assert(false); + } + catch (const RuntimeException& theException) + { + wxMessageBox(theException.show(), _("An exception occured!"), wxOK | wxICON_ERROR); + statusUpdater->requestAbortion(); + return; + } + catch (std::bad_alloc& e) + { + wxMessageBox(wxString(_("System out of memory!")) + wxT(" ") + wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); + statusUpdater->requestAbortion(); + return; + } - //do basis scan: only result lines of type FILE_UNDEFINED need to be determined - performBaseComparison(directoryPairsFormatted, output_tmp); + //only if everything was processed correctly output is written to! + output_tmp.swap(output); +} - if (cmpVar == CMP_BY_TIME_SIZE) + +void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryPairsFormatted, FileCompareResult& output) +{ + //inform about the total amount of data that will be processed from now on + statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects + + //buffer accesses to the same directories; useful when multiple folder pairs are used + DirectoryDescrBuffer descriptionBuffer; + + //process one folder pair after each other + unsigned tableSizeOld = 0; + for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) + { + //do basis scan: only result lines of type FILE_UNDEFINED (files that exist on both sides) need to be determined after this call + this->performBaseComparison(*pair, descriptionBuffer, output); + + //add some tolerance if one of the folders is FAT/FAT32 + time_t tolerance = 0; +#ifdef FFS_WIN + if (handleDstOnFat32 && (isFatDrive(pair->leftDirectory) || isFatDrive(pair->leftDirectory))) + tolerance = FILE_TIME_PRECISION + 3600; //tolerate filetime diff <= 1 h to handle daylight saving time issues + else + tolerance = FILE_TIME_PRECISION; +#elif defined FFS_LINUX + tolerance = FILE_TIME_PRECISION; +#endif + //categorize files that exist on both sides + for (FileCompareResult::iterator i = output.begin() + tableSizeOld; i != output.end(); ++i) { - for (FileCompareResult::iterator i = output_tmp.begin(); i != output_tmp.end(); ++i) + if (i->cmpResult == FILE_UNDEFINED) { - if (i->cmpResult == FILE_UNDEFINED) + //last write time may differ by up to 2 seconds (NTFS vs FAT32) + if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw, tolerance)) { - //last write time may differ by up to 2 seconds (NTFS vs FAT32) - if (sameFileTime(i->fileDescrLeft.lastWriteTimeRaw, i->fileDescrRight.lastWriteTimeRaw)) - { - if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) - i->cmpResult = FILE_EQUAL; - else - i->cmpResult = FILE_DIFFERENT; - } + if (i->fileDescrLeft.fileSize == i->fileDescrRight.fileSize) + i->cmpResult = FILE_EQUAL; else - { - if (i->fileDescrLeft.lastWriteTimeRaw < i->fileDescrRight.lastWriteTimeRaw) - i->cmpResult = FILE_RIGHT_NEWER; - else - i->cmpResult = FILE_LEFT_NEWER; - } + i->cmpResult = FILE_DIFFERENT; } - } - } -//################################################################################################################################################ - else if (cmpVar == CMP_BY_CONTENT) - { - set<int> rowsToCompareBytewise; //compare of file content happens AFTER finding corresponding files - //in order to separate into two processes (scanning and comparing) - - //pre-check: files have different content if they have a different filesize - for (FileCompareResult::iterator i = output_tmp.begin(); i != output_tmp.end(); ++i) - { - if (i->cmpResult == FILE_UNDEFINED) + else { - if (i->fileDescrLeft.fileSize != i->fileDescrRight.fileSize) - i->cmpResult = FILE_DIFFERENT; + if (i->fileDescrLeft.lastWriteTimeRaw < i->fileDescrRight.lastWriteTimeRaw) + i->cmpResult = FILE_RIGHT_NEWER; else - rowsToCompareBytewise.insert(i - output_tmp.begin()); + i->cmpResult = FILE_LEFT_NEWER; } } + } - int objectsTotal = 0; - double dataTotal = 0; - calcTotalDataForCompare(objectsTotal, dataTotal, output_tmp, rowsToCompareBytewise); + tableSizeOld = output.size(); + } +} - statusUpdater->initNewProcess(objectsTotal, dataTotal, StatusHandler::PROCESS_COMPARING_CONTENT); - set<int> rowsToDelete; //if errors occur during file access and user skips, these rows need to be deleted from result +void CompareProcess::compareByContent(const std::vector<FolderPair>& directoryPairsFormatted, FileCompareResult& output) +{ + //inform about the total amount of data that will be processed from now on + statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects - //compare files (that have same size) bytewise... - for (set<int>::iterator i = rowsToCompareBytewise.begin(); i != rowsToCompareBytewise.end(); ++i) - { - FileCompareLine& gridline = output_tmp[*i]; + //buffer accesses to the same directories; useful when multiple folder pairs are used + DirectoryDescrBuffer descriptionBuffer; + + //process one folder pair after each other + for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) + { + //do basis scan: only result lines of type FILE_UNDEFINED (files that exist on both sides) need to be determined after this call + this->performBaseComparison(*pair, descriptionBuffer, output); + } + + + std::set<int> rowsToCompareBytewise; //content comparison of file content happens AFTER finding corresponding files + //in order to separate into two processes (scanning and comparing) + + //pre-check: files have different content if they have a different filesize + for (FileCompareResult::iterator i = output.begin(); i != output.end(); ++i) + { + if (i->cmpResult == FILE_UNDEFINED) + { + if (i->fileDescrLeft.fileSize != i->fileDescrRight.fileSize) + i->cmpResult = FILE_DIFFERENT; + else + rowsToCompareBytewise.insert(i - output.begin()); + } + } + + int objectsTotal = 0; + double dataTotal = 0; + calcTotalDataForCompare(objectsTotal, dataTotal, output, rowsToCompareBytewise); - wxString statusText = txtComparingContentOfFiles; - statusText.Replace(wxT("%x"), gridline.fileDescrLeft.relativeName, false); - statusUpdater->updateStatusText(statusText); + statusUpdater->initNewProcess(objectsTotal, dataTotal, StatusHandler::PROCESS_COMPARING_CONTENT); - //check files that exist in left and right model but have different content - while (true) + std::set<int> rowsToDelete; //if errors occur during file access and user skips, these rows need to be deleted from result + + //compare files (that have same size) bytewise... + for (std::set<int>::iterator i = rowsToCompareBytewise.begin(); i != rowsToCompareBytewise.end(); ++i) + { + FileCompareLine& gridline = output[*i]; + + Zstring statusText = txtComparingContentOfFiles; + statusText.Replace(wxT("%x"), gridline.fileDescrLeft.relativeName, false); + statusUpdater->updateStatusText(statusText); + + //check files that exist in left and right model but have different content + while (true) + { + //trigger display refresh + statusUpdater->requestUiRefresh(); + + try + { + if (filesHaveSameContentMultithreaded(gridline.fileDescrLeft.fullName, gridline.fileDescrRight.fullName, statusUpdater)) + gridline.cmpResult = FILE_EQUAL; + else + gridline.cmpResult = FILE_DIFFERENT; + + statusUpdater->updateProcessedData(2, (gridline.fileDescrLeft.fileSize * 2).ToDouble()); + break; + } + catch (FileError& error) + { + ErrorHandler::Response rv = statusUpdater->reportError(error.show()); + if (rv == ErrorHandler::IGNORE_ERROR) { - //trigger display refresh - statusUpdater->requestUiRefresh(); - - try - { - if (filesHaveSameContentMultithreaded(gridline.fileDescrLeft.fullName, gridline.fileDescrRight.fullName, statusUpdater)) - gridline.cmpResult = FILE_EQUAL; - else - gridline.cmpResult = FILE_DIFFERENT; - - statusUpdater->updateProcessedData(2, (gridline.fileDescrLeft.fileSize * 2).ToDouble()); - break; - } - catch (FileError& error) - { - ErrorHandler::Response rv = statusUpdater->reportError(error.show()); - if (rv == ErrorHandler::IGNORE_ERROR) - { - rowsToDelete.insert(*i); - break; - } - else if (rv == ErrorHandler::RETRY) - ; //continue with loop - else - assert (false); - } + rowsToDelete.insert(*i); + break; } + else if (rv == ErrorHandler::RETRY) + ; //continue with loop + else + assert (false); } - - //delete invalid rows that have no valid cmpResult - if (rowsToDelete.size() > 0) - removeRowsFromVector(output_tmp, rowsToDelete); } - else assert(false); } - catch (const RuntimeException& theException) + + //delete invalid rows that have no valid cmpResult + if (rowsToDelete.size() > 0) + removeRowsFromVector(output, rowsToDelete); +} + + +class ThreadSorting : public wxThread +{ +public: + ThreadSorting(DirectoryDescrType* directory) : + wxThread(wxTHREAD_JOINABLE), + m_directory(directory) { - wxMessageBox(theException.show(), _("An exception occured!"), wxOK | wxICON_ERROR); - return; + if (Create() != wxTHREAD_NO_ERROR) + throw RuntimeException(wxString(wxT("Error starting thread for sorting!"))); } - catch (std::bad_alloc& e) + + ~ThreadSorting() {} + + + ExitCode Entry() { - wxMessageBox(wxString(_("System out of memory!")) + wxT(" ") + wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR); - return; + std::sort(m_directory->begin(), m_directory->end()); + return 0; } - //only if everything was processed correctly output is written to! - output_tmp.swap(output); -} +private: + DirectoryDescrType* m_directory; +}; -void CompareProcess::performBaseComparison(const vector<FolderPair>& directoryPairsFormatted, FileCompareResult& output) +void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDescrBuffer& descriptionBuffer, FileCompareResult& output) { - //buffer accesses to the same directories; useful when multiple folder pairs are used - DirectoryDescrBuffer descriptionBuffer; + //PERF_START; + //retrieve sets of files (with description data) + DirectoryDescrType* directoryLeft = descriptionBuffer.getDirectoryDescription(pair.leftDirectory, includeLineBreak, statusUpdater); + DirectoryDescrType* directoryRight = descriptionBuffer.getDirectoryDescription(pair.rightDirectory, includeLineBreak, statusUpdater); - //process one folder pair after each other - for (vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair) + statusUpdater->updateStatusText(_("Generating file list...")); + statusUpdater->forceUiRefresh(); //keep total number of scanned files up to date + //PERF_STOP; + + //we use binary search when comparing the directory structures: so sort() first + if (wxThread::GetCPUCount() >= 2) //do it the multithreaded way: + { + //no synchronization (multithreading) needed here: directoryLeft and directoryRight are disjunct + //reference counting Zstring also shouldn't be an issue, as no strings are deleted during std::sort() + ThreadSorting sortLeft(directoryLeft); + ThreadSorting sortRight(directoryRight); + + sortLeft.Run(); + if (directoryLeft != directoryRight) //attention: might point to the same vector because of buffer! + { + sortRight.Run(); + sortRight.Wait(); + } + sortLeft.Wait(); + } + else //single threaded { - //PERF_START; - //retrieve sets of files (with description data) - DirectoryDescrType* directoryLeft = descriptionBuffer.getDirectoryDescription(pair->leftDirectory, optionalLineBreak, statusUpdater); - DirectoryDescrType* directoryRight = descriptionBuffer.getDirectoryDescription(pair->rightDirectory, optionalLineBreak, statusUpdater); - - statusUpdater->forceUiRefresh(); - //PERF_STOP; - //we use binary search when comparing the directory structures: so sort() first - sort(directoryLeft->begin(), directoryLeft->end()); - sort(directoryRight->begin(), directoryRight->end()); - //PERF_STOP; - FileCompareLine newline; - - //reserve some space to avoid vector reallocations - output.reserve(int(max(directoryLeft->size(), directoryRight->size()) * 1.2)); - - //find files/folders that exist in left file model but not in right model - for (DirectoryDescrType::iterator i = directoryLeft->begin(); i != directoryLeft->end(); ++i) - if (custom_binary_search(directoryRight->begin(), directoryRight->end(), *i) == directoryRight->end()) + std::sort(directoryLeft->begin(), directoryLeft->end()); + + if (directoryLeft != directoryRight) //attention: might point to the same vector because of buffer! + std::sort(directoryRight->begin(), directoryRight->end()); + } + //PERF_STOP; + + //reserve some space to avoid vector reallocations + output.reserve(output.size() + unsigned(std::max(directoryLeft->size(), directoryRight->size()) * 1.2)); + + //begin base comparison + FileCompareLine newline; + DirectoryDescrType::iterator j; + for (DirectoryDescrType::iterator i = directoryLeft->begin(); i != directoryLeft->end(); ++i) + { //find files/folders that exist in left file model but not in right model + if ((j = custom_binary_search(directoryRight->begin(), directoryRight->end(), *i)) == directoryRight->end()) + { + newline.fileDescrLeft = *i; + newline.fileDescrRight = FileDescrLine(); + newline.fileDescrRight.directory = pair.rightDirectory; + newline.cmpResult = FILE_LEFT_SIDE_ONLY; + output.push_back(newline); + } + //find files/folders that exist in left and right file model + else + { + const FileDescrLine::ObjectType typeLeft = i->objType; + const FileDescrLine::ObjectType typeRight = j->objType; + + //files... + if (typeLeft == FileDescrLine::TYPE_FILE && typeRight == FileDescrLine::TYPE_FILE) { + newline.fileDescrLeft = *i; + newline.fileDescrRight = *j; + newline.cmpResult = FILE_UNDEFINED; //not yet determined! + output.push_back(newline); + } + //directories... + else if (typeLeft == FileDescrLine::TYPE_DIRECTORY && typeRight == FileDescrLine::TYPE_DIRECTORY) + { + newline.fileDescrLeft = *i; + newline.fileDescrRight = *j; + newline.cmpResult = FILE_EQUAL; + output.push_back(newline); + } + //if we have a nameclash between a file and a directory: split into two separate rows + else + { + assert (typeLeft != typeRight); + newline.fileDescrLeft = *i; newline.fileDescrRight = FileDescrLine(); - newline.fileDescrRight.directory = pair->rightDirectory; + newline.fileDescrRight.directory = pair.rightDirectory; newline.cmpResult = FILE_LEFT_SIDE_ONLY; output.push_back(newline); - } - for (DirectoryDescrType::iterator j = directoryRight->begin(); j != directoryRight->end(); ++j) - { - DirectoryDescrType::iterator i; - - //find files/folders that exist in right file model but not in left model - if ((i = custom_binary_search(directoryLeft->begin(), directoryLeft->end(), *j)) == directoryLeft->end()) - { newline.fileDescrLeft = FileDescrLine(); - newline.fileDescrLeft.directory = pair->leftDirectory; //directory info is needed when creating new directories + newline.fileDescrLeft.directory = pair.leftDirectory; newline.fileDescrRight = *j; newline.cmpResult = FILE_RIGHT_SIDE_ONLY; output.push_back(newline); } - //find files/folders that exist in left and right file model - else - { //files... - if (i->objType == FileDescrLine::TYPE_FILE && j->objType == FileDescrLine::TYPE_FILE) - { - newline.fileDescrLeft = *i; - newline.fileDescrRight = *j; - newline.cmpResult = FILE_UNDEFINED; //not yet determined! - output.push_back(newline); - } - //directories... - else if (i->objType == FileDescrLine::TYPE_DIRECTORY && j->objType == FileDescrLine::TYPE_DIRECTORY) - { - newline.fileDescrLeft = *i; - newline.fileDescrRight = *j; - newline.cmpResult = FILE_EQUAL; - output.push_back(newline); - } - //if we have a nameclash between a file and a directory: split into two separate rows - else if (i->objType != j->objType) - { - newline.fileDescrLeft = *i; - newline.fileDescrRight = FileDescrLine(); - newline.fileDescrRight.directory = pair->rightDirectory; - newline.cmpResult = FILE_LEFT_SIDE_ONLY; - output.push_back(newline); - - newline.fileDescrLeft = FileDescrLine(); - newline.fileDescrLeft.directory = pair->leftDirectory; - newline.fileDescrRight = *j; - newline.cmpResult = FILE_RIGHT_SIDE_ONLY; - output.push_back(newline); - } - else assert (false); - } } - //PERF_STOP; } + + + for (DirectoryDescrType::iterator j = directoryRight->begin(); j != directoryRight->end(); ++j) + { + //find files/folders that exist in right file model but not in left model + if (custom_binary_search(directoryLeft->begin(), directoryLeft->end(), *j) == directoryLeft->end()) + { + newline.fileDescrLeft = FileDescrLine(); + newline.fileDescrLeft.directory = pair.leftDirectory; //directory info is needed when creating new directories + newline.fileDescrRight = *j; + newline.cmpResult = FILE_RIGHT_SIDE_ONLY; + output.push_back(newline); + } + } + + //PERF_STOP } -bool FreeFileSync::foldersAreValidForComparison(const vector<FolderPair>& folderPairs, wxString& errorMessage) +bool FreeFileSync::foldersAreValidForComparison(const std::vector<FolderPair>& folderPairs, wxString& errorMessage) { errorMessage.Clear(); - for (vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) + for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) { - const wxString leftFolderName = getFormattedDirectoryName(i->leftDirectory); - const wxString rightFolderName = getFormattedDirectoryName(i->rightDirectory); + const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory); + const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory); //check if folder name is empty - if (leftFolderName.IsEmpty() || rightFolderName.IsEmpty()) + if (leftFolderName.empty() || rightFolderName.empty()) { errorMessage = _("Please fill all empty directory fields."); return false; @@ -582,15 +687,15 @@ bool FreeFileSync::foldersAreValidForComparison(const vector<FolderPair>& folder } -bool dependencyExists(const vector<wxString>& folders, const wxString& newFolder, wxString& warningMessage) +bool dependencyExists(const std::vector<Zstring>& folders, const Zstring& newFolder, wxString& warningMessage) { warningMessage.Clear(); - for (vector<wxString>::const_iterator i = folders.begin(); i != folders.end(); ++i) + for (std::vector<Zstring>::const_iterator i = folders.begin(); i != folders.end(); ++i) if (newFolder.StartsWith(*i) || i->StartsWith(newFolder)) { warningMessage = wxString(_("Directories are dependent:")) + - wxT(" \"") + *i + wxT("\"") + wxT(", ") + wxT("\"") + newFolder + wxT("\""); + wxT(" \n\"") + *i + wxT("\"") + wxT(", \n") + wxT("\"") + newFolder + wxT("\""); return true; } @@ -598,15 +703,15 @@ bool dependencyExists(const vector<wxString>& folders, const wxString& newFolder } -bool FreeFileSync::foldersHaveDependencies(const vector<FolderPair>& folderPairs, wxString& warningMessage) +bool FreeFileSync::foldersHaveDependencies(const std::vector<FolderPair>& folderPairs, wxString& warningMessage) { warningMessage.Clear(); - vector<wxString> folders; - for (vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) + std::vector<Zstring> folders; + for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) { - const wxString leftFolderName = getFormattedDirectoryName(i->leftDirectory); - const wxString rightFolderName = getFormattedDirectoryName(i->rightDirectory); + const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory); + const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory); if (dependencyExists(folders, leftFolderName, warningMessage)) return true; diff --git a/comparison.h b/comparison.h index a5705238..bbd93f9a 100644 --- a/comparison.h +++ b/comparison.h @@ -4,31 +4,37 @@ #include "FreeFileSync.h" #include "library/statusHandler.h" +class DirectoryDescrBuffer; namespace FreeFileSync { - bool foldersAreValidForComparison(const vector<FolderPair>& folderPairs, wxString& errorMessage); - bool foldersHaveDependencies(const vector<FolderPair>& folderPairs, wxString& warningMessage); + bool foldersAreValidForComparison(const std::vector<FolderPair>& folderPairs, wxString& errorMessage); + bool foldersHaveDependencies( const std::vector<FolderPair>& folderPairs, wxString& warningMessage); //class handling comparison process class CompareProcess { public: - CompareProcess(bool lineBreakOnMessages, StatusHandler* handler); + CompareProcess(bool lineBreakOnMessages, bool handleDstOnFat32Drives, StatusHandler* handler); - void startCompareProcess(const vector<FolderPair>& directoryPairsFormatted, + void startCompareProcess(const std::vector<FolderPair>& directoryPairsFormatted, const CompareVariant cmpVar, FileCompareResult& output) throw(AbortThisProcess); private: + void compareByTimeSize(const std::vector<FolderPair>& directoryPairsFormatted, FileCompareResult& output); + + void compareByContent(const std::vector<FolderPair>& directoryPairsFormatted, FileCompareResult& output); + //create comparison result table and fill relation except for files existing on both sides - void performBaseComparison(const vector<FolderPair>& directoryPairsFormatted, + void performBaseComparison(const FolderPair& pair, + DirectoryDescrBuffer& descriptionBuffer, FileCompareResult& output); + const bool includeLineBreak; //optional line break for status messages (used by GUI mode only) + const bool handleDstOnFat32; StatusHandler* statusUpdater; - wxString optionalLineBreak; //optional line break for status messages (used by GUI mode only) - - const Zstring txtComparingContentOfFiles; + Zstring txtComparingContentOfFiles; }; } diff --git a/library/CustomGrid.cpp b/library/CustomGrid.cpp index 25ceb537..95300a2b 100644 --- a/library/CustomGrid.cpp +++ b/library/CustomGrid.cpp @@ -3,24 +3,28 @@ #include "resources.h" #include <wx/dc.h> #include "../algorithm.h" +#include "resources.h" + +using namespace xmlAccess; + -const unsigned int MinimumRows = 15; +const unsigned int MIN_ROW_COUNT = 15; //class containing pure grid data: basically the same as wxGridStringTable, but adds cell formatting -class CustomGridTableBase : public wxGridStringTable +class CustomGridTable : public wxGridTableBase { public: - CustomGridTableBase(int numRows, int numCols) : - wxGridStringTable(numRows, numCols), + CustomGridTable() : + wxGridTableBase(), lightBlue(80, 110, 255), lightGrey(212, 208, 200), - gridIdentifier(0), - gridRefUI(0), - gridData(0), - lastNrRows(MinimumRows) {} + gridRefUI(NULL), + gridData(NULL), + lastNrRows(0), + lastNrCols(0) {} - ~CustomGridTableBase() {} + virtual ~CustomGridTable() {} void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData) @@ -30,182 +34,56 @@ public: } - void SetGridIdentifier(int id) - { - gridIdentifier = id; - } - //########################################################################### //grid standard input output methods, redirected directly to gridData to improve performance virtual int GetNumberRows() { if (gridRefUI) - return max(gridRefUI->size(), MinimumRows); + return std::max(gridRefUI->size(), MIN_ROW_COUNT); else - return MinimumRows; //grid is initialized with this number of rows + return 0; //grid is initialized with zero number of rows } - virtual bool IsEmptyCell( int row, int col ) + virtual int GetNumberCols() //virtual used by middle grid! { - return (GetValue(row, col) == wxEmptyString); + return columnPositions.size(); } - wxString evaluateCmpResult(const CompareFilesResult result, const bool selectedForSynchronization) + virtual bool IsEmptyCell( int row, int col ) { - if (selectedForSynchronization) - switch (result) - { - case FILE_LEFT_SIDE_ONLY: - return wxT("<|"); - break; - case FILE_RIGHT_SIDE_ONLY: - return wxT("|>"); - break; - case FILE_RIGHT_NEWER: - return wxT(">>"); - break; - case FILE_LEFT_NEWER: - return wxT("<<"); - break; - case FILE_DIFFERENT: - return wxT("!="); - break; - case FILE_EQUAL: - return wxT("=="); - break; - default: - assert (false); - return wxEmptyString; - } - else return wxT("(-)"); + return (GetValue(row, col) == wxEmptyString); } - virtual wxString GetValue(int row, int col) - { - if (gridRefUI) - { - if (unsigned(row) < gridRefUI->size()) - { - const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]]; - wxString fileSize; //tmp string - - switch (gridIdentifier) - { - case 1: - if (col < 4) - { - if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY) - { - switch (col) - { - case 0: //filename - return wxEmptyString; - case 1: //relative path - return gridLine.fileDescrLeft.relativeName; - case 2: //file size - return _("<Directory>"); - case 3: //date - return wxEmptyString; - } - } - else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE) - { - switch (col) - { - case 0: //filename - return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR); - case 1: //relative path - return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR); - case 2: //file size - return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrLeft.fileSize.ToString()); - case 3: //date - return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw); - } - } - } - else - assert (false); - - break; - - case 2: - if (col < 4) - { - if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY) - { - switch (col) - { - case 0: //filename - return wxEmptyString; - case 1: //relative path - return gridLine.fileDescrRight.relativeName; - case 2: //file size - return _("<Directory>"); - case 3: //date - return wxEmptyString; - } - } - else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE) - { - switch (col) - { - case 0: //filename - return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR); - case 1: //relative path - return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR); - case 2: //file size - return globalFunctions::includeNumberSeparator(fileSize = gridLine.fileDescrRight.fileSize.ToString()); - case 3: //date - return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw); - } - } - } - else - assert (false); - - break; + virtual wxString GetValue(int row, int col) = 0; - case 3: - if (col < 1) - return evaluateCmpResult(gridLine.cmpResult, gridLine.selectedForSynchronization); - else - assert (false); - break; - default: - assert (false); - break; - } - } - } - //if data is not found: - return wxEmptyString; - } - - - virtual void SetValue( int row, int col, const wxString& value ) + virtual void SetValue(int row, int col, const wxString& value) { assert (false); //should not be used, since values are retrieved directly from gridRefUI } + virtual void Clear() { assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI} } - virtual bool InsertRows( size_t pos = 0, size_t numRows = 1 ) + + virtual bool InsertRows(size_t pos = 0, size_t numRows = 1) { assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI} return true; } - virtual bool AppendRows( size_t numRows = 1 ) + + virtual bool AppendRows(size_t numRows = 1) { assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI} return true; } - virtual bool DeleteRows( size_t pos = 0, size_t numRows = 1 ) + + virtual bool DeleteRows(size_t pos = 0, size_t numRows = 1) { assert (false); // we don't want to use this, since the visible grid is directly connected to gridRefUI} return true; @@ -216,7 +94,7 @@ public: { if (gridRefUI) { - int currentNrRows = GetNumberRows(); + const int currentNrRows = GetNumberRows(); if (lastNrRows < currentNrRows) { @@ -243,79 +121,326 @@ public: } lastNrRows = currentNrRows; } - } -//########################################################################### - enum RowColor {BLUE, GREY, NONE}; + const int currentNrCols = GetNumberCols(); - inline //redundant command - RowColor getRowColor(int row) //rows that are filtered out are shown in different color - { - if (gridRefUI) + if (lastNrCols < currentNrCols) { - if (unsigned(row) < gridRefUI->size()) + if (GetView()) { - const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]]; - - //mark filtered rows - if (!cmpLine.selectedForSynchronization) - return BLUE; - //mark directories - else if (gridIdentifier == 1 && cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY) - return GREY; - else if (gridIdentifier == 2 && cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY) - return GREY; - else - return NONE; + wxGridTableMessage msg(this, + wxGRIDTABLE_NOTIFY_COLS_APPENDED, + currentNrCols - lastNrCols); + + GetView()->ProcessTableMessage( msg ); } } - return NONE; + else if (lastNrCols > currentNrCols) + { + if (GetView()) + { + wxGridTableMessage msg(this, + wxGRIDTABLE_NOTIFY_COLS_DELETED, + 0, + lastNrCols - currentNrCols); + + GetView()->ProcessTableMessage( msg ); + } + } + lastNrCols = currentNrCols; } +//########################################################################### - wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) + virtual wxString GetColLabelValue( int col ) { - wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind); + return CustomGrid::getTypeName(getTypeAtPos(col)); + } + + + virtual wxGridCellAttr* GetAttr(int row, int col, wxGridCellAttr::wxAttrKind kind) + { + const wxColour& color = getRowColor(row); - // MARK FILTERED ROWS: + //add color to some rows + wxGridCellAttr* result = wxGridTableBase::GetAttr(row, col, kind); if (result) - { //if kind is not a cell or row attribute, we have to clone the cell attribute, since we don't want to change e.g. all column attribs - if (result->GetKind() != wxGridCellAttr::Cell && result->GetKind() != wxGridCellAttr::Row) + { + if (result->GetBackgroundColour() == color) { - wxGridCellAttr* attr = result->Clone(); + return result; + } + else //grid attribute might be referenced by other nodes, so clone it! + { + wxGridCellAttr* attr = result->Clone(); //attr has ref-count 1 result->DecRef(); result = attr; } - - RowColor color = getRowColor(row); - if (color == BLUE) - result->SetBackgroundColour(lightBlue); - else if (color == GREY) - result->SetBackgroundColour(lightGrey); - else - result->SetBackgroundColour(*wxWHITE); } else - { - result = new wxGridCellAttr; + result = new wxGridCellAttr; //created with ref-count 1 - RowColor color = getRowColor(row); - if (color == BLUE) - result->SetBackgroundColour(lightBlue); - else if (color == GREY) - result->SetBackgroundColour(lightGrey); - } + result->SetBackgroundColour(color); return result; } -private: + + void setupColumns(const std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes>& positions) + { + columnPositions = positions; + updateGridSizes(); //add or remove columns + } + + + XmlGlobalSettings::ColumnTypes getTypeAtPos(unsigned pos) const + { + if (pos < columnPositions.size()) + return columnPositions[pos]; + else + return XmlGlobalSettings::ColumnTypes(1000); + } + + +protected: + virtual const wxColour& getRowColor(int row) = 0; //rows that are filtered out are shown in different color + + std::vector<xmlAccess::XmlGlobalSettings::ColumnTypes> columnPositions; + wxColour lightBlue; wxColour lightGrey; - int gridIdentifier; GridView* gridRefUI; //(very fast) access to underlying grid data :) FileCompareResult* gridData; int lastNrRows; + int lastNrCols; +}; + + +class CustomGridTableLeft : public CustomGridTable +{ +public: + CustomGridTableLeft() : CustomGridTable() {} + ~CustomGridTableLeft() {} + + virtual const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color + { + if (gridRefUI && unsigned(row) < gridRefUI->size()) + { + const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]]; + + //mark filtered rows + if (!cmpLine.selectedForSynchronization) + return lightBlue; + //mark directories + else if (cmpLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY) + return lightGrey; + else + return *wxWHITE; + } + return *wxWHITE; + } + + + //virtual impl. + wxString GetValue(int row, int col) + { + if (gridRefUI) + { + if (unsigned(row) < gridRefUI->size()) + { + const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]]; + + if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_DIRECTORY) + { + switch (getTypeAtPos(col)) + { + case XmlGlobalSettings::FILENAME: //filename + return wxEmptyString; + case XmlGlobalSettings::REL_PATH: //relative path + return gridLine.fileDescrLeft.relativeName.c_str(); + case XmlGlobalSettings::SIZE: //file size + return _("<Directory>"); + case XmlGlobalSettings::DATE: //date + return wxEmptyString; + } + } + else if (gridLine.fileDescrLeft.objType == FileDescrLine::TYPE_FILE) + { + switch (getTypeAtPos(col)) + { + case XmlGlobalSettings::FILENAME: //filename + return gridLine.fileDescrLeft.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str(); + case XmlGlobalSettings::REL_PATH: //relative path + return gridLine.fileDescrLeft.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str(); + case XmlGlobalSettings::SIZE: //file size + { + wxString fileSize = gridLine.fileDescrLeft.fileSize.ToString(); //tmp string + return globalFunctions::includeNumberSeparator(fileSize); + } + case XmlGlobalSettings::DATE: //date + return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrLeft.lastWriteTimeRaw); + } + } + } + } + //if data is not found: + return wxEmptyString; + } +}; + + +class CustomGridTableMiddle : public CustomGridTable +{ +public: + CustomGridTableMiddle() : CustomGridTable() + { + lastNrCols = 1; //ensure CustomGridTable::updateGridSizes() is working correctly + } + ~CustomGridTableMiddle() {} + + //virtual impl. + int GetNumberCols() + { + return 1; + } + + + int selectedForSynchronization(const unsigned int row) // 0 == false, 1 == true, -1 == not defined + { + if (gridRefUI && row < gridRefUI->size()) + { + const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]]; + + if (cmpLine.selectedForSynchronization) + return 1; + else + return 0; + } + return -1; + } + + + //virtual impl. + const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color + { + if (gridRefUI && unsigned(row) < gridRefUI->size()) + { + const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]]; + + //mark filtered rows + if (!cmpLine.selectedForSynchronization) + return lightBlue; + else + return *wxWHITE; + } + return *wxWHITE; + } + + //virtual impl. + wxString GetValue(int row, int col) + { + if (gridRefUI) + { + if (unsigned(row) < gridRefUI->size()) + { + const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]]; + + switch (gridLine.cmpResult) + { + case FILE_LEFT_SIDE_ONLY: + return wxT("<|"); + case FILE_RIGHT_SIDE_ONLY: + return wxT("|>"); + case FILE_RIGHT_NEWER: + return wxT(">>"); + case FILE_LEFT_NEWER: + return wxT("<<"); + case FILE_DIFFERENT: + return wxT("!="); + case FILE_EQUAL: + return wxT("=="); + default: + assert (false); + return wxEmptyString; + } + } + } + //if data is not found: + return wxEmptyString; + } +}; + + +class CustomGridTableRight : public CustomGridTable +{ +public: + CustomGridTableRight() : CustomGridTable() {} + ~CustomGridTableRight() {} + + //virtual impl. + const wxColour& getRowColor(int row) //rows that are filtered out are shown in different color + { + if (gridRefUI && unsigned(row) < gridRefUI->size()) + { + const FileCompareLine cmpLine = (*gridData)[(*gridRefUI)[row]]; + + //mark filtered rows + if (!cmpLine.selectedForSynchronization) + return lightBlue; + //mark directories + else if (cmpLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY) + return lightGrey; + else + return *wxWHITE; + } + return *wxWHITE; + } + + //virtual impl. + wxString GetValue(int row, int col) + { + if (gridRefUI) + { + if (unsigned(row) < gridRefUI->size()) + { + const FileCompareLine& gridLine = (*gridData)[(*gridRefUI)[row]]; + + if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_DIRECTORY) + { + switch (getTypeAtPos(col)) + { + case XmlGlobalSettings::FILENAME: //filename + return wxEmptyString; + case XmlGlobalSettings::REL_PATH: //relative path + return gridLine.fileDescrRight.relativeName.c_str(); + case XmlGlobalSettings::SIZE: //file size + return _("<Directory>"); + case XmlGlobalSettings::DATE: //date + return wxEmptyString; + } + } + else if (gridLine.fileDescrRight.objType == FileDescrLine::TYPE_FILE) + { + switch (getTypeAtPos(col)) + { + case XmlGlobalSettings::FILENAME: //filename + return gridLine.fileDescrRight.relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR).c_str(); + case XmlGlobalSettings::REL_PATH: //relative path + return gridLine.fileDescrRight.relativeName.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR).c_str(); + case XmlGlobalSettings::SIZE: //file size + { + wxString fileSize = gridLine.fileDescrRight.fileSize.ToString(); //tmp string + return globalFunctions::includeNumberSeparator(fileSize); + } + case XmlGlobalSettings::DATE: //date + return FreeFileSync::utcTimeToLocalString(gridLine.fileDescrRight.lastWriteTimeRaw); + } + } + } + } + //if data is not found: + return wxEmptyString; + } }; @@ -333,26 +458,33 @@ CustomGrid::CustomGrid(wxWindow *parent, m_gridLeft(NULL), m_gridRight(NULL), m_gridMiddle(NULL), gridDataTable(NULL), currentSortColumn(-1), - sortMarker(NULL) {} - - -CustomGrid::~CustomGrid() {} - - -bool CustomGrid::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) + sortMarker(NULL) { - //use custom wxGridTableBase class for management of large sets of formatted data. - //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default. - - gridDataTable = new CustomGridTableBase(numRows, numCols); - SetTable(gridDataTable, true, selmode); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor - return true; + //set color of selections + wxColour darkBlue(40, 35, 140); + SetSelectionBackground(darkBlue); + SetSelectionForeground(*wxWHITE); } -void CustomGrid::deactivateScrollbars() +void CustomGrid::initSettings(bool enableScrollbars, + CustomGrid* gridLeft, + CustomGrid* gridRight, + CustomGrid* gridMiddle, + GridView* gridRefUI, + FileCompareResult* gridData) { - scrollbarsEnabled = false; + scrollbarsEnabled = enableScrollbars; + + //these grids will scroll together + assert(gridLeft && gridRight && gridMiddle); + m_gridLeft = gridLeft; + m_gridRight = gridRight; + m_gridMiddle = gridMiddle; + + //set underlying grid data + assert(gridDataTable); + gridDataTable->setGridDataTable(gridRefUI, gridData); } @@ -380,7 +512,7 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are if (y1 != y2 || y2 != y3) { - int yMax = max(y1, max(y2, y3)); + int yMax = std::max(y1, std::max(y2, y3)); if (::leadGrid == m_gridLeft) //do not handle case (y1 == yMax) here!!! Avoid back coupling! m_gridLeft->SetMargins(0, 0); @@ -404,90 +536,311 @@ void CustomGrid::adjustGridHeights() //m_gridLeft, m_gridRight, m_gridMiddle are } -//this method is called when grid view changes: useful for parallel updating of multiple grids -void CustomGrid::DoPrepareDC(wxDC& dc) +void CustomGrid::updateGridSizes() { - wxScrollHelper::DoPrepareDC(dc); + assert(gridDataTable); + gridDataTable->updateGridSizes(); +} - int x, y = 0; - if (this == ::leadGrid) //avoid back coupling - { - if (this == m_gridLeft) + +void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap) +{ + currentSortColumn = sortColumn; + sortMarker = bitmap; +} + + +void CustomGrid::DrawColLabel(wxDC& dc, int col) +{ + wxGrid::DrawColLabel(dc, col); + + if (col == currentSortColumn) + dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border +} + + +void CustomGrid::setColumnAttributes(const xmlAccess::XmlGlobalSettings::ColumnAttributes& attr) +{ + //remove special alignment for column "size" + for (int i = 0; i < GetNumberCols(); ++i) + if (getTypeAtPos(i) == XmlGlobalSettings::SIZE) { - GetViewStart(&x, &y); - m_gridRight->Scroll(x, y); - m_gridMiddle->Scroll(-1, y); //scroll in y-direction only - adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL + wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i); + cellAttributes->SetAlignment(wxALIGN_LEFT,wxALIGN_CENTRE); + SetColAttr(i, cellAttributes); + break; } - else if (this == m_gridRight) +//---------------------------------------------------------------------------------- + setSortMarker(-1); //clear sorting marker + + columnSettings.clear(); + if (attr.size() == 0) + { //default settings: + xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry; + newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME; + newEntry.visible = true; + newEntry.position = 0; + newEntry.width = 138; + columnSettings.push_back(newEntry); + + newEntry.type = xmlAccess::XmlGlobalSettings::REL_PATH; + newEntry.position = 1; + newEntry.width = 118; + columnSettings.push_back(newEntry); + + newEntry.type = xmlAccess::XmlGlobalSettings::SIZE; + newEntry.position = 2; + newEntry.width = 67; + columnSettings.push_back(newEntry); + + newEntry.type = xmlAccess::XmlGlobalSettings::DATE; + newEntry.position = 3; + newEntry.width = 113; + columnSettings.push_back(newEntry); + } + else + { + for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) { - GetViewStart(&x, &y); - m_gridLeft->Scroll(x, y); - m_gridMiddle->Scroll(-1, y); - adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL + XmlGlobalSettings::ColumnAttrib newEntry; + + if (i < attr.size()) + newEntry = attr[i]; + else + { + newEntry.type = xmlAccess::XmlGlobalSettings::FILENAME; + newEntry.visible = true; + newEntry.position = i; + newEntry.width = 100; + } + columnSettings.push_back(newEntry); } - else if (this == m_gridMiddle) + + sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByType); + for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that each type exists only once + columnSettings[i].type = XmlGlobalSettings::ColumnTypes(i); + + sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly); + for (unsigned int i = 0; i < COLUMN_TYPE_COUNT; ++i) //just be sure that positions are numbered correctly + columnSettings[i].position = i; + + sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility); + } + + std::vector<XmlGlobalSettings::ColumnTypes> newPositions; + for (unsigned int i = 0; i < columnSettings.size() && columnSettings[i].visible; ++i) //hidden columns are sorted to the end of vector! + newPositions.push_back(columnSettings[i].type); + + //set column positions + assert(gridDataTable); + gridDataTable->setupColumns(newPositions); + + //set column width (set them after setupColumns!) + for (unsigned int i = 0; i < newPositions.size(); ++i) + SetColSize(i, columnSettings[i].width); + +//-------------------------------------------------------------------------------------------------------- + //set special alignment for column "size" + for (int i = 0; i < GetNumberCols(); ++i) + if (getTypeAtPos(i) == XmlGlobalSettings::SIZE) { - GetViewStart(&x, &y); - m_gridLeft->Scroll(-1, y); - m_gridRight->Scroll(-1, y); - adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL + wxGridCellAttr* cellAttributes = GetOrCreateCellAttr(0, i); + cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); + SetColAttr(i, cellAttributes); //make filesize right justified on grids + break; } - } + + ClearSelection(); + ForceRefresh(); } -//these classes will scroll together, hence the name ;) -void CustomGrid::setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle) +xmlAccess::XmlGlobalSettings::ColumnAttributes CustomGrid::getColumnAttributes() { - assert(gridLeft && gridRight && gridMiddle); + sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionAndVisibility); - m_gridLeft = gridLeft; - m_gridRight = gridRight; - m_gridMiddle = gridMiddle; + xmlAccess::XmlGlobalSettings::ColumnAttributes output; + xmlAccess::XmlGlobalSettings::ColumnAttrib newEntry; + for (unsigned int i = 0; i < columnSettings.size(); ++i) + { + newEntry = columnSettings[i]; + if (newEntry.visible) //hidden columns are sorted to the end of vector! + newEntry.width = GetColSize(i); + output.push_back(newEntry); + } - assert(gridDataTable); - if (this == m_gridLeft) - gridDataTable->SetGridIdentifier(1); - else if (this == m_gridRight) - gridDataTable->SetGridIdentifier(2); - else if (this == m_gridMiddle) - gridDataTable->SetGridIdentifier(3); - else - assert (false); + return output; } -void CustomGrid::setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData) -{ //set underlying grid data +XmlGlobalSettings::ColumnTypes CustomGrid::getTypeAtPos(unsigned pos) const +{ assert(gridDataTable); - gridDataTable->setGridDataTable(gridRefUI, gridData); + return gridDataTable->getTypeAtPos(pos); } -void CustomGrid::updateGridSizes() +wxString CustomGrid::getTypeName(XmlGlobalSettings::ColumnTypes colType) { - assert(gridDataTable); - gridDataTable->updateGridSizes(); + switch (colType) + { + case XmlGlobalSettings::FILENAME: + return _("Filename"); + case XmlGlobalSettings::REL_PATH: + return _("Relative path"); + case XmlGlobalSettings::SIZE: + return _("Size"); + case XmlGlobalSettings::DATE: + return _("Date"); + default: + return wxEmptyString; + } } +//############################################################################################ +//CustomGrid specializations -void CustomGrid::setSortMarker(const int sortColumn, const wxBitmap* bitmap) +CustomGridLeft::CustomGridLeft(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) : + CustomGrid(parent, id, pos, size, style, name) {} + + +bool CustomGridLeft::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) { - currentSortColumn = sortColumn; - sortMarker = bitmap; + //use custom wxGridTableBase class for management of large sets of formatted data. + //This is done in CreateGrid instead of SetTable method since source code is generated and wxFormbuilder invokes CreatedGrid by default. + gridDataTable = new CustomGridTableLeft(); + SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor + return true; } -void CustomGrid::DrawColLabel(wxDC& dc, int col) +//this method is called when grid view changes: useful for parallel updating of multiple grids +void CustomGridLeft::DoPrepareDC(wxDC& dc) { - assert(0 <= col && col < 4); + wxScrollHelper::DoPrepareDC(dc); - wxGrid::DrawColLabel(dc, col); + int x, y = 0; + if (this == ::leadGrid) //avoid back coupling + { + GetViewStart(&x, &y); + m_gridMiddle->Scroll(-1, y); //scroll in y-direction only + m_gridRight->Scroll(x, y); + adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL + } +} - if (col == currentSortColumn) + +//---------------------------------------------------------------------------------------- +CustomGridMiddle::CustomGridMiddle(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) : + CustomGrid(parent, id, pos, size, style, name) {} + + +bool CustomGridMiddle::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) +{ + CustomGridTableMiddle* newTable = new CustomGridTableMiddle(); + gridDataTable = newTable; + SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor + + //display checkboxes (representing bool values) if row is enabled for synchronization + SetDefaultRenderer(new GridCellRendererAddCheckbox(newTable)); //SetDefaultRenderer takes ownership! + + return true; +} + + +//this method is called when grid view changes: useful for parallel updating of multiple grids +void CustomGridMiddle::DoPrepareDC(wxDC& dc) +{ + wxScrollHelper::DoPrepareDC(dc); + + int x, y = 0; + if (this == ::leadGrid) //avoid back coupling { - dc.DrawBitmap(*sortMarker, GetColRight(col) - 16 - 2, 2, true); //respect 2-pixel border + GetViewStart(&x, &y); + m_gridLeft->Scroll(-1, y); + m_gridRight->Scroll(-1, y); + adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL } } + +void CustomGridMiddle::GridCellRendererAddCheckbox::Draw(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + const wxRect& rect, + int row, int col, + bool isSelected) +{ + const int selected = m_gridDataTable->selectedForSynchronization(row); + if (selected < 0) //no valid row + { + wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); + return; + } + + const int shift = std::min(11 + 3, rect.GetWidth()); //11 is width of checkbox image + + wxRect rectShrinked(rect); + + //clean first block of rect that will receive image of checkbox + rectShrinked.SetWidth(shift); + dc.SetPen(*wxWHITE_PEN); + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(rectShrinked); + + //print image into first block + rectShrinked.SetX(1); + if (selected > 0) + dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxTrue, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + else //if (selected == 0) -> redundant + dc.DrawLabel(wxEmptyString, *globalResource.bitmapCheckBoxFalse, rectShrinked, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + + //print second block (default): display compare result + rectShrinked.SetWidth(rect.GetWidth() - shift); + rectShrinked.SetX(shift); + wxGridCellStringRenderer::Draw(grid, attr, dc, rectShrinked, row, col, isSelected); +} + + +//---------------------------------------------------------------------------------------- +CustomGridRight::CustomGridRight(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) : + CustomGrid(parent, id, pos, size, style, name) {} + + +bool CustomGridRight::CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode) +{ + gridDataTable = new CustomGridTableRight(); + SetTable(gridDataTable, true, wxGrid::wxGridSelectRows); //give ownership to wxGrid: gridDataTable is deleted automatically in wxGrid destructor + return true; +} + + +//this method is called when grid view changes: useful for parallel updating of multiple grids +void CustomGridRight::DoPrepareDC(wxDC& dc) +{ + wxScrollHelper::DoPrepareDC(dc); + + int x, y = 0; + if (this == ::leadGrid) //avoid back coupling + { + GetViewStart(&x, &y); + m_gridLeft->Scroll(x, y); + m_gridMiddle->Scroll(-1, y); + adjustGridHeights(); //keep here to ensure m_gridLeft, m_gridRight, m_gridMiddle != NULL + } +} diff --git a/library/CustomGrid.h b/library/CustomGrid.h index bd2f3fa8..97642159 100644 --- a/library/CustomGrid.h +++ b/library/CustomGrid.h @@ -4,12 +4,13 @@ #include <vector> #include <wx/grid.h> #include "../FreeFileSync.h" +#include "processXml.h" using namespace FreeFileSync; -class CustomGridTableBase; - +class CustomGridTable; +class CustomGridTableMiddle; //################################################################################## extern const wxGrid* leadGrid; //this global variable is not very nice... @@ -24,35 +25,128 @@ public: long style = wxWANTS_CHARS, const wxString& name = wxGridNameStr); - ~CustomGrid(); + virtual ~CustomGrid() {} - virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); //overwrite virtual method to finally get rid of the scrollbars virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh = true); - //this method is called when grid view changes: useful for parallel updating of multiple grids - virtual void DoPrepareDC(wxDC& dc); + virtual void DrawColLabel(wxDC& dc, int col); - void deactivateScrollbars(); - void setScrollFriends(CustomGrid* gridLeft, CustomGrid* gridRight, CustomGrid* gridMiddle); - void setGridDataTable(GridView* gridRefUI, FileCompareResult* gridData); + void initSettings(bool enableScrollbars, + CustomGrid* gridLeft, + CustomGrid* gridRight, + CustomGrid* gridMiddle, + GridView* gridRefUI, + FileCompareResult* gridData); + + //notify wxGrid that underlying table size has changed void updateGridSizes(); + //set sort direction indicator on UI void setSortMarker(const int sortColumn, const wxBitmap* bitmap = &wxNullBitmap); -private: + //set visibility, position and width of columns + void setColumnAttributes(const xmlAccess::XmlGlobalSettings::ColumnAttributes& attr); + xmlAccess::XmlGlobalSettings::ColumnAttributes getColumnAttributes(); + + xmlAccess::XmlGlobalSettings::ColumnTypes getTypeAtPos(unsigned pos) const; + + static wxString getTypeName(xmlAccess::XmlGlobalSettings::ColumnTypes colType); + + static const unsigned COLUMN_TYPE_COUNT = 4; + +protected: + //set visibility, position and width of columns + xmlAccess::XmlGlobalSettings::ColumnAttributes columnSettings; + + void adjustGridHeights(); bool scrollbarsEnabled; - CustomGrid* m_gridLeft; CustomGrid* m_gridRight; CustomGrid* m_gridMiddle; - CustomGridTableBase* gridDataTable; + CustomGridTable* gridDataTable; int currentSortColumn; const wxBitmap* sortMarker; }; + +class CustomGridLeft : public CustomGrid +{ +public: + CustomGridLeft(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxWANTS_CHARS, + const wxString& name = wxGridNameStr); + + ~CustomGridLeft() {} + + //this method is called when grid view changes: useful for parallel updating of multiple grids + virtual void DoPrepareDC(wxDC& dc); + + virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); +}; + + +class CustomGridMiddle : public CustomGrid +{ +public: + CustomGridMiddle(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxWANTS_CHARS, + const wxString& name = wxGridNameStr); + + ~CustomGridMiddle() {} + + //this method is called when grid view changes: useful for parallel updating of multiple grids + virtual void DoPrepareDC(wxDC& dc); + + virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); + +private: + + class GridCellRendererAddCheckbox : public wxGridCellStringRenderer + { + public: + GridCellRendererAddCheckbox(CustomGridTableMiddle* gridDataTable) : m_gridDataTable(gridDataTable) {}; + + + virtual void Draw(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + const wxRect& rect, + int row, int col, + bool isSelected); + + private: + CustomGridTableMiddle* m_gridDataTable; + }; +}; + + +class CustomGridRight : public CustomGrid +{ +public: + CustomGridRight(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxWANTS_CHARS, + const wxString& name = wxGridNameStr); + + ~CustomGridRight() {} + + //this method is called when grid view changes: useful for parallel updating of multiple grids + virtual void DoPrepareDC(wxDC& dc); + + virtual bool CreateGrid(int numRows, int numCols, wxGrid::wxGridSelectionModes selmode = wxGrid::wxGridSelectCells); +}; + #endif // CUSTOMGRID_H_INCLUDED diff --git a/library/customButton.cpp b/library/customButton.cpp new file mode 100644 index 00000000..5cfa8a5a --- /dev/null +++ b/library/customButton.cpp @@ -0,0 +1,293 @@ +#include "customButton.h" +#include <wx/dcmemory.h> +#include <wx/image.h> + +wxButtonWithImage::wxButtonWithImage(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) : + wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name) +{ + setTextLabel(label); +} + + +void wxButtonWithImage::setBitmapFront(const wxBitmap& bitmap) +{ + bitmapFront = bitmap; + refreshButtonLabel(); +} + + +void wxButtonWithImage::setTextLabel(const wxString& text) +{ + textLabel = text; + wxBitmapButton::SetLabel(text); + refreshButtonLabel(); +} + + +void wxButtonWithImage::setBitmapBack(const wxBitmap& bitmap) +{ + bitmapBack = bitmap; + refreshButtonLabel(); +} + + +void makeWhiteTransparent(const wxColor exceptColor, wxImage& image) +{ + unsigned char* alphaData = image.GetAlpha(); + if (alphaData) + { + assert(exceptColor.Red() != 255); + + unsigned char exCol = exceptColor.Red(); //alpha value can be extracted from any one of (red/green/blue) + unsigned char* imageStart = image.GetData(); + + unsigned char* j = alphaData; + const unsigned char* const rowEnd = j + image.GetWidth() * image.GetHeight(); + while (j != rowEnd) + { + const unsigned char* imagePixel = imageStart + (j - alphaData) * 3; //each pixel consists of three chars + //exceptColor(red,green,blue) becomes fully opaque(255), while white(255,255,255) becomes transparent(0) + *(j++) = ((255 - imagePixel[0]) * wxIMAGE_ALPHA_OPAQUE) / (255 - exCol); + } + } +} + + +wxSize getSizeNeeded(const wxString& text, wxFont& font) +{ + wxCoord width, height; + wxMemoryDC dc; + + wxString textFormatted = text; + textFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator + dc.GetMultiLineTextExtent(textFormatted, &width, &height , NULL, &font); + return wxSize(width, height); +} + +/* +inline +void linearInterpolationHelper(const int shift, wxImage& img) +{ + unsigned char* const data = img.GetData(); + const int width = img.GetWidth(); + if (width < 2) + return; + + const float intensity = 0.25; + + for (int y = 1; y < img.GetHeight() - 1; ++y) + { + float back = 0; + float middle = 0; + float front = 0; + + unsigned char* location = data + 3 * (y * width) + shift; + const unsigned char* const endPos = location + 3 * width; + + middle = (*location + *(location - 3 * width) + *(location + 3 * width)) / 3;; + front = (*(location + 3) + *(location + 3 * (1 - width)) + *(location + 3 * (1 + width))) / 3; + *location += ((middle + front) / 2 - *location) * intensity; + location += 3; + + while (location < endPos - 3) + { + back = middle; + middle = front; + front = (*(location + 3) + *(location + 3 * (1 - width)) + *(location + 3 * (1 + width))) / 3; + *location += ((back + middle + front) / 3 - *location) * intensity; + location += 3; + } + + back = middle; + middle = front; + *location += ((back + middle) / 2 - *location) * intensity; + } +} + + +void linearInterpolation(wxImage& img) +{ + linearInterpolationHelper(0, img); //red channel + linearInterpolationHelper(1, img); //green channel + linearInterpolationHelper(2, img); //blue channel +} +*/ + +wxBitmap wxButtonWithImage::createBitmapFromText(const wxString& text) +{ + wxFont currentFont = wxBitmapButton::GetFont(); + wxColor textColor = wxBitmapButton::GetForegroundColour(); + + wxSize sizeNeeded = getSizeNeeded(text, currentFont); + wxBitmap newBitmap(sizeNeeded.GetWidth(), sizeNeeded.GetHeight()); + + wxMemoryDC dc; + dc.SelectObject(newBitmap); + + //set up white background + dc.SetBackground(*wxWHITE_BRUSH); + dc.Clear(); + + //find position of accelerator + int indexAccel = -1; + size_t accelPos; + wxString textLabelFormatted = text; + if ((accelPos = text.find(wxT("&"))) != wxString::npos) + { + textLabelFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator + indexAccel = accelPos; + } + + dc.SetTextForeground(textColor); + dc.SetTextBackground(*wxWHITE); + dc.SetFont(currentFont); + dc.DrawLabel(textLabelFormatted, wxNullBitmap, wxRect(0, 0, newBitmap.GetWidth(), newBitmap.GetHeight()), wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, indexAccel); + + dc.SelectObject(wxNullBitmap); + + //add alpha channel to image + wxImage finalImage(newBitmap.ConvertToImage()); + finalImage.SetAlpha(); + + //linearInterpolation(finalImage); + + //make white background transparent + makeWhiteTransparent(textColor, finalImage); + + return wxBitmap(finalImage); +} + + +//copy one image into another, allowing arbitrary overlapping! (pos may contain negative numbers) +void writeToImage(const wxImage& source, const wxPoint pos, wxImage& target) +{ + //determine startpositions in source and target image, as well as width and height to be copied + wxPoint posSrc, posTrg; + int width, height; + + //X-axis + if (pos.x < 0) + { + posSrc.x = -pos.x; + posTrg.x = 0; + width = std::min(pos.x + source.GetWidth(), target.GetWidth()); + } + else + { + posSrc.x = 0; + posTrg.x = pos.x; + width = std::min(target.GetWidth() - pos.x, source.GetWidth()); + } + + //Y-axis + if (pos.y < 0) + { + posSrc.y = -pos.y; + posTrg.y = 0; + height = std::min(pos.y + source.GetHeight(), target.GetHeight()); + } + else + { + posSrc.y = 0; + posTrg.y = pos.y; + height = std::min(target.GetHeight() - pos.y, source.GetHeight()); + } + + + if (width > 0 && height > 0) + { + //copy source to target respecting overlapping parts + const unsigned char* sourcePtr = source.GetData() + 3 * (posSrc.x + posSrc.y * source.GetWidth()); + const unsigned char* const sourcePtrEnd = source.GetData() + 3 * (posSrc.x + (posSrc.y + height) * source.GetWidth()); + unsigned char* targetPtr = target.GetData() + 3 * (posTrg.x + posTrg.y * target.GetWidth()); + + while (sourcePtr < sourcePtrEnd) + { + memcpy(targetPtr, sourcePtr, 3 * width); + sourcePtr += 3 * source.GetWidth(); + targetPtr += 3 * target.GetWidth(); + } + + //handle different cases concerning alpha channel + if (source.HasAlpha()) + { + if (!target.HasAlpha()) + { + target.SetAlpha(); + unsigned char* alpha = target.GetAlpha(); + memset(alpha, wxIMAGE_ALPHA_OPAQUE, target.GetWidth() * target.GetHeight()); + } + + //copy alpha channel + const unsigned char* sourcePtr = source.GetAlpha() + (posSrc.x + posSrc.y * source.GetWidth()); + const unsigned char* const sourcePtrEnd = source.GetAlpha() + (posSrc.x + (posSrc.y + height) * source.GetWidth()); + unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth()); + + while (sourcePtr < sourcePtrEnd) + { + memcpy(targetPtr, sourcePtr, width); + sourcePtr += source.GetWidth(); + targetPtr += target.GetWidth(); + } + } + else if (target.HasAlpha()) + { + unsigned char* targetPtr = target.GetAlpha() + (posTrg.x + posTrg.y * target.GetWidth()); + const unsigned char* const targetPtrEnd = target.GetAlpha() + (posTrg.x + (posTrg.y + height) * target.GetWidth()); + + while (targetPtr < targetPtrEnd) + { + memset(targetPtr, wxIMAGE_ALPHA_OPAQUE, width); + targetPtr += target.GetWidth(); + } + } + } +} + + +void wxButtonWithImage::refreshButtonLabel() +{ + wxBitmap bitmapText = createBitmapFromText(textLabel); + + //calculate dimensions of new button + const int height = std::max(std::max(bitmapFront.GetHeight(), bitmapText.GetHeight()), bitmapBack.GetHeight()); + const int width = bitmapFront.GetWidth() + bitmapText.GetWidth() + bitmapBack.GetWidth(); + + //create a transparent image + wxImage transparentImage(width, height, false); + transparentImage.SetAlpha(); + unsigned char* alpha = transparentImage.GetAlpha(); + memset(alpha, wxIMAGE_ALPHA_TRANSPARENT, width * height); + + //wxDC::DrawLabel() unfortunately isn't working for transparent images on Linux, so we need to use custom image-concatenation + if (bitmapFront.IsOk()) + writeToImage(wxImage(bitmapFront.ConvertToImage()), + wxPoint(0, (transparentImage.GetHeight() - bitmapFront.GetHeight()) / 2), + transparentImage); + + if (bitmapText.IsOk()) + writeToImage(wxImage(bitmapText.ConvertToImage()), + wxPoint(bitmapFront.GetWidth(), (transparentImage.GetHeight() - bitmapText.GetHeight()) / 2), + transparentImage); + + if (bitmapBack.IsOk()) + writeToImage(wxImage(bitmapBack.ConvertToImage()), + wxPoint(bitmapFront.GetWidth() + bitmapText.GetWidth(), (transparentImage.GetHeight() - bitmapBack.GetHeight()) / 2), + transparentImage); + + //adjust button size + wxSize minSize = GetMinSize(); + + //SetMinSize() instead of SetSize() is needed here for wxWindows layout determination to work corretly + wxBitmapButton::SetMinSize(wxSize(std::max(width + 10, minSize.GetWidth()), std::max(height + 5, minSize.GetHeight()))); + + //finally set bitmap + wxBitmapButton::SetBitmapLabel(wxBitmap(transparentImage)); +} diff --git a/library/customButton.h b/library/customButton.h new file mode 100644 index 00000000..1f3f50ec --- /dev/null +++ b/library/customButton.h @@ -0,0 +1,40 @@ +/*************************************************************** + * Purpose: wxButton with bitmap label + * Author: ZenJu (zhnmju123@gmx.de) + * Created: Feb. 2009 + **************************************************************/ + +#ifndef CUSTOMBUTTON_H_INCLUDED +#define CUSTOMBUTTON_H_INCLUDED + +#include <wx/bmpbuttn.h> + + +//wxButtonWithImage behaves like wxButton but optionally adds bitmap labels +class wxButtonWithImage : public wxBitmapButton +{ +public: + wxButtonWithImage(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxButtonNameStr); + + void setBitmapFront(const wxBitmap& bitmap); + void setTextLabel( const wxString& text); + void setBitmapBack( const wxBitmap& bitmap); + +private: + wxBitmap createBitmapFromText(const wxString& text); + void refreshButtonLabel(); + + wxBitmap bitmapFront; + wxString textLabel; + wxBitmap bitmapBack; +}; + + +#endif // CUSTOMBUTTON_H_INCLUDED diff --git a/library/fileHandling.cpp b/library/fileHandling.cpp index eb14b2f6..688d3640 100644 --- a/library/fileHandling.cpp +++ b/library/fileHandling.cpp @@ -8,9 +8,9 @@ #endif // FFS_WIN inline -bool endsWithPathSeparator(const wxChar* name) +bool endsWithPathSeparator(const Zstring& name) { - size_t len = wxStrlen(name); + const size_t len = name.length(); return len && (name[len - 1] == GlobalResources::FILE_NAME_SEPARATOR); } @@ -84,12 +84,12 @@ bool moveToRecycleBin(const Zstring& filename) throw(RuntimeException) inline void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin) { - if (!wxFileExists(filename)) return; //this is NOT an error situation: the manual deletion relies on it! + if (!wxFileExists(filename.c_str())) return; //this is NOT an error situation: the manual deletion relies on it! if (useRecycleBin) { if (!moveToRecycleBin(filename)) - throw FileError(wxString(_("Error moving to recycle bin:")) + wxT(" \"") + filename.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error moving to recycle bin:")) + wxT(" \"") + filename + wxT("\"")); return; } @@ -97,11 +97,11 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin) if (!SetFileAttributes( filename.c_str(), //address of filename FILE_ATTRIBUTE_NORMAL //attributes to set - )) throw FileError(wxString(_("Error deleting file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); + )) throw FileError(Zstring(_("Error deleting file:")) + wxT(" \"") + filename + wxT("\"")); #endif //FFS_WIN - if (!wxRemoveFile(filename)) - throw FileError(wxString(_("Error deleting file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); + if (!wxRemoveFile(filename.c_str())) + throw FileError(Zstring(_("Error deleting file:")) + wxT(" \"") + filename + wxT("\"")); } @@ -112,12 +112,12 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc if (useRecycleBin) { if (!moveToRecycleBin(directory)) - throw FileError(wxString(_("Error moving to recycle bin:")) + wxT(" \"") + directory.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error moving to recycle bin:")) + wxT(" \"") + directory + wxT("\"")); return; } - vector<Zstring> fileList; - vector<Zstring> dirList; + std::vector<Zstring> fileList; + std::vector<Zstring> dirList; try { //should be executed in own scope so that directory access does not disturb deletion! @@ -125,7 +125,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc } catch (const FileError& e) { - throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + directory.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + directory + wxT("\"")); } for (unsigned int j = 0; j < fileList.size(); ++j) @@ -139,11 +139,11 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc if (!SetFileAttributes( dirList[j].c_str(), // address of directory name FILE_ATTRIBUTE_NORMAL)) // attributes to set - throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + dirList[j].c_str() + wxT("\"")); + throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + dirList[j] + wxT("\"")); #endif // FFS_WIN - if (!wxRmdir(dirList[j])) - throw FileError(wxString(_("Error deleting directory:")) + wxT(" \"") + dirList[j].c_str() + wxT("\"")); + if (!wxRmdir(dirList[j].c_str())) + throw FileError(Zstring(_("Error deleting directory:")) + wxT(" \"") + dirList[j] + wxT("\"")); } } @@ -157,12 +157,12 @@ void FreeFileSync::createDirectory(const Zstring& directory, const int level) return; //try to create directory - if (wxMkdir(directory)) + if (wxMkdir(directory.c_str())) return; //if not successfull try to create parent folders first Zstring parentDir; - if (endsWithPathSeparator(directory.c_str())) //may be valid on first level of recursion at most! Usually never true! + if (endsWithPathSeparator(directory)) //may be valid on first level of recursion at most! Usually never true! { parentDir = directory.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR); parentDir = parentDir.BeforeLast(GlobalResources::FILE_NAME_SEPARATOR); @@ -176,10 +176,10 @@ void FreeFileSync::createDirectory(const Zstring& directory, const int level) createDirectory(parentDir, level + 1); //now creation should be possible - if (!wxMkdir(directory)) + if (!wxMkdir(directory.c_str())) { if (level == 0) - throw FileError(wxString(_("Error creating directory:")) + wxT(" \"") + directory.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error creating directory:")) + wxT(" \"") + directory + wxT("\"")); } } @@ -189,12 +189,12 @@ void FreeFileSync::copyFolderAttributes(const Zstring& source, const Zstring& ta #ifdef FFS_WIN DWORD attr = GetFileAttributes(source.c_str()); // address of the name of a file or directory if (attr == 0xFFFFFFFF) - throw FileError(wxString(_("Error reading file attributes:")) + wxT(" \"") + source.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error reading folder attributes:")) + wxT(" \"") + source + wxT("\"")); if (!SetFileAttributes( target.c_str(), // address of filename attr)) // address of attributes to set - throw FileError(wxString(_("Error writing file attributes:")) + wxT(" \"") + target.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error writing folder attributes:")) + wxT(" \"") + target + wxT("\"")); #elif defined FFS_LINUX //Linux doesn't use attributes for files or folders #endif @@ -204,19 +204,19 @@ void FreeFileSync::copyFolderAttributes(const Zstring& source, const Zstring& ta class GetAllFilesSimple : public wxDirTraverser { public: - GetAllFilesSimple(vector<Zstring>& files, vector<Zstring>& subDirectories) : + GetAllFilesSimple(std::vector<Zstring>& files, std::vector<Zstring>& subDirectories) : m_files(files), m_dirs(subDirectories) {} wxDirTraverseResult OnDir(const wxString& dirname) { - m_dirs.push_back(dirname); + m_dirs.push_back(dirname.c_str()); return wxDIR_CONTINUE; } wxDirTraverseResult OnFile(const wxString& filename) { - m_files.push_back(filename); + m_files.push_back(filename.c_str()); return wxDIR_CONTINUE; } @@ -227,22 +227,22 @@ public: } private: - vector<Zstring>& m_files; - vector<Zstring>& m_dirs; + std::vector<Zstring>& m_files; + std::vector<Zstring>& m_dirs; }; -void FreeFileSync::getAllFilesAndDirs(const Zstring& sourceDir, vector<Zstring>& files, vector<Zstring>& directories) throw(FileError) +void FreeFileSync::getAllFilesAndDirs(const Zstring& sourceDir, std::vector<Zstring>& files, std::vector<Zstring>& directories) throw(FileError) { files.clear(); directories.clear(); //get all files and directories from current directory (and subdirectories) - wxDir dir(sourceDir); + wxDir dir(sourceDir.c_str()); GetAllFilesSimple traverser(files, directories); if (dir.Traverse(traverser) == (size_t)-1) - throw FileError(wxString(_("Error traversing directory:")) + wxT(" \"") + sourceDir.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error traversing directory:")) + wxT(" \"") + sourceDir + wxT("\"")); } @@ -267,10 +267,10 @@ void getWin32FileInformation(const WIN32_FIND_DATA& input, FreeFileSync::FileInf { //convert UTC FILETIME to ANSI C format (number of seconds since Jan. 1st 1970 UTC) wxULongLong writeTimeLong(input.ftLastWriteTime.dwHighDateTime, input.ftLastWriteTime.dwLowDateTime); - writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s) - writeTimeLong -= wxULongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s - output.lastWriteTimeRaw = writeTimeLong.GetLo(); //it should fit into a 32bit variable now - assert(writeTimeLong.GetHi() == 0); + writeTimeLong /= 10000000; //reduce precision to 1 second (FILETIME has unit 10^-7 s) + writeTimeLong -= wxULongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s + assert(writeTimeLong.GetHi() == 0); //it should fit into a 32bit variable now + output.lastWriteTimeRaw = writeTimeLong.GetLo(); output.fileSize = wxULongLong(input.nFileSizeHigh, input.nFileSizeLow); } @@ -281,7 +281,7 @@ class EnhancedFileTraverser : public wxDirTraverser public: EnhancedFileTraverser(FreeFileSync::FullDetailFileTraverser* sink) : m_sink(sink) {} - virtual wxDirTraverseResult OnFile(const wxString& filename) + wxDirTraverseResult OnFile(const wxString& filename) //virtual impl. { struct stat fileInfo; if (stat(filename.c_str(), &fileInfo) != 0) @@ -291,17 +291,17 @@ public: details.lastWriteTimeRaw = fileInfo.st_mtime; //UTC time(ANSI C format); unit: 1 second details.fileSize = fileInfo.st_size; - return m_sink->OnFile(filename, details); + return m_sink->OnFile(filename.c_str(), details); } - virtual wxDirTraverseResult OnDir(const wxString& dirname) + wxDirTraverseResult OnDir(const wxString& dirname) //virtual impl. { - return m_sink->OnDir(dirname); + return m_sink->OnDir(dirname.c_str()); } - virtual wxDirTraverseResult OnOpenError(const wxString& errorText) + wxDirTraverseResult OnOpenError(const wxString& errorText) //virtual impl. { - return m_sink->OnError(errorText); + return m_sink->OnError(errorText.c_str()); } private: @@ -322,7 +322,7 @@ bool FreeFileSync::traverseInDetail(const Zstring& directory, FullDetailFileTrav } Zstring directoryFormatted = directory; - if (!endsWithPathSeparator(directoryFormatted.c_str())) + if (!endsWithPathSeparator(directoryFormatted)) directoryFormatted += GlobalResources::FILE_NAME_SEPARATOR; const Zstring filespec = directoryFormatted + wxT("*.*"); @@ -403,10 +403,10 @@ bool FreeFileSync::traverseInDetail(const Zstring& directory, FullDetailFileTrav #elif defined FFS_LINUX //use standard file traverser and enrich output with additional file information - //could be improved with own traversing algorithm for optimized performance + //could be improved with custom traversing algorithm for optimized performance EnhancedFileTraverser traverser(sink); - wxDir dir(directory); + wxDir dir(directory.c_str()); if (dir.IsOpened()) dir.Traverse(traverser); diff --git a/library/fileHandling.h b/library/fileHandling.h index cd86333b..5578ce91 100644 --- a/library/fileHandling.h +++ b/library/fileHandling.h @@ -8,21 +8,21 @@ class FileError //Exception class used to notify file/directory copy/delete errors { public: - FileError(const wxString& txt) : errorMessage(txt) {} + FileError(const Zstring& txt) : errorMessage(txt) {} - wxString show() const + Zstring show() const { return errorMessage; } private: - wxString errorMessage; + Zstring errorMessage; }; namespace FreeFileSync { - void getAllFilesAndDirs(const Zstring& sourceDir, vector<Zstring>& files, vector<Zstring>& directories) throw(FileError); + void getAllFilesAndDirs(const Zstring& sourceDir, std::vector<Zstring>& files, std::vector<Zstring>& directories) throw(FileError); //recycler bool recycleBinExists(); //test existence of Recycle Bin API on current system diff --git a/library/globalFunctions.cpp b/library/globalFunctions.cpp index 7f8b57c0..eed6dfe9 100644 --- a/library/globalFunctions.cpp +++ b/library/globalFunctions.cpp @@ -11,27 +11,27 @@ int globalFunctions::round(const double d) } -string globalFunctions::numberToString(const unsigned int number) +std::string globalFunctions::numberToString(const unsigned int number) { char result[100]; sprintf(result, "%u", number); - return string(result); + return std::string(result); } -string globalFunctions::numberToString(const int number) +std::string globalFunctions::numberToString(const int number) { char result[100]; sprintf(result, "%d", number); - return string(result); + return std::string(result); } -string globalFunctions::numberToString(const float number) +std::string globalFunctions::numberToString(const float number) { char result[100]; sprintf(result, "%f", number); - return string(result); + return std::string(result); } @@ -53,14 +53,14 @@ wxString globalFunctions::numberToWxString(const float number) } -int globalFunctions::stringToInt(const string& number) +int globalFunctions::stringToInt(const std::string& number) { return atoi(number.c_str()); } inline -double globalFunctions::stringToDouble(const string& number) +double globalFunctions::stringToDouble(const std::string& number) { return atof(number.c_str()); } @@ -96,7 +96,7 @@ wxString& globalFunctions::includeNumberSeparator(wxString& number) } -int globalFunctions::readInt(ifstream& stream) +int globalFunctions::readInt(std::ifstream& stream) { int result = 0; char* buffer = reinterpret_cast<char*>(&result); @@ -105,7 +105,7 @@ int globalFunctions::readInt(ifstream& stream) } -void globalFunctions::writeInt(ofstream& stream, const int number) +void globalFunctions::writeInt(std::ofstream& stream, const int number) { const char* buffer = reinterpret_cast<const char*>(&number); stream.write(buffer, sizeof(int)); diff --git a/library/globalFunctions.h b/library/globalFunctions.h index f46a5906..b4ccba5c 100644 --- a/library/globalFunctions.h +++ b/library/globalFunctions.h @@ -10,8 +10,6 @@ #include <wx/stream.h> #include <wx/stopwatch.h> -using namespace std; - namespace globalFunctions { @@ -23,24 +21,24 @@ namespace globalFunctions return(d<0?-d:d); } - string numberToString(const unsigned int number); //convert number to string - string numberToString(const int number); //convert number to string - string numberToString(const float number); //convert number to string + std::string numberToString(const unsigned int number); //convert number to string + std::string numberToString(const int number); //convert number to string + std::string numberToString(const float number); //convert number to string 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 string& number); //convert String to number - double stringToDouble(const string& number); //convert String to number + int stringToInt( 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 wxString& includeNumberSeparator(wxString& number); - int readInt(ifstream& stream); //read int from file stream - void writeInt(ofstream& stream, const int number); //write int to filestream + int readInt(std::ifstream& stream); //read int from file stream + void writeInt(std::ofstream& stream, const int number); //write int to filestream int readInt(wxInputStream& stream); //read int from file stream void writeInt(wxOutputStream& stream, const int number); //write int to filestream @@ -108,12 +106,12 @@ private: //Note: the following lines are a performance optimization for deleting elements from a vector. It is incredibly faster to create a new //vector and leave specific elements out than to delete row by row and force recopying of most elements for each single deletion (linear vs quadratic runtime) template <class T> -void removeRowsFromVector(vector<T>& grid, const set<int>& rowsToRemove) +void removeRowsFromVector(std::vector<T>& grid, const std::set<int>& rowsToRemove) { - vector<T> temp; + std::vector<T> temp; int rowToSkip = -1; //keep it an INT! - set<int>::iterator rowToSkipIndex = rowsToRemove.begin(); + std::set<int>::iterator rowToSkipIndex = rowsToRemove.begin(); if (rowToSkipIndex != rowsToRemove.end()) rowToSkip = *rowToSkipIndex; diff --git a/library/misc.cpp b/library/misc.cpp index 050be108..f5c562c7 100644 --- a/library/misc.cpp +++ b/library/misc.cpp @@ -19,8 +19,7 @@ void exchangeEscapeChars(wxString& data) { //read next character ++input; - value = *input; - if (value == wxChar(0)) + if ((value = *input) == wxChar(0)) break; switch (value) @@ -60,23 +59,32 @@ void CustomLocale::setLanguage(const int language) { currentLanguage = language; - string languageFile; + std::string languageFile; switch (language) { - case wxLANGUAGE_GERMAN: - languageFile = "german.lng"; + case wxLANGUAGE_CHINESE_SIMPLIFIED: + languageFile = "Languages/chinese_simple.lng"; + break; + case wxLANGUAGE_DUTCH: + languageFile = "Languages/dutch.lng"; break; case wxLANGUAGE_FRENCH: - languageFile = "french.lng"; + languageFile = "Languages/french.lng"; + break; + case wxLANGUAGE_GERMAN: + languageFile = "Languages/german.lng"; + break; + case wxLANGUAGE_ITALIAN: + languageFile = "Languages/italian.lng"; break; case wxLANGUAGE_JAPANESE: - languageFile = "japanese.lng"; + languageFile = "Languages/japanese.lng"; break; - case wxLANGUAGE_DUTCH: - languageFile = "dutch.lng"; + case wxLANGUAGE_POLISH: + languageFile = "Languages/polish.lng"; break; - case wxLANGUAGE_CHINESE_SIMPLIFIED: - languageFile = "chinese_simple.lng"; + case wxLANGUAGE_PORTUGUESE: + languageFile = "Languages/portuguese.lng"; break; default: languageFile.clear(); @@ -96,7 +104,7 @@ void CustomLocale::setLanguage(const int language) char temp[bufferSize]; if (!languageFile.empty()) { - ifstream langFile(languageFile.c_str(), ios::binary); + std::ifstream langFile(languageFile.c_str(), std::ios::binary); if (langFile) { TranslationLine currentLine; diff --git a/library/misc.h b/library/misc.h index 5fa2c943..c3e960ff 100644 --- a/library/misc.h +++ b/library/misc.h @@ -6,7 +6,6 @@ #include <wx/intl.h> #include <wx/panel.h> -using namespace std; struct TranslationLine { @@ -26,7 +25,7 @@ struct TranslationLine return (original == b.original); } }; -typedef set<TranslationLine> Translation; +typedef std::set<TranslationLine> Translation; class CustomLocale : public wxLocale @@ -44,7 +43,7 @@ public: const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const; - static const string FfsLanguageDat; + static const std::string FfsLanguageDat; private: Translation translationDB; diff --git a/library/multithreading.cpp b/library/multithreading.cpp index bf5918d2..f7f5ed04 100644 --- a/library/multithreading.cpp +++ b/library/multithreading.cpp @@ -39,6 +39,7 @@ class WorkerThread : public wxThread public: WorkerThread(UpdateWhileExecuting* handler) : + wxThread(wxTHREAD_DETACHED), readyToBeginProcessing(), beginProcessing(readyToBeginProcessing), threadIsInitialized(false), diff --git a/library/processXml.cpp b/library/processXml.cpp index 04048124..80ac190b 100644 --- a/library/processXml.cpp +++ b/library/processXml.cpp @@ -8,16 +8,16 @@ using namespace globalFunctions; using namespace xmlAccess; //small helper functions -bool readXmlElementValue(string& output, const TiXmlElement* parent, const string& name); -bool readXmlElementValue(int& output, const TiXmlElement* parent, const string& name); -bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const string& name); -bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const string& name); -bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string& name); +bool readXmlElementValue(std::string& output, const TiXmlElement* parent, const std::string& name); +bool readXmlElementValue(int& output, const TiXmlElement* parent, const std::string& name); +bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const std::string& name); +bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const std::string& name); +bool readXmlElementValue(bool& output, const TiXmlElement* parent, const std::string& name); -void addXmlElement(TiXmlElement* parent, const string& name, const string& value); -void addXmlElement(TiXmlElement* parent, const string& name, const int value); -void addXmlElement(TiXmlElement* parent, const string& name, const SyncConfiguration::Direction value); -void addXmlElement(TiXmlElement* parent, const string& name, const bool value); +void addXmlElement(TiXmlElement* parent, const std::string& name, const std::string& value); +void addXmlElement(TiXmlElement* parent, const std::string& name, const int value); +void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncConfiguration::Direction value); +void addXmlElement(TiXmlElement* parent, const std::string& name, const bool value); class XmlConfigInput @@ -40,7 +40,7 @@ public: private: //read basic FreefileSync settings (used by commandline and GUI), return true if ALL values have been retrieved successfully - bool readXmlMainConfig(MainConfiguration& mainCfg, vector<FolderPair>& directoryPairs); + bool readXmlMainConfig(MainConfiguration& mainCfg, std::vector<FolderPair>& directoryPairs); TiXmlDocument doc; bool loadSuccess; @@ -56,15 +56,15 @@ public: bool writeToFile(); //write gui settings - bool writeXmlGuiConfig(const XmlGuiConfig& inputCfg); + bool writeXmlGuiConfig(const XmlGuiConfig& outputCfg); //write batch settings - bool writeXmlBatchConfig(const XmlBatchConfig& inputCfg); + bool writeXmlBatchConfig(const XmlBatchConfig& outputCfg); //write global settings - bool writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg); + bool writeXmlGlobalSettings(const XmlGlobalSettings& outputCfg); private: //write basic FreefileSync settings (used by commandline and GUI), return true if everything was written successfully - bool writeXmlMainConfig(const MainConfiguration& mainCfg, const vector<FolderPair>& directoryPairs); + bool writeXmlMainConfig(const MainConfiguration& mainCfg, const std::vector<FolderPair>& directoryPairs); TiXmlDocument doc; const wxString& m_fileName; @@ -89,18 +89,18 @@ XmlType xmlAccess::getXmlType(const wxString& filename) TiXmlElement* root = doc.RootElement(); - if (!root || (root->ValueStr() != string("FreeFileSync"))) //check for FFS configuration xml + if (!root || (root->ValueStr() != std::string("FreeFileSync"))) //check for FFS configuration xml return XML_OTHER; const char* cfgType = root->Attribute("XmlType"); if (!cfgType) return XML_OTHER; - if (string(cfgType) == "BATCH") + if (std::string(cfgType) == "BATCH") return XML_BATCH_CONFIG; - else if (string(cfgType) == "GUI") + else if (std::string(cfgType) == "GUI") return XML_GUI_CONFIG; - else if (string(cfgType) == "GLOBAL") + else if (std::string(cfgType) == "GLOBAL") return XML_GLOBAL_SETTINGS; else return XML_OTHER; @@ -115,10 +115,10 @@ XmlGuiConfig xmlAccess::readGuiConfig(const wxString& filename) XmlGuiConfig outputCfg; if (!inputFile.loadedSuccessfully()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); if (!inputFile.readXmlGuiConfig(outputCfg)) //read GUI layout configuration - throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); return outputCfg; } @@ -132,10 +132,10 @@ XmlBatchConfig xmlAccess::readBatchConfig(const wxString& filename) XmlBatchConfig outputCfg; if (!inputFile.loadedSuccessfully()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); if (!inputFile.readXmlBatchConfig(outputCfg)) - throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); return outputCfg; } @@ -149,47 +149,47 @@ XmlGlobalSettings xmlAccess::readGlobalSettings() XmlGlobalSettings outputCfg; if (!inputFile.loadedSuccessfully()) - throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\"")); + throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\"")); if (!inputFile.readXmlGlobalSettings(outputCfg)) - throw FileError(wxString(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\"")); + throw FileError(Zstring(_("Error parsing configuration file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\"")); return outputCfg; } -void xmlAccess::writeGuiConfig(const wxString& filename, const XmlGuiConfig& inputCfg) +void xmlAccess::writeGuiConfig(const wxString& filename, const XmlGuiConfig& outputCfg) { XmlConfigOutput outputFile(filename, XML_GUI_CONFIG); //populate and write XML tree - if ( !outputFile.writeXmlGuiConfig(inputCfg) || //add GUI layout configuration settings + if ( !outputFile.writeXmlGuiConfig(outputCfg) || //add GUI layout configuration settings !outputFile.writeToFile()) //save XML - throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); return; } -void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig& inputCfg) +void xmlAccess::writeBatchConfig(const wxString& filename, const XmlBatchConfig& outputCfg) { XmlConfigOutput outputFile(filename, XML_BATCH_CONFIG); //populate and write XML tree - if ( !outputFile.writeXmlBatchConfig(inputCfg) || //add GUI layout configuration settings + if ( !outputFile.writeXmlBatchConfig(outputCfg) || //add GUI layout configuration settings !outputFile.writeToFile()) //save XML - throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + filename + wxT("\"")); + throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + filename.c_str() + wxT("\"")); return; } -void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& inputCfg) +void xmlAccess::writeGlobalSettings(const XmlGlobalSettings& outputCfg) { XmlConfigOutput outputFile(FreeFileSync::GLOBAL_CONFIG_FILE, XML_GLOBAL_SETTINGS); //populate and write XML tree - if ( !outputFile.writeXmlGlobalSettings(inputCfg) || //add GUI layout configuration settings + if ( !outputFile.writeXmlGlobalSettings(outputCfg) || //add GUI layout configuration settings !outputFile.writeToFile()) //save XML - throw FileError(wxString(_("Error writing file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE + wxT("\"")); + throw FileError(Zstring(_("Error writing file:")) + wxT(" \"") + FreeFileSync::GLOBAL_CONFIG_FILE.c_str() + wxT("\"")); return; } @@ -212,17 +212,17 @@ XmlConfigInput::XmlConfigInput(const wxString& fileName, const XmlType type) : { TiXmlElement* root = doc.RootElement(); - if (root && (root->ValueStr() == string("FreeFileSync"))) //check for FFS configuration xml + if (root && (root->ValueStr() == std::string("FreeFileSync"))) //check for FFS configuration xml { const char* cfgType = root->Attribute("XmlType"); if (cfgType) { if (type == XML_GUI_CONFIG) - loadSuccess = string(cfgType) == "GUI"; + loadSuccess = std::string(cfgType) == "GUI"; else if (type == XML_BATCH_CONFIG) - loadSuccess = string(cfgType) == "BATCH"; + loadSuccess = std::string(cfgType) == "BATCH"; else if (type == XML_GLOBAL_SETTINGS) - loadSuccess = string(cfgType) == "GLOBAL"; + loadSuccess = std::string(cfgType) == "GLOBAL"; } } } @@ -230,7 +230,7 @@ XmlConfigInput::XmlConfigInput(const wxString& fileName, const XmlType type) : } -bool readXmlElementValue(string& output, const TiXmlElement* parent, const string& name) +bool readXmlElementValue(std::string& output, const TiXmlElement* parent, const std::string& name) { if (parent) { @@ -250,9 +250,9 @@ bool readXmlElementValue(string& output, const TiXmlElement* parent, const strin } -bool readXmlElementValue(int& output, const TiXmlElement* parent, const string& name) +bool readXmlElementValue(int& output, const TiXmlElement* parent, const std::string& name) { - string temp; + std::string temp; if (readXmlElementValue(temp, parent, name)) { output = stringToInt(temp); @@ -263,7 +263,7 @@ bool readXmlElementValue(int& output, const TiXmlElement* parent, const string& } -bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const string& name) +bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, const std::string& name) { int dummy = 0; if (readXmlElementValue(dummy, parent, name)) @@ -276,9 +276,9 @@ bool readXmlElementValue(CompareVariant& output, const TiXmlElement* parent, con } -bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const string& name) +bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElement* parent, const std::string& name) { - string dummy; + std::string dummy; if (readXmlElementValue(dummy, parent, name)) { if (dummy == "left") @@ -295,9 +295,9 @@ bool readXmlElementValue(SyncConfiguration::Direction& output, const TiXmlElemen } -bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string& name) +bool readXmlElementValue(bool& output, const TiXmlElement* parent, const std::string& name) { - string dummy; + std::string dummy; if (readXmlElementValue(dummy, parent, name)) { output = (dummy == "true"); @@ -308,7 +308,7 @@ bool readXmlElementValue(bool& output, const TiXmlElement* parent, const string& } -bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, vector<FolderPair>& directoryPairs) +bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, std::vector<FolderPair>& directoryPairs) { TiXmlElement* root = doc.RootElement(); if (!root) return false; @@ -323,7 +323,7 @@ bool XmlConfigInput::readXmlMainConfig(MainConfiguration& mainCfg, vector<Folder if (!cmpSettings || !syncConfig || !miscSettings || !filter) return false; - string tempString; + std::string tempString; //########################################################### //read compare variant if (!readXmlElementValue(mainCfg.compareVar, cmpSettings, "Variant")) return false; @@ -435,7 +435,7 @@ bool XmlConfigInput::readXmlGlobalSettings(XmlGlobalSettings& outputCfg) #ifdef FFS_WIN //daylight saving time check - readXmlElementValue(outputCfg.global.dstCheckActive, global, "DaylightSavingTimeCheckActive"); + readXmlElementValue(outputCfg.global.handleDstOnFat32, global, "HandleDaylightSavingTimeOnFAT"); #endif //folder dependency check @@ -453,50 +453,78 @@ bool XmlConfigInput::readXmlGlobalSettings(XmlGlobalSettings& outputCfg) readXmlElementValue(outputCfg.gui.isMaximized, mainWindow, "Maximized"); //########################################################### - //read column widths - TiXmlElement* leftColumn = TiXmlHandle(mainWindow).FirstChild("LeftColumns").FirstChild("Width").ToElement(); + //read column attributes + TiXmlElement* leftColumn = TiXmlHandle(mainWindow).FirstChild("LeftColumns").FirstChild("Column").ToElement(); + unsigned int colType = 0; while (leftColumn) { - const char* width = leftColumn->GetText(); - if (width) //may be NULL!! - outputCfg.gui.columnWidthLeft.push_back(stringToInt(width)); + const char* visible = leftColumn->Attribute("Visible"); + const char* position = leftColumn->Attribute("Position"); + const char* width = leftColumn->Attribute("Width"); + + if (visible && position && width) //may be NULL!! + { + XmlGlobalSettings::ColumnAttrib newAttrib; + newAttrib.type = XmlGlobalSettings::ColumnTypes(colType); + newAttrib.visible = std::string(visible) != std::string("false"); + newAttrib.position = stringToInt(position); + newAttrib.width = stringToInt(width); + outputCfg.gui.columnAttribLeft.push_back(newAttrib); + } else break; + leftColumn = leftColumn->NextSiblingElement(); + ++colType; } - TiXmlElement* rightColumn = TiXmlHandle(mainWindow).FirstChild("RightColumns").FirstChild("Width").ToElement(); + TiXmlElement* rightColumn = TiXmlHandle(mainWindow).FirstChild("RightColumns").FirstChild("Column").ToElement(); + colType = 0; while (rightColumn) { - const char* width = rightColumn->GetText(); - if (width) //may be NULL!! - outputCfg.gui.columnWidthRight.push_back(stringToInt(width)); + const char* visible = rightColumn->Attribute("Visible"); + const char* position = rightColumn->Attribute("Position"); + const char* width = rightColumn->Attribute("Width"); + + if (visible && position && width) //may be NULL!! + { + XmlGlobalSettings::ColumnAttrib newAttrib; + newAttrib.type = XmlGlobalSettings::ColumnTypes(colType); + newAttrib.visible = std::string(visible) != std::string("false"); + newAttrib.position = stringToInt(position); + newAttrib.width = stringToInt(width); + outputCfg.gui.columnAttribRight.push_back(newAttrib); + } else break; + rightColumn = rightColumn->NextSiblingElement(); + ++colType; } + } - //read column positions - TiXmlElement* leftColumnPos = TiXmlHandle(mainWindow).FirstChild("LeftColumnPositions").FirstChild("Position").ToElement(); - while (leftColumnPos) - { - const char* width = leftColumnPos->GetText(); - if (width) //may be NULL!! - outputCfg.gui.columnPositionsLeft.push_back(stringToInt(width)); - else - break; - leftColumnPos = leftColumnPos->NextSiblingElement(); - } + TiXmlElement* gui = hRoot.FirstChild("Gui").ToElement(); + if (gui) + { + //commandline for file manager integration + std::string tempString; + if (readXmlElementValue(tempString, gui, "FileManager")) + outputCfg.gui.commandLineFileManager = wxString::FromUTF8(tempString.c_str()); + } - TiXmlElement* rightColumnPos = TiXmlHandle(mainWindow).FirstChild("RightColumnPositions").FirstChild("Position").ToElement(); - while (rightColumnPos) + //load config file history + TiXmlElement* cfgHistory = hRoot.FirstChild("Gui").FirstChild("History").ToElement(); + if (cfgHistory) + { + TiXmlElement* cfgFile = TiXmlHandle(cfgHistory).FirstChild("File").ToElement(); + while (cfgFile) { - const char* width = rightColumnPos->GetText(); - if (width) //may be NULL!! - outputCfg.gui.columnPositionsRight.push_back(stringToInt(width)); + const char* fileName = cfgFile->GetText(); + if (fileName) //may be NULL!! + outputCfg.gui.cfgFileHistory.push_back(wxString::FromUTF8(fileName)); else break; - rightColumnPos = rightColumnPos->NextSiblingElement(); + cfgFile = cfgFile->NextSiblingElement(); } } @@ -546,7 +574,7 @@ bool XmlConfigOutput::writeToFile() } -void addXmlElement(TiXmlElement* parent, const string& name, const string& value) +void addXmlElement(TiXmlElement* parent, const std::string& name, const std::string& value) { if (parent) { @@ -557,35 +585,35 @@ void addXmlElement(TiXmlElement* parent, const string& name, const string& value } -void addXmlElement(TiXmlElement* parent, const string& name, const int value) +void addXmlElement(TiXmlElement* parent, const std::string& name, const int value) { addXmlElement(parent, name, numberToString(value)); } -void addXmlElement(TiXmlElement* parent, const string& name, const SyncConfiguration::Direction value) +void addXmlElement(TiXmlElement* parent, const std::string& name, const SyncConfiguration::Direction value) { if (value == SyncConfiguration::SYNC_DIR_LEFT) - addXmlElement(parent, name, string("left")); + addXmlElement(parent, name, std::string("left")); else if (value == SyncConfiguration::SYNC_DIR_RIGHT) - addXmlElement(parent, name, string("right")); + addXmlElement(parent, name, std::string("right")); else if (value == SyncConfiguration::SYNC_DIR_NONE) - addXmlElement(parent, name, string("none")); + addXmlElement(parent, name, std::string("none")); else assert(false); } -void addXmlElement(TiXmlElement* parent, const string& name, const bool value) +void addXmlElement(TiXmlElement* parent, const std::string& name, const bool value) { if (value) - addXmlElement(parent, name, string("true")); + addXmlElement(parent, name, std::string("true")); else - addXmlElement(parent, name, string("false")); + addXmlElement(parent, name, std::string("false")); } -bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const vector<FolderPair>& directoryPairs) +bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const std::vector<FolderPair>& directoryPairs) { TiXmlElement* root = doc.RootElement(); if (!root) return false; @@ -605,13 +633,13 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const cmpSettings->LinkEndChild(folders); //write folder pairs - for (vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i) + for (std::vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i) { TiXmlElement* folderPair = new TiXmlElement("Pair"); folders->LinkEndChild(folderPair); - addXmlElement(folderPair, "Left", string(wxString(i->leftDirectory.c_str()).ToUTF8())); - addXmlElement(folderPair, "Right", string(wxString(i->rightDirectory.c_str()).ToUTF8())); + addXmlElement(folderPair, "Left", std::string(wxString(i->leftDirectory.c_str()).ToUTF8())); + addXmlElement(folderPair, "Right", std::string(wxString(i->rightDirectory.c_str()).ToUTF8())); } //########################################################### @@ -637,8 +665,8 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const miscSettings->LinkEndChild(filter); addXmlElement(filter, "Active", mainCfg.filterIsActive); - addXmlElement(filter, "Include", string((mainCfg.includeFilter).ToUTF8())); - addXmlElement(filter, "Exclude", string((mainCfg.excludeFilter).ToUTF8())); + addXmlElement(filter, "Include", std::string((mainCfg.includeFilter).ToUTF8())); + addXmlElement(filter, "Exclude", std::string((mainCfg.excludeFilter).ToUTF8())); //other addXmlElement(miscSettings, "UseRecycler", mainCfg.useRecycleBin); @@ -649,10 +677,10 @@ bool XmlConfigOutput::writeXmlMainConfig(const MainConfiguration& mainCfg, const } -bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& inputCfg) +bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& outputCfg) { //write main config - if (!writeXmlMainConfig(inputCfg.mainCfg, inputCfg.directoryPairs)) + if (!writeXmlMainConfig(outputCfg.mainCfg, outputCfg.directoryPairs)) return false; //write GUI specific config @@ -668,16 +696,16 @@ bool XmlConfigOutput::writeXmlGuiConfig(const XmlGuiConfig& inputCfg) TiXmlElement* mainWindow = new TiXmlElement("Main"); windows->LinkEndChild(mainWindow); - addXmlElement(mainWindow, "HideFiltered", inputCfg.hideFilteredElements); + addXmlElement(mainWindow, "HideFiltered", outputCfg.hideFilteredElements); return true; } -bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& inputCfg) +bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& outputCfg) { //write main config - if (!writeXmlMainConfig(inputCfg.mainCfg, inputCfg.directoryPairs)) + if (!writeXmlMainConfig(outputCfg.mainCfg, outputCfg.directoryPairs)) return false; //write GUI specific config @@ -687,13 +715,13 @@ bool XmlConfigOutput::writeXmlBatchConfig(const XmlBatchConfig& inputCfg) TiXmlElement* batchConfig = new TiXmlElement("BatchConfig"); root->LinkEndChild(batchConfig); - addXmlElement(batchConfig, "Silent", inputCfg.silent); + addXmlElement(batchConfig, "Silent", outputCfg.silent); return true; } -bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg) +bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& outputCfg) { TiXmlElement* root = doc.RootElement(); if (!root) return false; @@ -704,64 +732,83 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg) root->LinkEndChild(global); //program language - addXmlElement(global, "Language", inputCfg.global.programLanguage); + addXmlElement(global, "Language", outputCfg.global.programLanguage); #ifdef FFS_WIN //daylight saving time check - addXmlElement(global, "DaylightSavingTimeCheckActive", inputCfg.global.dstCheckActive); + addXmlElement(global, "HandleDaylightSavingTimeOnFAT", outputCfg.global.handleDstOnFat32); #endif //folder dependency check - addXmlElement(global, "FolderDependencyCheckActive", inputCfg.global.folderDependCheckActive); + addXmlElement(global, "FolderDependencyCheckActive", outputCfg.global.folderDependCheckActive); + //################################################################### - //write gui settings - TiXmlElement* guiLayout = new TiXmlElement("Gui"); - root->LinkEndChild(guiLayout); + //write global gui settings + TiXmlElement* gui = new TiXmlElement("Gui"); + root->LinkEndChild(gui); TiXmlElement* windows = new TiXmlElement("Windows"); - guiLayout->LinkEndChild(windows); + gui->LinkEndChild(windows); TiXmlElement* mainWindow = new TiXmlElement("Main"); windows->LinkEndChild(mainWindow); //window size - addXmlElement(mainWindow, "Width", inputCfg.gui.widthNotMaximized); - addXmlElement(mainWindow, "Height", inputCfg.gui.heightNotMaximized); + addXmlElement(mainWindow, "Width", outputCfg.gui.widthNotMaximized); + addXmlElement(mainWindow, "Height", outputCfg.gui.heightNotMaximized); //window position - addXmlElement(mainWindow, "PosX", inputCfg.gui.posXNotMaximized); - addXmlElement(mainWindow, "PosY", inputCfg.gui.posYNotMaximized); - addXmlElement(mainWindow, "Maximized", inputCfg.gui.isMaximized); + addXmlElement(mainWindow, "PosX", outputCfg.gui.posXNotMaximized); + addXmlElement(mainWindow, "PosY", outputCfg.gui.posYNotMaximized); + addXmlElement(mainWindow, "Maximized", outputCfg.gui.isMaximized); - //write column sizes + //write column attributes TiXmlElement* leftColumn = new TiXmlElement("LeftColumns"); mainWindow->LinkEndChild(leftColumn); - - for (unsigned int i = 0; i < inputCfg.gui.columnWidthLeft.size(); ++i) - addXmlElement(leftColumn, "Width", inputCfg.gui.columnWidthLeft[i]); + XmlGlobalSettings::ColumnAttributes columnAtrribLeftCopy = outputCfg.gui.columnAttribLeft; //can't change const vector + sort(columnAtrribLeftCopy.begin(), columnAtrribLeftCopy.end(), xmlAccess::sortByType); + for (unsigned int i = 0; i < columnAtrribLeftCopy.size(); ++i) + { + TiXmlElement* subElement = new TiXmlElement("Column"); + leftColumn->LinkEndChild(subElement); + + const XmlGlobalSettings::ColumnAttrib& colAttrib = columnAtrribLeftCopy[i]; + if (colAttrib.visible) subElement->SetAttribute("Visible", "true"); + else subElement->SetAttribute("Visible", "false"); + subElement->SetAttribute("Position", colAttrib.position); + subElement->SetAttribute("Width", colAttrib.width); + } TiXmlElement* rightColumn = new TiXmlElement("RightColumns"); mainWindow->LinkEndChild(rightColumn); + XmlGlobalSettings::ColumnAttributes columnAtrribRightCopy = outputCfg.gui.columnAttribRight; + sort(columnAtrribRightCopy.begin(), columnAtrribRightCopy.end(), xmlAccess::sortByType); + for (unsigned int i = 0; i < columnAtrribRightCopy.size(); ++i) + { + TiXmlElement* subElement = new TiXmlElement("Column"); + rightColumn->LinkEndChild(subElement); + + const XmlGlobalSettings::ColumnAttrib& colAttrib = columnAtrribRightCopy[i]; + if (colAttrib.visible) subElement->SetAttribute("Visible", "true"); + else subElement->SetAttribute("Visible", "false"); + subElement->SetAttribute("Position", colAttrib.position); + subElement->SetAttribute("Width", colAttrib.width); + } - for (unsigned int i = 0; i < inputCfg.gui.columnWidthRight.size(); ++i) - addXmlElement(rightColumn, "Width", inputCfg.gui.columnWidthRight[i]); - - //write column positions - TiXmlElement* leftColumnPos = new TiXmlElement("LeftColumnPositions"); - mainWindow->LinkEndChild(leftColumnPos); + //commandline for file manager integration + addXmlElement(gui, "FileManager", std::string((outputCfg.gui.commandLineFileManager).ToUTF8())); - for (unsigned int i = 0; i < inputCfg.gui.columnPositionsLeft.size(); ++i) - addXmlElement(leftColumnPos, "Position", inputCfg.gui.columnPositionsLeft[i]); + //write config file history + TiXmlElement* cfgHistory = new TiXmlElement("History"); + gui->LinkEndChild(cfgHistory); - TiXmlElement* rightColumnPos = new TiXmlElement("RightColumnPositions"); - mainWindow->LinkEndChild(rightColumnPos); + for (unsigned int i = 0; i < outputCfg.gui.cfgFileHistory.size(); ++i) + addXmlElement(cfgHistory, "File", std::string(outputCfg.gui.cfgFileHistory[i].ToUTF8())); - for (unsigned int i = 0; i < inputCfg.gui.columnPositionsRight.size(); ++i) - addXmlElement(rightColumnPos, "Position", inputCfg.gui.columnPositionsRight[i]); //################################################################### - //write batch settings + //write global batch settings TiXmlElement* batch = new TiXmlElement("Batch"); root->LinkEndChild(batch); @@ -770,12 +817,13 @@ bool XmlConfigOutput::writeXmlGlobalSettings(const XmlGlobalSettings& inputCfg) } -int xmlAccess::retrieveSystemLanguage() //map language dialects +int xmlAccess::retrieveSystemLanguage() { const int lang = wxLocale::GetSystemLanguage(); - switch (lang) + switch (lang) //map language dialects { + //variants of wxLANGUAGE_GERMAN case wxLANGUAGE_GERMAN_AUSTRIAN: case wxLANGUAGE_GERMAN_BELGIUM: case wxLANGUAGE_GERMAN_LIECHTENSTEIN: @@ -783,6 +831,7 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects case wxLANGUAGE_GERMAN_SWISS: return wxLANGUAGE_GERMAN; + //variants of wxLANGUAGE_FRENCH case wxLANGUAGE_FRENCH_BELGIAN: case wxLANGUAGE_FRENCH_CANADIAN: case wxLANGUAGE_FRENCH_LUXEMBOURG: @@ -790,11 +839,15 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects case wxLANGUAGE_FRENCH_SWISS: return wxLANGUAGE_FRENCH; - //case wxLANGUAGE_JAPANESE: - + //variants of wxLANGUAGE_DUTCH case wxLANGUAGE_DUTCH_BELGIAN: return wxLANGUAGE_DUTCH; + //variants of wxLANGUAGE_ITALIAN + case wxLANGUAGE_ITALIAN_SWISS: + return wxLANGUAGE_ITALIAN; + + //variants of wxLANGUAGE_CHINESE_SIMPLIFIED case wxLANGUAGE_CHINESE: case wxLANGUAGE_CHINESE_TRADITIONAL: case wxLANGUAGE_CHINESE_HONGKONG: @@ -803,7 +856,16 @@ int xmlAccess::retrieveSystemLanguage() //map language dialects case wxLANGUAGE_CHINESE_TAIWAN: return wxLANGUAGE_CHINESE_SIMPLIFIED; + //variants of wxLANGUAGE_PORTUGUESE + case wxLANGUAGE_PORTUGUESE_BRAZILIAN: + return wxLANGUAGE_PORTUGUESE; + + //case wxLANGUAGE_JAPANESE: + //case wxLANGUAGE_POLISH: + + default: + //all the rest: wxLANGUAGE_ENGLISH; return lang; } } diff --git a/library/processXml.h b/library/processXml.h index bc81556e..5f3f8ef9 100644 --- a/library/processXml.h +++ b/library/processXml.h @@ -25,7 +25,7 @@ namespace xmlAccess XmlGuiConfig() : hideFilteredElements(false) {} //initialize values MainConfiguration mainCfg; - vector<FolderPair> directoryPairs; + std::vector<FolderPair> directoryPairs; bool hideFilteredElements; }; @@ -36,31 +36,53 @@ namespace xmlAccess XmlBatchConfig() : silent(false) {} MainConfiguration mainCfg; - vector<FolderPair> directoryPairs; + std::vector<FolderPair> directoryPairs; bool silent; }; int retrieveSystemLanguage(); + struct XmlGlobalSettings { +//--------------------------------------------------------------------- +//internal structures: + enum ColumnTypes + { + FILENAME = 0, + REL_PATH, + SIZE, + DATE + }; + + struct ColumnAttrib + { + ColumnTypes type; + bool visible; + unsigned position; + int width; + }; + typedef std::vector<ColumnAttrib> ColumnAttributes; + +//--------------------------------------------------------------------- struct _Global { _Global() : programLanguage(retrieveSystemLanguage()), #ifdef FFS_WIN - dstCheckActive(true), + handleDstOnFat32(true), #endif folderDependCheckActive(true) {} int programLanguage; #ifdef FFS_WIN - bool dstCheckActive; + bool handleDstOnFat32; #endif bool folderDependCheckActive; } global; +//--------------------------------------------------------------------- struct _Gui { _Gui() : @@ -68,30 +90,63 @@ namespace xmlAccess heightNotMaximized(wxDefaultCoord), posXNotMaximized(wxDefaultCoord), posYNotMaximized(wxDefaultCoord), - isMaximized(false) {} + isMaximized(false), +#ifdef FFS_WIN + commandLineFileManager(wxT("explorer /select, %x")) +#elif defined FFS_LINUX + commandLineFileManager(wxT("konqueror \"%path\"")) +#endif + {} int widthNotMaximized; int heightNotMaximized; int posXNotMaximized; int posYNotMaximized; bool isMaximized; - vector<int> columnWidthLeft; - vector<int> columnWidthRight; - vector<int> columnPositionsLeft; - vector<int> columnPositionsRight; + + ColumnAttributes columnAttribLeft; + ColumnAttributes columnAttribRight; + std::vector<wxString> cfgFileHistory; + wxString commandLineFileManager; } gui; +//--------------------------------------------------------------------- //struct _Batch }; + inline + bool sortByType(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::ColumnAttrib& b) + { + return a.type < b.type; + } + + + inline + bool sortByPositionOnly(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::ColumnAttrib& b) + { + return a.position < b.position; + } + + + inline + bool sortByPositionAndVisibility(const XmlGlobalSettings::ColumnAttrib& a, const XmlGlobalSettings::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; + } + + XmlGuiConfig readGuiConfig(const wxString& filename); XmlBatchConfig readBatchConfig(const wxString& filename); XmlGlobalSettings readGlobalSettings(); //used for both GUI and batch mode, independent from configuration instance - void writeGuiConfig(const wxString& filename, const XmlGuiConfig& inputCfg); - void writeBatchConfig(const wxString& filename, const XmlBatchConfig& inputCfg); - void writeGlobalSettings(const XmlGlobalSettings& inputCfg); + void writeGuiConfig(const wxString& filename, const XmlGuiConfig& outputCfg); + void writeBatchConfig(const wxString& filename, const XmlBatchConfig& outputCfg); + void writeGlobalSettings(const XmlGlobalSettings& outputCfg); } diff --git a/library/resources.cpp b/library/resources.cpp index 9169bf85..c60c259c 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -92,6 +92,12 @@ GlobalResources::GlobalResources() bitmapResource[wxT("filter.png")] = (bitmapFilter = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("batch.png")] = (bitmapBatch = new wxBitmap(wxNullBitmap)); bitmapResource[wxT("batch_small.png")] = (bitmapBatchSmall = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("move up.png")] = (bitmapMoveUp = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("move down.png")] = (bitmapMoveDown = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("checkbox true.png")] = (bitmapCheckBoxTrue = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("checkbox false.png")] = (bitmapCheckBoxFalse = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("settings.png")] = (bitmapSettings = new wxBitmap(wxNullBitmap)); + bitmapResource[wxT("settings_small.png")] = (bitmapSettingsSmall = new wxBitmap(wxNullBitmap)); //init all the other resource files animationMoney = new wxAnimation(wxNullAnimation); @@ -102,7 +108,7 @@ GlobalResources::GlobalResources() GlobalResources::~GlobalResources() { //free bitmap resources - for (map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i) + for (std::map<wxString, wxBitmap*>::iterator i = bitmapResource.begin(); i != bitmapResource.end(); ++i) delete i->second; //free other resources @@ -117,7 +123,7 @@ void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation* animation) //Workaround for wxWidgets: //construct seekable input stream (zip-input stream is non-seekable) for wxAnimation::Load() //luckily this method call is very fast: below measurement precision! - vector<unsigned char> data; + std::vector<unsigned char> data; data.reserve(10000); int newValue = 0; @@ -141,7 +147,7 @@ void GlobalResources::load() wxZipInputStream resourceFile(input); wxZipEntry* entry = NULL; - map<wxString, wxBitmap*>::iterator bmp; + std::map<wxString, wxBitmap*>::iterator bmp; while ((entry = resourceFile.GetNextEntry())) { wxString name = entry->GetName(); diff --git a/library/resources.h b/library/resources.h index d08ce0ce..4eec185e 100644 --- a/library/resources.h +++ b/library/resources.h @@ -6,7 +6,6 @@ #include <wx/string.h> #include <map> -using namespace std; class GlobalResources { @@ -92,6 +91,12 @@ public: wxBitmap* bitmapFilter; wxBitmap* bitmapBatch; wxBitmap* bitmapBatchSmall; + wxBitmap* bitmapMoveUp; + wxBitmap* bitmapMoveDown; + wxBitmap* bitmapCheckBoxTrue; + wxBitmap* bitmapCheckBoxFalse; + wxBitmap* bitmapSettings; + wxBitmap* bitmapSettingsSmall; wxAnimation* animationMoney; wxAnimation* animationSync; @@ -100,7 +105,7 @@ public: private: //resource mapping - map<wxString, wxBitmap*> bitmapResource; + std::map<wxString, wxBitmap*> bitmapResource; }; diff --git a/library/sorting.h b/library/sorting.h index 560e246a..fabdad1f 100644 --- a/library/sorting.h +++ b/library/sorting.h @@ -5,6 +5,7 @@ #include "resources.h" #include "globalFunctions.h" +using namespace FreeFileSync; enum SideToSort { @@ -115,11 +116,11 @@ bool sortByFileName(const FileCompareLine& a, const FileCompareLine& b) const wxChar* stringB = descrLineB->relativeName.c_str(); size_t pos = descrLineA->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end - if (pos != string::npos) + if (pos != std::string::npos) stringA += pos + 1; pos = descrLineB->relativeName.Find(GlobalResources::FILE_NAME_SEPARATOR, true); //start search beginning from end - if (pos != string::npos) + if (pos != std::string::npos) stringB += pos + 1; return stringSmallerThan<sortAscending>(stringA, stringB); @@ -250,4 +251,20 @@ bool sortByDate(const FileCompareLine& a, const FileCompareLine& b) } +template <bool sortAscending> +inline +bool sortByCmpResult(const FileCompareLine& a, const FileCompareLine& b) +{ + //presort result: equal shall appear at end of list + if (a.cmpResult == FILE_EQUAL) + return false; + if (b.cmpResult == FILE_EQUAL) + return true; + + return sortAscending ? + a.cmpResult < b.cmpResult : + a.cmpResult > b.cmpResult; +} + + #endif // SORTING_H_INCLUDED diff --git a/library/statusHandler.h b/library/statusHandler.h index 4c12035d..bae1de8e 100644 --- a/library/statusHandler.h +++ b/library/statusHandler.h @@ -1,7 +1,7 @@ #ifndef STATUSHANDLER_H_INCLUDED #define STATUSHANDLER_H_INCLUDED -#include <wx/string.h> +#include "zstring.h" const int UI_UPDATE_INTERVAL = 100; //perform ui updates not more often than necessary, 100 seems to be a good value with only a minimal performance loss @@ -24,7 +24,7 @@ public: IGNORE_ERROR = 10, RETRY }; - virtual Response reportError(const wxString& text) = 0; + virtual Response reportError(const Zstring& text) = 0; }; @@ -45,10 +45,10 @@ public: }; //these methods have to be implemented in the derived classes to handle error and status information - virtual void updateStatusText(const wxString& text) = 0; + virtual void updateStatusText(const Zstring& text) = 0; virtual void initNewProcess(int objectsTotal, double dataTotal, Process processID) = 0; //informs about the total amount of data that will be processed from now on virtual void updateProcessedData(int objectsProcessed, double dataProcessed) = 0; //called periodically after data was processed - virtual ErrorHandler::Response reportError(const wxString& text) = 0; + virtual ErrorHandler::Response reportError(const Zstring& text) = 0; //this method is triggered repeatedly by requestUiRefresh() and can be used to refresh the ui by dispatching pending events virtual void forceUiRefresh() = 0; diff --git a/library/zstring.cpp b/library/zstring.cpp index b84c9512..35704b01 100644 --- a/library/zstring.cpp +++ b/library/zstring.cpp @@ -44,14 +44,14 @@ int FreeFileSync::compareStringsWin32(const wchar_t* a, const wchar_t* b, const bCount); //size, in bytes or characters, of second string if (rv == 0) - throw RuntimeException(wxString(_("Error comparing strings!"))); + throw RuntimeException(wxString(wxT("Error comparing strings!"))); else return rv - 2; } #endif -size_t Zstring::Replace(const defaultChar* old, const defaultChar* replacement, bool replaceAll) +size_t Zstring::Replace(const DefaultChar* old, const DefaultChar* replacement, bool replaceAll) { const size_t oldLen = defaultLength(old); const size_t replacementLen = defaultLength(replacement); @@ -77,29 +77,29 @@ size_t Zstring::Replace(const defaultChar* old, const defaultChar* replacement, } -bool matchesHelper(const defaultChar* string, const defaultChar* mask) +bool matchesHelper(const DefaultChar* string, const DefaultChar* mask) { - for (defaultChar ch; (ch = *mask) != 0; ++mask) + for (DefaultChar ch; (ch = *mask) != 0; ++mask) { switch (ch) { - case defaultChar('?'): + case DefaultChar('?'): if (*string == 0) return false; else ++string; break; - case defaultChar('*'): + case DefaultChar('*'): //advance to next non-*/? char do { ++mask; ch = *mask; } - while (ch == defaultChar('*') || ch == defaultChar('?')); + while (ch == DefaultChar('*') || ch == DefaultChar('?')); //if match ends with '*': - if (ch == defaultChar(0)) + if (ch == DefaultChar(0)) return true; ++mask; @@ -123,7 +123,7 @@ bool matchesHelper(const defaultChar* string, const defaultChar* mask) } -bool Zstring::Matches(const defaultChar* mask) const +bool Zstring::Matches(const DefaultChar* mask) const { return matchesHelper(c_str(), mask); } @@ -137,7 +137,7 @@ Zstring& Zstring::Trim(bool fromRight) if (fromRight) { - const defaultChar* cursor = data + thisLen - 1; + const DefaultChar* cursor = data + thisLen - 1; while (cursor != data - 1 && defaultIsWhiteSpace(*cursor)) //break when pointing one char further than last skipped element --cursor; ++cursor; @@ -153,8 +153,8 @@ Zstring& Zstring::Trim(bool fromRight) } else { - defaultChar* cursor = data; - defaultChar ch; + DefaultChar* cursor = data; + DefaultChar ch; while ((ch = *cursor) != 0 && defaultIsWhiteSpace(ch)) ++cursor; @@ -185,7 +185,7 @@ Zstring& Zstring::MakeLower() if (descr->refCount > 1) //allocate new string { StringDescriptor* newDescr; - defaultChar* newData; + DefaultChar* newData; const size_t newCapacity = getCapacityToAllocate(thisLen); allocate(1, thisLen, newCapacity, newDescr, newData); @@ -224,7 +224,7 @@ Zstring Zstring::substr(size_t pos, size_t len) const } -size_t Zstring::rfind(const defaultChar ch, size_t pos) const +size_t Zstring::rfind(const DefaultChar ch, size_t pos) const { const size_t thisLen = length(); if (thisLen == 0) @@ -245,7 +245,7 @@ size_t Zstring::rfind(const defaultChar ch, size_t pos) const } -Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t n2) +Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t n2) { assert(str < c_str() || c_str() + length() < str); //str mustn't point to data in this string assert(n1 <= length() - pos1); @@ -265,15 +265,15 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t const size_t newCapacity = getCapacityToAllocate(newLen); StringDescriptor* newDescr; - defaultChar* newData; + DefaultChar* newData; allocate(1, newLen, newCapacity, newDescr, newData); //StringDescriptor* newDescr = new StringDescriptor(1, newLen, newCapacity); - //defaultChar* newData = new defaultChar[newCapacity + 1]; + //DefaultChar* newData = new DefaultChar[newCapacity + 1]; //assemble new string with replacement - memcpy(newData, data, pos1 * sizeof(defaultChar)); - memcpy(newData + pos1, str, n2 * sizeof(defaultChar)); - memcpy(newData + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(defaultChar)); + memcpy(newData, data, pos1 * sizeof(DefaultChar)); + memcpy(newData + pos1, str, n2 * sizeof(DefaultChar)); + memcpy(newData + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(DefaultChar)); newData[newLen] = 0; decRef(); @@ -282,10 +282,10 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t } else { //overwrite current string - memcpy(data + pos1, str, n2 * sizeof(defaultChar)); + memcpy(data + pos1, str, n2 * sizeof(DefaultChar)); if (n1 > n2) { - memmove(data + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(defaultChar)); + memmove(data + pos1 + n2, data + pos1 + n1, (oldLen - pos1 - n1) * sizeof(DefaultChar)); data[newLen] = 0; descr->length = newLen; } @@ -295,7 +295,7 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const defaultChar* str, size_t } -Zstring& Zstring::operator=(const defaultChar* source) +Zstring& Zstring::operator=(const DefaultChar* source) { const size_t sourceLen = defaultLength(source); if (sourceLen == 0) @@ -305,7 +305,7 @@ Zstring& Zstring::operator=(const defaultChar* source) *this = Zstring(source, sourceLen); else { //overwrite this string - memcpy(data, source, sourceLen * sizeof(defaultChar)); + memcpy(data, source, sourceLen * sizeof(DefaultChar)); data[sourceLen] = 0; descr->length = sourceLen; } @@ -322,7 +322,7 @@ Zstring& Zstring::operator+=(const Zstring& other) const size_t newLen = thisLen + otherLen; copyBeforeWrite(newLen); - memcpy(data + thisLen, other.c_str(), otherLen * sizeof(defaultChar)); + memcpy(data + thisLen, other.c_str(), otherLen * sizeof(DefaultChar)); data[newLen] = 0; descr->length = newLen; } @@ -330,7 +330,7 @@ Zstring& Zstring::operator+=(const Zstring& other) } -Zstring& Zstring::operator+=(const defaultChar* other) +Zstring& Zstring::operator+=(const DefaultChar* other) { const size_t otherLen = defaultLength(other); if (otherLen != 0) @@ -339,7 +339,7 @@ Zstring& Zstring::operator+=(const defaultChar* other) const size_t newLen = thisLen + otherLen; copyBeforeWrite(newLen); - memcpy(data + thisLen, other, otherLen * sizeof(defaultChar)); + memcpy(data + thisLen, other, otherLen * sizeof(DefaultChar)); data[newLen] = 0; descr->length = newLen; } @@ -347,7 +347,7 @@ Zstring& Zstring::operator+=(const defaultChar* other) } -Zstring& Zstring::operator+=(defaultChar ch) +Zstring& Zstring::operator+=(DefaultChar ch) { const size_t oldLen = length(); copyBeforeWrite(oldLen + 1); @@ -368,15 +368,13 @@ void Zstring::copyBeforeWrite(const size_t capacityNeeded) const size_t newCapacity = getCapacityToAllocate(capacityNeeded); StringDescriptor* newDescr; - defaultChar* newData; + DefaultChar* newData; allocate(1, oldLength, newCapacity, newDescr, newData); - //StringDescriptor* newDescr = new StringDescriptor(1, oldLength, newCapacity); - //defaultChar* newData = new defaultChar[newCapacity + 1]; if (oldLength) { assert(oldLength <= newCapacity); - memcpy(newData, data, oldLength * sizeof(defaultChar)); + memcpy(newData, data, oldLength * sizeof(DefaultChar)); newData[oldLength] = 0; } decRef(); @@ -387,10 +385,10 @@ void Zstring::copyBeforeWrite(const size_t capacityNeeded) { //try to resize the current string (allocate anew if necessary) const size_t newCapacity = getCapacityToAllocate(capacityNeeded); - descr = (StringDescriptor*) realloc(descr, sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(defaultChar)); + descr = (StringDescriptor*) realloc(descr, sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar)); if (descr == NULL) - throw; //std::bad_alloc& e - data = (defaultChar*)(descr + 1); + throw std::bad_alloc(); + data = (DefaultChar*)(descr + 1); descr->capacity = newCapacity; } } diff --git a/library/zstring.h b/library/zstring.h index 00590d4f..9013dd22 100644 --- a/library/zstring.h +++ b/library/zstring.h @@ -7,7 +7,8 @@ #ifndef ZSTRING_H_INCLUDED #define ZSTRING_H_INCLUDED -#include <wx/string.h> +#include <string> + namespace FreeFileSync { @@ -18,6 +19,7 @@ namespace FreeFileSync #endif //FFS_WIN } + #ifdef FFS_WIN #define ZSTRING_WIDE_CHAR //use wide character strings @@ -27,89 +29,93 @@ namespace FreeFileSync #ifdef ZSTRING_CHAR -typedef char defaultChar; +typedef char DefaultChar; #elif defined ZSTRING_WIDE_CHAR -typedef wchar_t defaultChar; +typedef wchar_t DefaultChar; #endif + class Zstring { public: Zstring(); - Zstring(const defaultChar* source); //string is copied: O(length) - Zstring(const defaultChar* source, size_t length); //string is copied: O(length) + Zstring(const DefaultChar* source); //string is copied: O(length) + Zstring(const DefaultChar* source, size_t length); //string is copied: O(length) Zstring(const Zstring& source); //reference-counting => O(1) - Zstring(const wxString& source); //string is copied: O(length) ~Zstring(); - operator const defaultChar*() const; //implicit conversion to C string - operator const wxString() const; //implicit conversion to wxString + operator const DefaultChar*() const; //implicit conversion to C string //wxWidgets functions - bool StartsWith(const defaultChar* begin) const; + bool StartsWith(const DefaultChar* begin) const; bool StartsWith(const Zstring& begin) const; - bool EndsWith(const defaultChar* end) const; + bool EndsWith(const DefaultChar* end) const; bool EndsWith(const Zstring& end) const; #ifdef FFS_WIN - int CmpNoCase(const defaultChar* other) const; + int CmpNoCase(const DefaultChar* other) const; int CmpNoCase(const Zstring& other) const; #endif - int Cmp(const defaultChar* other) const; + int Cmp(const DefaultChar* other) const; int Cmp(const Zstring& other) const; - size_t Replace(const defaultChar* old, const defaultChar* replacement, bool replaceAll = true); - Zstring AfterLast(defaultChar ch) const; - Zstring BeforeLast(defaultChar ch) const; - size_t Find(defaultChar ch, bool fromEnd) const; - bool Matches(const defaultChar* mask) const; + size_t Replace(const DefaultChar* old, const DefaultChar* replacement, bool replaceAll = true); + Zstring AfterLast(DefaultChar ch) const; + Zstring BeforeLast(DefaultChar ch) const; + size_t Find(DefaultChar ch, bool fromEnd) const; + bool Matches(const DefaultChar* mask) const; Zstring& Trim(bool fromRight); //from right or left Zstring& MakeLower(); //std::string functions size_t length() const; - const defaultChar* c_str() const; + const DefaultChar* c_str() const; Zstring substr(size_t pos = 0, size_t len = npos) const; bool empty() const; - int compare(const defaultChar* other) const; + int compare(const DefaultChar* other) const; int compare(const Zstring& other) const; - int compare(const size_t pos1, const size_t n1, const defaultChar* other) const; - size_t find(const defaultChar* str, const size_t pos = 0 ) const; - size_t find(const defaultChar ch, const size_t pos = 0) const; - size_t rfind(const defaultChar ch, size_t pos = npos) const; - Zstring& replace(size_t pos1, size_t n1, const defaultChar* str, size_t n2); + int compare(const size_t pos1, const size_t n1, const DefaultChar* other) const; + size_t find(const DefaultChar* str, const size_t pos = 0 ) const; + size_t find(const DefaultChar ch, const size_t pos = 0) const; + size_t rfind(const DefaultChar ch, size_t pos = npos) const; + Zstring& replace(size_t pos1, size_t n1, const DefaultChar* str, size_t n2); + size_t size() const; Zstring& operator=(const Zstring& source); - Zstring& operator=(const defaultChar* source); + Zstring& operator=(const DefaultChar* source); bool operator==(const Zstring& other) const; - bool operator==(const defaultChar* other) const; + bool operator==(const DefaultChar* other) const; + bool operator!=(const Zstring& other) const; + bool operator!=(const DefaultChar* other) const; + + DefaultChar operator[](const size_t pos) const; Zstring& operator+=(const Zstring& other); - Zstring& operator+=(const defaultChar* other); - Zstring& operator+=(defaultChar ch); + Zstring& operator+=(const DefaultChar* other); + Zstring& operator+=(DefaultChar ch); Zstring operator+(const Zstring& string2) const; - Zstring operator+(const defaultChar* string2) const; - Zstring operator+(const defaultChar ch) const; + Zstring operator+(const DefaultChar* string2) const; + Zstring operator+(const DefaultChar ch) const; static const size_t npos = static_cast<size_t>(-1); private: - void initAndCopy(const defaultChar* source, size_t length); - void incRef(); //support for reference-counting + void initAndCopy(const DefaultChar* source, size_t length); + void incRef() const; //support for reference-counting void decRef(); // void copyBeforeWrite(const size_t capacityNeeded); //and copy-on-write struct StringDescriptor { StringDescriptor(const unsigned int refC, const size_t len, const size_t cap) : refCount(refC), length(len), capacity(cap) {} - unsigned int refCount; + mutable unsigned int refCount; size_t length; size_t capacity; //allocated length without null-termination }; - static void allocate(const unsigned int newRefCount, const size_t newLength, const size_t newCapacity, Zstring::StringDescriptor*& newDescr, defaultChar*& newData); + static void allocate(const unsigned int newRefCount, const size_t newLength, const size_t newCapacity, Zstring::StringDescriptor*& newDescr, DefaultChar*& newData); StringDescriptor* descr; - defaultChar* data; + DefaultChar* data; }; @@ -151,13 +157,13 @@ inline bool defaultIsWhiteSpace(const char ch) { // some compilers (e.g. VC++ 6.0) return true for a call to isspace('\xEA') => exclude char(128) to char(255) - return (ch < 128) && isspace(ch) != 0; + return ((unsigned char)ch < 128) && isspace((unsigned char)ch) != 0; } inline char defaultToLower(const char ch) { - return tolower(ch); + return tolower((unsigned char)ch); //caution: although tolower() has int as input parameter it expects unsigned chars! } #elif defined ZSTRING_WIDE_CHAR @@ -217,20 +223,20 @@ void Zstring::allocate(const unsigned int newRefCount, const size_t newLength, const size_t newCapacity, StringDescriptor*& newDescr, - defaultChar*& newData) + DefaultChar*& newData) { //allocate and set data for new string if (newCapacity) { - newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(defaultChar)); + newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar)); if (newDescr == NULL) - throw; //std::bad_alloc& e - newData = (defaultChar*)(newDescr + 1); + throw std::bad_alloc(); + newData = (DefaultChar*)(newDescr + 1); } else { newDescr = (StringDescriptor*) malloc( sizeof(StringDescriptor)); if (newDescr == NULL) - throw; //std::bad_alloc& e + throw std::bad_alloc(); newData = NULL; } @@ -259,14 +265,14 @@ Zstring::Zstring() inline -Zstring::Zstring(const defaultChar* source) +Zstring::Zstring(const DefaultChar* source) { initAndCopy(source, defaultLength(source)); } inline -Zstring::Zstring(const defaultChar* source, size_t length) +Zstring::Zstring(const DefaultChar* source, size_t length) { initAndCopy(source, length); } @@ -282,13 +288,6 @@ Zstring::Zstring(const Zstring& source) inline -Zstring::Zstring(const wxString& source) -{ - initAndCopy(source.c_str(), source.length()); -} - - -inline Zstring::~Zstring() { decRef(); @@ -303,17 +302,17 @@ size_t getCapacityToAllocate(const size_t length) inline -void Zstring::initAndCopy(const defaultChar* source, size_t length) +void Zstring::initAndCopy(const DefaultChar* source, size_t length) { const size_t newCapacity = getCapacityToAllocate(length); allocate(1, length, newCapacity, descr, data); - memcpy(data, source, length * sizeof(defaultChar)); + memcpy(data, source, length * sizeof(DefaultChar)); data[length] = 0; } inline -void Zstring::incRef() +void Zstring::incRef() const { assert(descr); ++descr->refCount; @@ -337,7 +336,7 @@ void Zstring::decRef() #ifdef FFS_WIN inline -int Zstring::CmpNoCase(const defaultChar* other) const +int Zstring::CmpNoCase(const DefaultChar* other) const { return FreeFileSync::compareStringsWin32(c_str(), other); //way faster than wxString::CmpNoCase()!! } @@ -352,7 +351,7 @@ int Zstring::CmpNoCase(const Zstring& other) const inline -Zstring::operator const defaultChar*() const +Zstring::operator const DefaultChar*() const { return c_str(); } @@ -361,19 +360,17 @@ Zstring::operator const defaultChar*() const inline Zstring& Zstring::operator=(const Zstring& source) { - if (this != &source) - { - decRef(); - descr = source.descr; - data = source.data; - incRef(); - } + source.incRef(); //implicitly handle case "this == &source" and avoid this check + decRef(); // + descr = source.descr; + data = source.data; + return *this; } inline -size_t Zstring::Find(defaultChar ch, bool fromEnd) const +size_t Zstring::Find(DefaultChar ch, bool fromEnd) const { if (fromEnd) return rfind(ch, npos); @@ -385,7 +382,7 @@ size_t Zstring::Find(defaultChar ch, bool fromEnd) const // get all characters after the last occurence of ch // (returns the whole string if ch not found) inline -Zstring Zstring::AfterLast(defaultChar ch) const +Zstring Zstring::AfterLast(DefaultChar ch) const { size_t pos = rfind(ch, npos); if (pos == npos ) @@ -398,7 +395,7 @@ Zstring Zstring::AfterLast(defaultChar ch) const // get all characters before the last occurence of ch // (returns empty string if ch not found) inline -Zstring Zstring::BeforeLast(defaultChar ch) const +Zstring Zstring::BeforeLast(DefaultChar ch) const { size_t pos = rfind(ch, npos); @@ -410,7 +407,7 @@ Zstring Zstring::BeforeLast(defaultChar ch) const inline -bool Zstring::StartsWith(const defaultChar* begin) const +bool Zstring::StartsWith(const DefaultChar* begin) const { const size_t beginLength = defaultLength(begin); if (length() < beginLength) @@ -430,7 +427,7 @@ bool Zstring::StartsWith(const Zstring& begin) const inline -bool Zstring::EndsWith(const defaultChar* end) const +bool Zstring::EndsWith(const DefaultChar* end) const { const size_t thisLength = length(); const size_t endLength = defaultLength(end); @@ -452,57 +449,64 @@ bool Zstring::EndsWith(const Zstring& end) const inline -size_t Zstring::find(const defaultChar* str, const size_t pos) const +size_t Zstring::find(const DefaultChar* str, const size_t pos) const { assert(pos <= length()); - const defaultChar* thisStr = c_str(); - const defaultChar* found = defaultStrFind(thisStr + pos, str); + const DefaultChar* thisStr = c_str(); + const DefaultChar* found = defaultStrFind(thisStr + pos, str); return found == NULL ? npos : found - thisStr; } inline -size_t Zstring::find(const defaultChar ch, const size_t pos) const +size_t Zstring::find(const DefaultChar ch, const size_t pos) const { assert(pos <= length()); - const defaultChar* thisStr = c_str(); - const defaultChar* found = defaultStrFind(thisStr + pos, ch); + const DefaultChar* thisStr = c_str(); + const DefaultChar* found = defaultStrFind(thisStr + pos, ch); return found == NULL ? npos : found - thisStr; } inline -Zstring::operator const wxString() const +int Zstring::Cmp(const DefaultChar* other) const { - return wxString(c_str()); + return compare(other); } inline -int Zstring::Cmp(const defaultChar* other) const +int Zstring::Cmp(const Zstring& other) const { - return compare(other); + return defaultCompare(c_str(), other.c_str()); //overload using strcmp(char*, char*) should be fastest! } inline -int Zstring::Cmp(const Zstring& other) const +bool Zstring::operator==(const Zstring& other) const { - return defaultCompare(c_str(), other.c_str()); //overload using strcmp(char*, char*) should be fastest! + return length() != other.length() ? false : defaultCompare(c_str(), other.c_str()) == 0; } inline -bool Zstring::operator==(const Zstring& other) const +bool Zstring::operator==(const DefaultChar* other) const { - return defaultCompare(c_str(), other.c_str()) == 0; //overload using strcmp(char*, char*) should be fastest! + return defaultCompare(c_str(), other) == 0; //overload using strcmp(char*, char*) should be fastest! } inline -bool Zstring::operator==(const defaultChar* other) const +bool Zstring::operator!=(const Zstring& other) const { - return compare(other) == 0; + return length() != other.length() ? true: defaultCompare(c_str(), other.c_str()) != 0; +} + + +inline +bool Zstring::operator!=(const DefaultChar* other) const +{ + return defaultCompare(c_str(), other) != 0; //overload using strcmp(char*, char*) should be fastest! } @@ -514,14 +518,14 @@ int Zstring::compare(const Zstring& other) const inline -int Zstring::compare(const defaultChar* other) const +int Zstring::compare(const DefaultChar* other) const { return defaultCompare(c_str(), other); //overload using strcmp(char*, char*) should be fastest! } inline -int Zstring::compare(const size_t pos1, const size_t n1, const defaultChar* other) const +int Zstring::compare(const size_t pos1, const size_t n1, const DefaultChar* other) const { assert(length() - pos1 >= n1); return defaultCompare(c_str() + pos1, other, n1); @@ -536,7 +540,14 @@ size_t Zstring::length() const inline -const defaultChar* Zstring::c_str() const +size_t Zstring::size() const +{ + return descr->length; +} + + +inline +const DefaultChar* Zstring::c_str() const { if (length()) return data; @@ -557,6 +568,14 @@ bool Zstring::empty() const inline +DefaultChar Zstring::operator[](const size_t pos) const +{ + assert(pos < length()); + return data[pos]; +} + + +inline Zstring Zstring::operator+(const Zstring& string2) const { return Zstring(*this)+=string2; @@ -564,14 +583,14 @@ Zstring Zstring::operator+(const Zstring& string2) const inline -Zstring Zstring::operator+(const defaultChar* string2) const +Zstring Zstring::operator+(const DefaultChar* string2) const { return Zstring(*this)+=string2; } inline -Zstring Zstring::operator+(const defaultChar ch) const +Zstring Zstring::operator+(const DefaultChar ch) const { return Zstring(*this)+=ch; } diff --git a/synchronization.cpp b/synchronization.cpp index 85b4d4c1..487bceb9 100644 --- a/synchronization.cpp +++ b/synchronization.cpp @@ -14,14 +14,32 @@ using namespace FreeFileSync; SyncProcess::SyncProcess(bool useRecycler, bool lineBreakOnMessages, StatusHandler* handler) : useRecycleBin(useRecycler), statusUpdater(handler), - txtCopyingFile(_("Copying file \"%x\" to \"%y\"")), - txtOverwritingFile(_("Copying file \"%x\" overwriting \"%y\"")), - txtCreatingFolder(_("Creating folder \"%x\"")), - txtDeletingFile(_("Deleting file \"%x\"")), - txtDeletingFolder(_("Deleting folder \"%x\"")) + txtCopyingFile(_("Copying file %x to %y")), + txtOverwritingFile(_("Copying file %x overwriting %y")), + txtCreatingFolder(_("Creating folder %x")), + txtDeletingFile(_("Deleting file %x")), + txtDeletingFolder(_("Deleting folder %x")) { if (lineBreakOnMessages) - optionalLineBreak = wxT("\n"); + { + txtCopyingFile.Replace( wxT("%x"), wxT("\n\"%x\""), false); + txtCopyingFile.Replace( wxT("%y"), wxT("\n\"%y\""), false); + txtOverwritingFile.Replace(wxT("%x"), wxT("\n\"%x\""), false); + txtOverwritingFile.Replace(wxT("%y"), wxT("\n\"%y\""), false); + txtCreatingFolder.Replace( wxT("%x"), wxT("\n\"%x\""), false); + txtDeletingFile.Replace( wxT("%x"), wxT("\n\"%x\""), false); + txtDeletingFolder.Replace( wxT("%x"), wxT("\n\"%x\""), false); + } + else + { + txtCopyingFile.Replace( wxT("%x"), wxT("\"%x\""), false); + txtCopyingFile.Replace( wxT("%y"), wxT("\"%y\""), false); + txtOverwritingFile.Replace(wxT("%x"), wxT("\"%x\""), false); + txtOverwritingFile.Replace(wxT("%y"), wxT("\"%y\""), false); + txtCreatingFolder.Replace( wxT("%x"), wxT("\"%x\""), false); + txtDeletingFile.Replace( wxT("%x"), wxT("\"%x\""), false); + txtDeletingFolder.Replace( wxT("%x"), wxT("\"%x\""), false); + } } @@ -139,7 +157,7 @@ bool getBytesToTransfer(int& objectsToCreate, return true; } -void copyfileMultithreaded(const wxString& source, const wxString& target, StatusHandler* updateClass); +void copyfileMultithreaded(const Zstring& source, const Zstring& target, StatusHandler* updateClass); bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const SyncConfiguration& config) @@ -168,7 +186,7 @@ bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const SyncConf statusText = txtCopyingFile; statusText.Replace(wxT("%x"), cmpLine.fileDescrLeft.fullName, false); - statusText.Replace(wxT("%y"), target, false); + statusText.Replace(wxT("%y"), cmpLine.fileDescrRight.directory, false); statusUpdater->updateStatusText(statusText); copyfileMultithreaded(cmpLine.fileDescrLeft.fullName, target, statusUpdater); @@ -188,7 +206,7 @@ bool SyncProcess::synchronizeFile(const FileCompareLine& cmpLine, const SyncConf statusText = txtCopyingFile; statusText.Replace(wxT("%x"), cmpLine.fileDescrRight.fullName, false); - statusText.Replace(wxT("%y"), target, false); + statusText.Replace(wxT("%y"), cmpLine.fileDescrLeft.directory, false); statusUpdater->updateStatusText(statusText); copyfileMultithreaded(cmpLine.fileDescrRight.fullName, target, statusUpdater); @@ -278,7 +296,7 @@ bool SyncProcess::synchronizeFolder(const FileCompareLine& cmpLine, const SyncCo //some check to catch the error that directory on source has been deleted externally after "compare"... if (!wxDirExists(cmpLine.fileDescrLeft.fullName)) - throw FileError(wxString(_("Error: Source directory does not exist anymore:")) + wxT(" \"") + cmpLine.fileDescrLeft.fullName.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT(" \"") + cmpLine.fileDescrLeft.fullName + wxT("\"")); createDirectory(target); copyFolderAttributes(cmpLine.fileDescrLeft.fullName, target); break; @@ -301,7 +319,7 @@ bool SyncProcess::synchronizeFolder(const FileCompareLine& cmpLine, const SyncCo //some check to catch the error that directory on source has been deleted externally after "compare"... if (!wxDirExists(cmpLine.fileDescrRight.fullName)) - throw FileError(wxString(_("Error: Source directory does not exist anymore:")) + wxT(" \"") + cmpLine.fileDescrRight.fullName.c_str() + wxT("\"")); + throw FileError(Zstring(_("Error: Source directory does not exist anymore:")) + wxT(" \"") + cmpLine.fileDescrRight.fullName + wxT("\"")); createDirectory(target); copyFolderAttributes(cmpLine.fileDescrRight.fullName, target); break; @@ -361,7 +379,7 @@ public: private: FileCompareResult& gridToWrite; - set<int> rowsProcessed; + std::set<int> rowsProcessed; }; @@ -381,12 +399,12 @@ void SyncProcess::startSynchronizationProcess(FileCompareResult& grid, const Syn int objectsToOverwrite = 0; int objectsToDelete = 0; double dataToProcess = 0; - calcTotalBytesToSync(objectsToCreate, + calcTotalBytesToSync(grid, + config, + objectsToCreate, objectsToOverwrite, objectsToDelete, - dataToProcess, - grid, - config); + dataToProcess); statusUpdater->initNewProcess(objectsToCreate + objectsToOverwrite + objectsToDelete, dataToProcess, StatusHandler::PROCESS_SYNCHRONIZING); @@ -495,6 +513,7 @@ void SyncProcess::startSynchronizationProcess(FileCompareResult& grid, const Syn catch (const RuntimeException& theException) { wxMessageBox(theException.show(), _("An exception occured!"), wxOK | wxICON_ERROR); + statusUpdater->requestAbortion(); return; } } @@ -510,18 +529,18 @@ public: UpdateWhileCopying() {} ~UpdateWhileCopying() {} - wxString source; - wxString target; + Zstring source; + Zstring target; bool success; - wxString errorMessage; + Zstring errorMessage; private: - virtual void longRunner() //virtual method implementation + void longRunner() //virtual impl. { - if (!wxCopyFile(source, target, false)) //abort if file exists + if (!wxCopyFile(source.c_str(), target.c_str(), false)) //abort if file exists { success = false; - errorMessage = wxString(_("Error copying file:")) + wxT(" \"") + source + wxT("\" -> \"") + target + wxT("\""); + errorMessage = Zstring(_("Error copying file:")) + wxT(" \"") + source + wxT("\" -> \"") + target + wxT("\""); return; } @@ -530,7 +549,7 @@ private: if (stat(source.c_str(), &fileInfo) != 0) //read modification time from source file { success = false; - errorMessage = wxString(_("Could not retrieve file info for:")) + wxT(" \"") + source + wxT("\""); + errorMessage = Zstring(_("Could not retrieve file info for:")) + wxT(" \"") + source + wxT("\""); return; } @@ -541,7 +560,7 @@ private: if (utime(target.c_str(), &newTimes) != 0) { success = false; - errorMessage = wxString(_("Error changing modification time:")) + wxT(" \"") + target + wxT("\""); + errorMessage = Zstring(_("Error changing modification time:")) + wxT(" \"") + target + wxT("\""); return; } #endif // FFS_LINUX @@ -551,7 +570,7 @@ private: }; -void copyfileMultithreaded(const wxString& source, const wxString& target, StatusHandler* updateClass) +void copyfileMultithreaded(const Zstring& source, const Zstring& target, StatusHandler* updateClass) { static UpdateWhileCopying copyAndUpdate; //single instantiation: after each execution thread enters wait phase @@ -569,12 +588,12 @@ void copyfileMultithreaded(const wxString& source, const wxString& target, Statu } -void FreeFileSync::calcTotalBytesToSync(int& objectsToCreate, +void FreeFileSync::calcTotalBytesToSync(const FileCompareResult& fileCmpResult, + const SyncConfiguration& config, + int& objectsToCreate, int& objectsToOverwrite, int& objectsToDelete, - double& dataToProcess, - const FileCompareResult& fileCmpResult, - const SyncConfiguration& config) + double& dataToProcess) { objectsToCreate = 0; objectsToOverwrite = 0; @@ -590,10 +609,26 @@ void FreeFileSync::calcTotalBytesToSync(int& objectsToCreate, { //only sum up sizes of files AND directories if (getBytesToTransfer(toCreate, toOverwrite, toDelete, data, *i, config)) { - objectsToCreate+= toCreate; - objectsToOverwrite+= toOverwrite; - objectsToDelete+= toDelete; - dataToProcess+= data; + objectsToCreate += toCreate; + objectsToOverwrite += toOverwrite; + objectsToDelete += toDelete; + dataToProcess += data; } } } + + +bool FreeFileSync::synchronizationNeeded(const FileCompareResult& fileCmpResult, const SyncConfiguration& config) +{ + int objectsToCreate = 0; + int objectsToOverwrite = 0; + int objectsToDelete = 0; + double dataToProcess = 0; + FreeFileSync::calcTotalBytesToSync(fileCmpResult, + config, + objectsToCreate, + objectsToOverwrite, + objectsToDelete, + dataToProcess); + return objectsToCreate + objectsToOverwrite + objectsToDelete != 0; +} diff --git a/synchronization.h b/synchronization.h index 32ffaba6..7e80dc7b 100644 --- a/synchronization.h +++ b/synchronization.h @@ -7,12 +7,14 @@ namespace FreeFileSync { - void calcTotalBytesToSync(int& objectsToCreate, + void calcTotalBytesToSync(const FileCompareResult& fileCmpResult, + const SyncConfiguration& config, + int& objectsToCreate, int& objectsToOverwrite, int& objectsToDelete, - double& dataToProcess, - const FileCompareResult& fileCmpResult, - const SyncConfiguration& config); + double& dataToProcess); + + bool synchronizationNeeded(const FileCompareResult& fileCmpResult, const SyncConfiguration& config); //class handling synchronization process class SyncProcess @@ -28,14 +30,13 @@ namespace FreeFileSync const bool useRecycleBin; StatusHandler* statusUpdater; - wxString optionalLineBreak; //optional line break for status messages (used by GUI mode only) //preload status texts - const Zstring txtCopyingFile; - const Zstring txtOverwritingFile; - const Zstring txtCreatingFolder; - const Zstring txtDeletingFile; - const Zstring txtDeletingFolder; + Zstring txtCopyingFile; + Zstring txtOverwritingFile; + Zstring txtCreatingFolder; + Zstring txtDeletingFile; + Zstring txtDeletingFolder; }; } diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp index 7c74454f..ead2084f 100644 --- a/ui/MainDialog.cpp +++ b/ui/MainDialog.cpp @@ -14,6 +14,7 @@ #include <wx/clipbrd.h> #include <wx/ffile.h> #include "../library/customGrid.h" +#include "../library/customButton.h" #include <algorithm> #include "../library/sorting.h" #include <wx/msgdlg.h> @@ -37,37 +38,22 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale restartOnExit(false), cmpStatusHandlerTmp(0) { - m_bpButtonCompare->SetLabel(_("&Compare")); - m_bpButtonSync->SetLabel(_("&Synchronize")); - - //load list of last used configuration files - cfgFileHistory = new wxConfig(wxT("FreeFileSync")); - for (int i = CfgHistroyLength - 1; i >= 0; --i) //put files in reverse order to history - { - const wxString key = wxString(wxT("Selection")) + numberToWxString(i); - - wxString value; - if (cfgFileHistory->Read(key, &value)) - addCfgFileToHistory(value); - } - m_choiceLoad->SetSelection(0); - //initialize and load configuration - readConfigurationFromXml(cfgFileName, true); readGlobalSettings(); + readConfigurationFromXml(cfgFileName, true); leftOnlyFilesActive = true; leftNewerFilesActive = true; differentFilesActive = true; - rightNewerFilesActive = true; //do not put these bool values into config.dat! + rightNewerFilesActive = true; //do not save/load these bool values from harddisk! rightOnlyFilesActive = true; //it's more convenient to have them defaulted at startup equalFilesActive = false; updateViewFilterButtons(); //set icons for this dialog m_bpButton10->SetBitmapLabel(*globalResource.bitmapExit); - m_bpButtonCompare->SetBitmapLabel(*globalResource.bitmapCompare); - m_bpButtonSync->SetBitmapLabel(*globalResource.bitmapSync); + m_buttonCompare->setBitmapFront(*globalResource.bitmapCompare); + m_buttonSync->setBitmapFront(*globalResource.bitmapSync); m_bpButtonSwap->SetBitmapLabel(*globalResource.bitmapSwap); m_bpButton14->SetBitmapLabel(*globalResource.bitmapHelp); m_bpButton201->SetBitmapLabel(*globalResource.bitmapSave); @@ -76,11 +62,13 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale m_bpButtonRemovePair->SetBitmapDisabled(*globalResource.bitmapRemoveFolderPairD); m_bitmap15->SetBitmap(*globalResource.bitmapStatusEdge); + bSizer6->Layout(); //wxButtonWithImage size might have changed + //menu icons m_menuItem10->SetBitmap(*globalResource.bitmapCompareSmall); m_menuItem11->SetBitmap(*globalResource.bitmapSyncSmall); m_menuItem7->SetBitmap(*globalResource.bitmapBatchSmall); - m_menuItemAdjustTimes->SetBitmap(*globalResource.bitmapClockSmall); + m_menuItemGlobSett->SetBitmap(*globalResource.bitmapSettingsSmall); //Workaround for wxWidgets: small hack to update menu items: actually this is a wxWidgets bug (affects Windows- and Linux-build) m_menu1->Remove(m_menuItem10); @@ -88,13 +76,9 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale m_menu1->Insert(0, m_menuItem10); m_menu1->Insert(1, m_menuItem11); m_menu3->Remove(m_menuItem7); - m_menu3->Remove(m_menuItemAdjustTimes); + m_menu3->Remove(m_menuItemGlobSett); m_menu3->Insert(2, m_menuItem7); - m_menu3->Insert(3, m_menuItemAdjustTimes); - -#ifdef FFS_LINUX //file time adjustment not needed for Linux build - m_menu3->Remove(m_menuItemAdjustTimes); -#endif + m_menu3->Insert(3, m_menuItemGlobSett); //prepare drag & drop m_panel1->SetDropTarget(new FileDropEvent(this, m_panel1)); @@ -156,71 +140,48 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale _("<< left file is newer\n") + _(">> right file is newer\n") + _("!= files are different\n") + - _("== files are equal\n\n") + - _("(-) filtered out from sync-process\n"); + _("== files are equal\n\n"); m_gridMiddle->GetGridWindow()->SetToolTip(toolTip); - //enable parallel scrolling - m_gridLeft->setScrollFriends(m_gridLeft, m_gridRight, m_gridMiddle); - m_gridRight->setScrollFriends(m_gridLeft, m_gridRight, m_gridMiddle); - m_gridMiddle->setScrollFriends(m_gridLeft, m_gridRight, m_gridMiddle); - - //share data with GUI grids - m_gridLeft->setGridDataTable(&gridRefUI, ¤tGridData); - m_gridRight->setGridDataTable(&gridRefUI, ¤tGridData); - m_gridMiddle->setGridDataTable(&gridRefUI, ¤tGridData); + //init grid settings + m_gridLeft->initSettings( true, m_gridLeft, m_gridRight, m_gridMiddle, &gridRefUI, ¤tGridData); + m_gridMiddle->initSettings(false, m_gridLeft, m_gridRight, m_gridMiddle, &gridRefUI, ¤tGridData); + m_gridRight->initSettings( true, m_gridLeft, m_gridRight, m_gridMiddle, &gridRefUI, ¤tGridData); //disable sync button as long as "compare" hasn't been triggered. enableSynchronization(false); - //make filesize right justified on grids - wxGridCellAttr* cellAttributes = m_gridLeft->GetOrCreateCellAttr(0, 2); - cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); - m_gridLeft->SetColAttr(2, cellAttributes); - - cellAttributes = m_gridRight->GetOrCreateCellAttr(0, 2); //leave these two rows, might be necessary 'cause wxGridCellAttr is ref-counting - cellAttributes->SetAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE); //and SetColAttr takes ownership (means: it will call DecRef()) - m_gridRight->SetColAttr(2, cellAttributes); - - //as the name says: disable them - m_gridMiddle->deactivateScrollbars(); - //mainly to update row label sizes... writeGrid(currentGridData); - //select rows only - m_gridLeft->SetSelectionMode(wxGrid::wxGridSelectRows); - m_gridRight->SetSelectionMode(wxGrid::wxGridSelectRows); - m_gridMiddle->SetSelectionMode(wxGrid::wxGridSelectRows); - - //set color of selections - wxColour darkBlue(40, 35, 140); - m_gridLeft->SetSelectionBackground(darkBlue); - m_gridRight->SetSelectionBackground(darkBlue); - m_gridMiddle->SetSelectionBackground(darkBlue); - m_gridLeft->SetSelectionForeground(*wxWHITE); - m_gridRight->SetSelectionForeground(*wxWHITE); - m_gridMiddle->SetSelectionForeground(*wxWHITE); - enableSynchronization(false); //initialize language selection switch (programLanguage->getLanguage()) { - case wxLANGUAGE_GERMAN: - m_menuItemGerman->Check(); + case wxLANGUAGE_CHINESE_SIMPLIFIED: + m_menuItemChineseSimple->Check(); + break; + case wxLANGUAGE_DUTCH: + m_menuItemDutch->Check(); break; case wxLANGUAGE_FRENCH: m_menuItemFrench->Check(); break; + case wxLANGUAGE_GERMAN: + m_menuItemGerman->Check(); + break; + case wxLANGUAGE_ITALIAN: + m_menuItemItalian->Check(); + break; case wxLANGUAGE_JAPANESE: m_menuItemJapanese->Check(); break; - case wxLANGUAGE_DUTCH: - m_menuItemDutch->Check(); + case wxLANGUAGE_POLISH: + m_menuItemPolish->Check(); break; - case wxLANGUAGE_CHINESE_SIMPLIFIED: - m_menuItemChineseSimple->Check(); + case wxLANGUAGE_PORTUGUESE: + m_menuItemPortuguese->Check(); break; default: m_menuItemEnglish->Check(); @@ -232,21 +193,27 @@ MainDialog::MainDialog(wxFrame* frame, const wxString& cfgFileName, CustomLocale Layout(); //avoid screen flicker when panel is shown later compareStatus->Hide(); - //correct width of middle grid + //correct width of swap button above middle grid wxSize source = m_gridMiddle->GetSize(); wxSize target = bSizerMiddle->GetSize(); int spaceToAdd = source.GetX() - target.GetX(); bSizerMiddle->Insert(1, spaceToAdd / 2, 0, 0); bSizerMiddle->Insert(0, spaceToAdd - (spaceToAdd / 2), 0, 0); + + { //set minimum width for choice load + wxSize old; + if ((old = m_choiceLoad->GetSize()).x < 140) + { + old.x = 140; + m_choiceLoad->SetMinSize(old); + bSizer58->Layout(); + } + } } MainDialog::~MainDialog() { - m_gridLeft->setGridDataTable(0, 0); - m_gridRight->setGridDataTable(0, 0); - m_gridMiddle->setGridDataTable(0, 0); - m_gridLeft->setSortMarker(-1); m_gridRight->setSortMarker(-1); @@ -254,22 +221,6 @@ MainDialog::~MainDialog() delete contextMenu; - //write list of last used configuration files - int vectorSize = cfgFileNames.size(); - for (int i = 0; i < CfgHistroyLength; ++i) - { - const wxString key = wxString(wxT("Selection")) + numberToWxString(i); - - if (i < vectorSize) - cfgFileHistory->Write(key, cfgFileNames[i]); - else - { - if (cfgFileHistory->Exists(key)) - cfgFileHistory->DeleteEntry(key, false); - } - } - delete cfgFileHistory; - //save configuration writeConfigurationToXml(FreeFileSync::LAST_CONFIG_FILE); //don't trow exceptions in destructors writeGlobalSettings(); @@ -292,36 +243,25 @@ void MainDialog::readGlobalSettings() posYNotMaximized = globalSettings.gui.posYNotMaximized; //apply window size and position - if ( widthNotMaximized != wxDefaultCoord && + if ( widthNotMaximized != wxDefaultCoord && heightNotMaximized != wxDefaultCoord && - posXNotMaximized != wxDefaultCoord && - posYNotMaximized != wxDefaultCoord) + posXNotMaximized != wxDefaultCoord && + posYNotMaximized != wxDefaultCoord) SetSize(posXNotMaximized, posYNotMaximized, widthNotMaximized, heightNotMaximized); Maximize(globalSettings.gui.isMaximized); - //read column widths - for (int i = 0; i < m_gridLeft->GetNumberCols() && i < int(globalSettings.gui.columnWidthLeft.size()); ++i) - m_gridLeft->SetColSize(i, globalSettings.gui.columnWidthLeft[i]); - - for (int i = 0; i < m_gridRight->GetNumberCols() && i < int(globalSettings.gui.columnWidthRight.size()); ++i) - m_gridRight->SetColSize(i, globalSettings.gui.columnWidthRight[i]); + //set column attributes + m_gridLeft->setColumnAttributes(globalSettings.gui.columnAttribLeft); + m_gridRight->setColumnAttributes(globalSettings.gui.columnAttribRight); -/* //read column positions - for (int i = 0; i < m_gridLeft->GetNumberCols() && i < int(globalSettings.gui.columnPositionsLeft.size()); ++i) - { - const int newPosition = globalSettings.gui.columnPositionsLeft[i]; - if (0 <= newPosition && newPosition < m_gridLeft->GetNumberCols()) - m_gridLeft->SetColPos(i, newPosition); - } + //load list of last used configuration files (in reverse order) + for (std::vector<wxString>::reverse_iterator i = globalSettings.gui.cfgFileHistory.rbegin(); + i != globalSettings.gui.cfgFileHistory.rend(); + ++i) + addCfgFileToHistory(*i); + m_choiceLoad->SetSelection(0); - for (int i = 0; i < m_gridRight->GetNumberCols() && i < int(globalSettings.gui.columnPositionsRight.size()); ++i) - { - const int newPosition = globalSettings.gui.columnPositionsRight[i]; - if (0 <= newPosition && newPosition < m_gridRight->GetNumberCols()) - m_gridRight->SetColPos(i, newPosition); - } - */ } @@ -334,24 +274,12 @@ void MainDialog::writeGlobalSettings() globalSettings.gui.posYNotMaximized = posYNotMaximized; globalSettings.gui.isMaximized = IsMaximized(); - //write column widths - globalSettings.gui.columnWidthLeft.clear(); - for (int i = 0; i < m_gridLeft->GetNumberCols(); ++i) - globalSettings.gui.columnWidthLeft.push_back(m_gridLeft->GetColSize(i)); - - globalSettings.gui.columnWidthRight.clear(); - for (int i = 0; i < m_gridRight->GetNumberCols(); ++i) - globalSettings.gui.columnWidthRight.push_back(m_gridRight->GetColSize(i)); + //retrieve column attributes + globalSettings.gui.columnAttribLeft = m_gridLeft->getColumnAttributes(); + globalSettings.gui.columnAttribRight = m_gridRight->getColumnAttributes(); -/* - //write column positions - globalSettings.gui.columnPositionsLeft.clear(); - for (int i = 0; i < m_gridLeft->GetNumberCols(); ++i) - globalSettings.gui.columnPositionsLeft.push_back(m_gridLeft->GetColPos(i)); - - globalSettings.gui.columnPositionsRight.clear(); - for (int i = 0; i < m_gridRight->GetNumberCols(); ++i) - globalSettings.gui.columnPositionsRight.push_back(m_gridRight->GetColPos(i));*/ + //write list of last used configuration files + globalSettings.gui.cfgFileHistory = cfgFileNames; } @@ -398,26 +326,28 @@ void MainDialog::enableSynchronization(bool value) if (value) { synchronizationEnabled = true; - m_bpButtonSync->SetBitmapLabel(*globalResource.bitmapSync); + m_buttonSync->SetForegroundColour(*wxBLACK); + m_buttonSync->setBitmapFront(*globalResource.bitmapSync); } else { synchronizationEnabled = false; - m_bpButtonSync->SetBitmapLabel(*globalResource.bitmapSyncDisabled); + m_buttonSync->SetForegroundColour(wxColor(94, 94, 94)); //grey + m_buttonSync->setBitmapFront(*globalResource.bitmapSyncDisabled); } } -void MainDialog::filterRangeTemp(const set<int>& rowsToFilterOnUI_View) +void MainDialog::filterRangeManually(const std::set<int>& rowsToFilterOnUiTable) { - if (rowsToFilterOnUI_View.size() > 0) + if (rowsToFilterOnUiTable.size() > 0) { int gridSizeUI = gridRefUI.size(); bool newSelection = false; //default: deselect range //leadingRow determines de-/selection of all other rows - int leadingRow = *rowsToFilterOnUI_View.begin(); + int leadingRow = *rowsToFilterOnUiTable.begin(); if (0 <= leadingRow && leadingRow < gridSizeUI) newSelection = !currentGridData[gridRefUI[leadingRow]].selectedForSynchronization; @@ -426,9 +356,9 @@ void MainDialog::filterRangeTemp(const set<int>& rowsToFilterOnUI_View) //get all lines that need to be filtered (e.g. if a folder is marked, then its subelements should be marked as well) - set<int> rowsToFilterOnGridData; //rows to filter in backend + std::set<int> rowsToFilterOnGridData; //rows to filter in backend - for (set<int>::iterator i = rowsToFilterOnUI_View.begin(); i != rowsToFilterOnUI_View.end(); ++i) + for (std::set<int>::iterator i = rowsToFilterOnUiTable.begin(); i != rowsToFilterOnUiTable.end(); ++i) { if (0 <= *i && *i < gridSizeUI) { @@ -440,7 +370,7 @@ void MainDialog::filterRangeTemp(const set<int>& rowsToFilterOnUI_View) } //toggle selection of filtered rows - for (set<int>::iterator i = rowsToFilterOnGridData.begin(); i != rowsToFilterOnGridData.end(); ++i) + for (std::set<int>::iterator i = rowsToFilterOnGridData.begin(); i != rowsToFilterOnGridData.end(); ++i) currentGridData[*i].selectedForSynchronization = newSelection; //signal UI that grids need to be refreshed on next Update() @@ -508,7 +438,7 @@ void MainDialog::OnIdleEvent(wxEvent& event) filteringInitialized = false; if (leadGrid) - filterRangeTemp(getSelectedRows(leadGrid)); + filterRangeManually(getSelectedRows(leadGrid)); } } @@ -534,12 +464,12 @@ void MainDialog::OnIdleEvent(wxEvent& event) void MainDialog::copySelectionToClipboard(const wxGrid* selectedGrid) { - const set<int> selectedRows = getSelectedRows(selectedGrid); + const std::set<int> selectedRows = getSelectedRows(selectedGrid); if (selectedRows.size() > 0) { wxString clipboardString; - for (set<int>::iterator i = selectedRows.begin(); i != selectedRows.end(); ++i) + for (std::set<int>::iterator i = selectedRows.begin(); i != selectedRows.end(); ++i) { for (int k = 0; k < const_cast<wxGrid*>(selectedGrid)->GetNumberCols(); ++k) { @@ -563,23 +493,23 @@ void MainDialog::copySelectionToClipboard(const wxGrid* selectedGrid) } -void removeInvalidRows(set<int>& rows, const int currentUI_Size) +void removeInvalidRows(std::set<int>& rows, const int currentUiTableSize) { - set<int> validRows; //temporal table IS needed here - for (set<int>::iterator i = rows.begin(); i != rows.end(); ++i) + std::set<int> validRows; //temporal table IS needed here + for (std::set<int>::iterator i = rows.begin(); i != rows.end(); ++i) if (0 <= *i) { - if (*i >= currentUI_Size) //set is sorted, so no need to continue here + if (*i >= currentUiTableSize) //set is sorted, so no need to continue here break; validRows.insert(*i); } - rows = validRows; + rows.swap(validRows); } -set<int> MainDialog::getSelectedRows(const wxGrid* grid) +std::set<int> MainDialog::getSelectedRows(const wxGrid* grid) { - set<int> output; + std::set<int> output; int rowTop, rowBottom; //coords of selection wxArrayInt selectedRows = grid->GetSelectedRows(); @@ -637,7 +567,7 @@ public: unsolvedErrors(unsolvedErrorOccured) {} ~DeleteErrorHandler() {} - Response reportError(const wxString& text) + Response reportError(const Zstring& text) { if (ignoreErrors) { @@ -646,7 +576,7 @@ public: } bool ignoreNextErrors = false; - wxString errorMessage = text + wxT("\n\n") + _("Information: If you ignore the error or abort a re-compare will be necessary!"); + wxString errorMessage = wxString(text.c_str()) + wxT("\n\n") + _("Information: If you ignore the error or abort a re-compare will be necessary!"); ErrorDlg* errorDlg = new ErrorDlg(parent, errorMessage, ignoreNextErrors); int rv = errorDlg->ShowModal(); @@ -677,13 +607,13 @@ private: }; -void MainDialog::deleteFilesOnGrid(const set<int>& rowsToDeleteOnUI) +void MainDialog::deleteFilesOnGrid(const std::set<int>& rowsToDeleteOnUI) { if (rowsToDeleteOnUI.size()) { //map grid lines from UI to grid lines in backend (gridData) - set<int> rowsToDeleteOnGrid; - for (set<int>::iterator i = rowsToDeleteOnUI.begin(); i != rowsToDeleteOnUI.end(); ++i) + std::set<int> rowsToDeleteOnGrid; + for (std::set<int>::iterator i = rowsToDeleteOnUI.begin(); i != rowsToDeleteOnUI.end(); ++i) rowsToDeleteOnGrid.insert(gridRefUI[*i]); wxString headerText; @@ -694,7 +624,7 @@ void MainDialog::deleteFilesOnGrid(const set<int>& rowsToDeleteOnUI) else headerText = _("Do you really want to delete the following objects(s)?"); - for (set<int>::iterator i = rowsToDeleteOnGrid.begin(); i != rowsToDeleteOnGrid.end(); ++i) + for (std::set<int>::iterator i = rowsToDeleteOnGrid.begin(); i != rowsToDeleteOnGrid.end(); ++i) { const FileCompareLine& currentCmpLine = currentGridData[*i]; @@ -745,34 +675,41 @@ void MainDialog::deleteFilesOnGrid(const set<int>& rowsToDeleteOnUI) } -void MainDialog::openWithFileBrowser(int rowNumber, const wxGrid* grid) +void MainDialog::openWithFileManager(int rowNumber, const wxGrid* grid) { -#ifdef FFS_WIN + wxString command; + const FileDescrLine* fileDescr = NULL; if (grid == m_gridLeft) { - wxString command = wxString(wxT("explorer ")) + FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue()).c_str(); //default - if (0 <= rowNumber && rowNumber < int(gridRefUI.size())) - { - const FileDescrLine& fileDescr = currentGridData[gridRefUI[rowNumber]].fileDescrLeft; - if (fileDescr.objType != FileDescrLine::TYPE_NOTHING) - command = wxString(wxT("explorer /select,")) + fileDescr.fullName.c_str(); - } - wxExecute(command); + fileDescr = ¤tGridData[gridRefUI[rowNumber]].fileDescrLeft; +#ifdef FFS_WIN + command = wxString(wxT("explorer ")) + FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue().c_str()).c_str(); //default +#endif // FFS_WIN } else if (grid == m_gridRight) { - wxString command = wxString(wxT("explorer ")) + FreeFileSync::getFormattedDirectoryName(m_directoryRight->GetValue()).c_str(); //default - if (0 <= rowNumber && rowNumber < int(gridRefUI.size())) - { - const FileDescrLine& fileDescr = currentGridData[gridRefUI[rowNumber]].fileDescrRight; - if (fileDescr.objType != FileDescrLine::TYPE_NOTHING) - command = wxString(wxT("explorer /select,")) + fileDescr.fullName.c_str(); - } - wxExecute(command); - } + fileDescr = ¤tGridData[gridRefUI[rowNumber]].fileDescrRight; +#ifdef FFS_WIN + command = wxString(wxT("explorer ")) + FreeFileSync::getFormattedDirectoryName(m_directoryRight->GetValue().c_str()).c_str(); //default #endif // FFS_WIN + } + else + { + assert(false); + return; + } + + if (fileDescr && fileDescr->objType != FileDescrLine::TYPE_NOTHING) + { + command = globalSettings.gui.commandLineFileManager; + command.Replace(wxT("%x"), fileDescr->fullName.c_str()); + command.Replace(wxT("%path"), wxFileName(fileDescr->fullName.c_str()).GetPath()); + } + + if (!command.empty()) + wxExecute(command.c_str()); } @@ -867,7 +804,7 @@ void MainDialog::onGridMiddleButtonEvent(wxKeyEvent& event) void MainDialog::OnOpenContextMenu(wxGridEvent& event) { - set<int> selection; + std::set<int> selection; if (leadGrid) selection = getSelectedRows(leadGrid); @@ -893,7 +830,7 @@ void MainDialog::OnOpenContextMenu(wxGridEvent& event) //get list of relative file/dir-names into vectors FilterObject newFilterEntry; if (leadGrid == m_gridLeft) - for (set<int>::iterator i = selection.begin(); i != selection.end(); ++i) + for (std::set<int>::iterator i = selection.begin(); i != selection.end(); ++i) { const FileCompareLine& line = currentGridData[gridRefUI[*i]]; newFilterEntry.relativeName = line.fileDescrLeft.relativeName.c_str(); @@ -902,7 +839,7 @@ void MainDialog::OnOpenContextMenu(wxGridEvent& event) exFilterCandidateObj.push_back(newFilterEntry); } else if (leadGrid == m_gridRight) - for (set<int>::iterator i = selection.begin(); i != selection.end(); ++i) + for (std::set<int>::iterator i = selection.begin(); i != selection.end(); ++i) { const FileCompareLine& line = currentGridData[gridRefUI[*i]]; newFilterEntry.relativeName = line.fileDescrRight.relativeName.c_str(); @@ -918,23 +855,23 @@ void MainDialog::OnOpenContextMenu(wxGridEvent& event) if (filename.Find(wxChar('.')) != wxNOT_FOUND) //be careful: AfterLast will return the whole string if '.' is not found! { exFilterCandidateExtension = filename.AfterLast(wxChar('.')); - contextMenu->Append(CONTEXT_EXCLUDE_EXT, wxString(_("Add to exclude filter:")) + wxT(" ") + wxT("*.") + exFilterCandidateExtension); + contextMenu->Append(CONTEXT_EXCLUDE_EXT, wxString(_("Exclude via filter:")) + wxT(" ") + wxT("*.") + exFilterCandidateExtension); } } if (exFilterCandidateObj.size() == 1) - contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Add to exclude filter:")) + wxT(" ") + exFilterCandidateObj[0].relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR)); + contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + exFilterCandidateObj[0].relativeName.AfterLast(GlobalResources::FILE_NAME_SEPARATOR)); else if (exFilterCandidateObj.size() > 1) - contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Add to exclude filter:")) + wxT(" ") + _("<multiple selection>")); + contextMenu->Append(CONTEXT_EXCLUDE_OBJ, wxString(_("Exclude via filter:")) + wxT(" ") + _("<multiple selection>")); } else contextMenu->Append(CONTEXT_FILTER_TEMP, _("Exclude temporarily")); //this element should always be visible contextMenu->AppendSeparator(); contextMenu->Append(CONTEXT_CLIPBOARD, _("Copy to clipboard\tCTRL+C")); -#ifdef FFS_WIN - contextMenu->Append(CONTEXT_EXPLORER, _("Open with Explorer\tD-Click")); -#endif + + contextMenu->Append(CONTEXT_EXPLORER, _("Open with File Manager\tD-Click")); + contextMenu->AppendSeparator(); contextMenu->Append(CONTEXT_DELETE_FILES, _("Delete files\tDEL")); @@ -955,12 +892,10 @@ void MainDialog::OnOpenContextMenu(wxGridEvent& event) contextMenu->Enable(CONTEXT_DELETE_FILES, false); } -#ifdef FFS_WIN if ((leadGrid == m_gridLeft || leadGrid == m_gridRight) && selection.size() <= 1) contextMenu->Enable(CONTEXT_EXPLORER, true); else contextMenu->Enable(CONTEXT_EXPLORER, false); -#endif //show context menu PopupMenu(contextMenu); @@ -975,8 +910,8 @@ void MainDialog::onContextMenuSelection(wxCommandEvent& event) { if (leadGrid) { - set<int> selection = getSelectedRows(leadGrid); - filterRangeTemp(selection); + std::set<int> selection = getSelectedRows(leadGrid); + filterRangeManually(selection); } } else if (eventId == CONTEXT_EXCLUDE_EXT) @@ -1006,7 +941,7 @@ void MainDialog::onContextMenuSelection(wxCommandEvent& event) { if (exFilterCandidateObj.size() > 0) //check needed to determine if filtering is needed { - for (vector<FilterObject>::const_iterator i = exFilterCandidateObj.begin(); i != exFilterCandidateObj.end(); ++i) + for (std::vector<FilterObject>::const_iterator i = exFilterCandidateObj.begin(); i != exFilterCandidateObj.end(); ++i) { if (!cfg.excludeFilter.IsEmpty() && !cfg.excludeFilter.EndsWith(wxT("\n"))) cfg.excludeFilter+= wxT("\n"); @@ -1046,22 +981,40 @@ void MainDialog::onContextMenuSelection(wxCommandEvent& event) { if (leadGrid == m_gridLeft || leadGrid == m_gridRight) { - set<int> selection = getSelectedRows(leadGrid); + std::set<int> selection = getSelectedRows(leadGrid); if (selection.size() == 1) - openWithFileBrowser(*selection.begin(), leadGrid); + openWithFileManager(*selection.begin(), leadGrid); else if (selection.size() == 0) - openWithFileBrowser(-1, leadGrid); + openWithFileManager(-1, leadGrid); } } else if (eventId == CONTEXT_DELETE_FILES) { if (leadGrid) { - set<int> selection = getSelectedRows(leadGrid); + std::set<int> selection = getSelectedRows(leadGrid); deleteFilesOnGrid(selection); } } + else if (eventId == CONTEXT_CUSTOMIZE_COLUMN_LEFT) + { + XmlGlobalSettings::ColumnAttributes colAttr = m_gridLeft->getColumnAttributes(); + CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr); + if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY) + { + m_gridLeft->setColumnAttributes(colAttr); + } + } + else if (eventId == CONTEXT_CUSTOMIZE_COLUMN_RIGHT) + { + XmlGlobalSettings::ColumnAttributes colAttr = m_gridRight->getColumnAttributes(); + CustomizeColsDlg* customizeDlg = new CustomizeColsDlg(this, colAttr); + if (customizeDlg->ShowModal() == CustomizeColsDlg::BUTTON_OKAY) + { + m_gridRight->setColumnAttributes(colAttr); + } + } event.Skip(); } @@ -1069,19 +1022,31 @@ void MainDialog::onContextMenuSelection(wxCommandEvent& event) void MainDialog::OnColumnMenuLeft(wxGridEvent& event) { + delete contextMenu; + contextMenu = new wxMenu; //re-create context menu + contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_LEFT, _("Customize columns")); + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::onContextMenuSelection), NULL, this); + PopupMenu(contextMenu); //show context menu + event.Skip(); } void MainDialog::OnColumnMenuRight(wxGridEvent& event) { + delete contextMenu; + contextMenu = new wxMenu; //re-create context menu + contextMenu->Append(CONTEXT_CUSTOMIZE_COLUMN_RIGHT, _("Customize columns")); + contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainDialog::onContextMenuSelection), NULL, this); + PopupMenu(contextMenu); //show context menu + event.Skip(); } void MainDialog::OnWriteDirManually(wxCommandEvent& event) { - wxString newDir = FreeFileSync::getFormattedDirectoryName(event.GetString()); + wxString newDir = FreeFileSync::getFormattedDirectoryName(event.GetString().c_str()).c_str(); if (wxDirExists(newDir)) { wxObject* eventObj = event.GetEventObject(); @@ -1094,7 +1059,7 @@ void MainDialog::OnWriteDirManually(wxCommandEvent& event) else { //check if event comes from additional pairs - for (vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) + for (std::vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) { FolderPairGenerated* dirPair = *i; if (eventObj == (wxObject*)(dirPair->m_directoryLeft)) @@ -1126,7 +1091,7 @@ void MainDialog::OnDirSelected(wxFileDirPickerEvent& event) m_directoryRight->SetValue(newPath); else //check if event comes from additional pairs { - for (vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) + for (std::vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) { FolderPairGenerated* dirPair = *i; if (eventObj == (wxObject*)(dirPair->m_dirPickerLeft)) @@ -1163,6 +1128,7 @@ wxString getFormattedHistoryElement(const wxString& filename) //tests if the same filenames are specified, even if they are relative to the current working directory +inline bool sameFileSpecified(const wxString& file1, const wxString& file2) { wxString file1Full = file1; @@ -1178,9 +1144,24 @@ bool sameFileSpecified(const wxString& file1, const wxString& file2) } +class FindDuplicates +{ +public: + FindDuplicates(const wxString& name) : m_name(name) {} + + bool operator()(const wxString& other) const + { + return sameFileSpecified(m_name, other); + } + +private: + const wxString& m_name; +}; + + void MainDialog::addCfgFileToHistory(const wxString& filename) { - //the default configFile should not be in the history + //the default config file should not be in the history if (sameFileSpecified(FreeFileSync::LAST_CONFIG_FILE, filename)) return; @@ -1188,19 +1169,11 @@ void MainDialog::addCfgFileToHistory(const wxString& filename) if (!wxFileExists(filename)) return; - bool duplicateEntry = false; - unsigned int duplicatePos = 0; - for (unsigned int i = 0; i < cfgFileNames.size(); ++i) - if (sameFileSpecified(cfgFileNames[i], filename)) - { - duplicateEntry = true; - duplicatePos = i; - break; - } - if (duplicateEntry) //if entry is in the list, then jump to element - { - m_choiceLoad->SetSelection(duplicatePos + 1); + std::vector<wxString>::const_iterator i; + if ((i = find_if(cfgFileNames.begin(), cfgFileNames.end(), FindDuplicates(filename))) != cfgFileNames.end()) + { //if entry is in the list, then jump to element + m_choiceLoad->SetSelection(i - cfgFileNames.begin() + 1); } else { @@ -1210,11 +1183,11 @@ void MainDialog::addCfgFileToHistory(const wxString& filename) } //keep maximal size of history list - if (cfgFileNames.size() > unsigned(CfgHistroyLength)) + if (cfgFileNames.size() > CFG_HISTORY_LENGTH) { //delete last rows - cfgFileNames.erase(cfgFileNames.end() - 1); - m_choiceLoad->Delete(CfgHistroyLength); //don't forget: m_choiceLoad has (cfgHistroyLength + 1) elements + cfgFileNames.pop_back(); + m_choiceLoad->Delete(CFG_HISTORY_LENGTH); //don't forget: m_choiceLoad has (CFG_HISTORY_LENGTH + 1) elements } } @@ -1269,7 +1242,7 @@ bool FileDropEvent::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filen else //test if additional folder pairs are drop targets { - for (vector<FolderPairGenerated*>::const_iterator i = mainDlg->additionalFolderPairs.begin(); i != mainDlg->additionalFolderPairs.end(); ++i) + for (std::vector<FolderPairGenerated*>::const_iterator i = mainDlg->additionalFolderPairs.begin(); i != mainDlg->additionalFolderPairs.end(); ++i) { FolderPairGenerated* dirPair = *i; if (dropTarget == (dirPair->m_panelLeft)) @@ -1440,15 +1413,18 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program } catch (const FileError& error) { - if (programStartup && filename == FreeFileSync::LAST_CONFIG_FILE && !wxFileExists(filename)) //do not show error in this case - ; - else if (!programStartup) + if (programStartup) + { + if (filename == FreeFileSync::LAST_CONFIG_FILE && !wxFileExists(filename)) //do not show error in this case + ; + else //program startup: show error message and load defaults + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); + } + else { - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); return false; } - else //program startup: show error message and load defaults - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); } //load main configuration into instance @@ -1471,21 +1447,21 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program const unsigned int folderPairCount = guiCfg.directoryPairs.size(); if (folderPairCount > 0) { - vector<FolderPair>::const_iterator i = guiCfg.directoryPairs.begin(); + std::vector<FolderPair>::const_iterator i = guiCfg.directoryPairs.begin(); - m_directoryLeft->SetValue(i->leftDirectory); - wxString leftDirFormatted = FreeFileSync::getFormattedDirectoryName(i->leftDirectory); + m_directoryLeft->SetValue(i->leftDirectory.c_str()); + wxString leftDirFormatted = FreeFileSync::getFormattedDirectoryName(i->leftDirectory).c_str(); if (wxDirExists(leftDirFormatted)) m_dirPickerLeft->SetPath(leftDirFormatted); - m_directoryRight->SetValue(i->rightDirectory); - wxString rightDirFormatted = FreeFileSync::getFormattedDirectoryName(i->rightDirectory); + m_directoryRight->SetValue(i->rightDirectory.c_str()); + wxString rightDirFormatted = FreeFileSync::getFormattedDirectoryName(i->rightDirectory).c_str(); if (wxDirExists(rightDirFormatted)) m_dirPickerRight->SetPath(rightDirFormatted); //set additional pairs - for (vector<FolderPair>::const_iterator i = guiCfg.directoryPairs.begin() + 1; i != guiCfg.directoryPairs.end(); ++i) - addFolderPair(i->leftDirectory, i->rightDirectory); + for (std::vector<FolderPair>::const_iterator i = guiCfg.directoryPairs.begin() + 1; i != guiCfg.directoryPairs.end(); ++i) + addFolderPair(i->leftDirectory.c_str(), i->rightDirectory.c_str()); //adjust folder pair buttons const int additionalFolderCount = folderPairCount - 1; @@ -1522,7 +1498,7 @@ bool MainDialog::writeConfigurationToXml(const wxString& filename) } catch (const FileError& error) { - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); return false; } @@ -1755,7 +1731,7 @@ void MainDialog::updateCompareButtons() } -void MainDialog::getFolderPairs(vector<FolderPair>& output, bool formatted) +void MainDialog::getFolderPairs(std::vector<FolderPair>& output, bool formatted) { output.clear(); @@ -1763,8 +1739,8 @@ void MainDialog::getFolderPairs(vector<FolderPair>& output, bool formatted) FolderPair newPair; if (formatted) { - newPair.leftDirectory = FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue()).c_str(); - newPair.rightDirectory = FreeFileSync::getFormattedDirectoryName(m_directoryRight->GetValue()).c_str(); + newPair.leftDirectory = FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue().c_str()); + newPair.rightDirectory = FreeFileSync::getFormattedDirectoryName(m_directoryRight->GetValue().c_str()); } else { @@ -1774,13 +1750,13 @@ void MainDialog::getFolderPairs(vector<FolderPair>& output, bool formatted) output.push_back(newPair); //add additional pairs - for (vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) + for (std::vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) { FolderPairGenerated* dirPair = *i; if (formatted) { - newPair.leftDirectory = FreeFileSync::getFormattedDirectoryName(dirPair->m_directoryLeft->GetValue()); - newPair.rightDirectory = FreeFileSync::getFormattedDirectoryName(dirPair->m_directoryRight->GetValue()); + newPair.leftDirectory = FreeFileSync::getFormattedDirectoryName(dirPair->m_directoryLeft->GetValue().c_str()); + newPair.rightDirectory = FreeFileSync::getFormattedDirectoryName(dirPair->m_directoryRight->GetValue().c_str()); } else { @@ -1796,7 +1772,7 @@ void MainDialog::getFolderPairs(vector<FolderPair>& output, bool formatted) void MainDialog::OnCompare(wxCommandEvent &event) { //assemble vector of formatted folder pairs - vector<FolderPair> directoryPairsFormatted; + std::vector<FolderPair> directoryPairsFormatted; getFolderPairs(directoryPairsFormatted, true); //check if folders are valid @@ -1837,46 +1813,25 @@ void MainDialog::OnCompare(wxCommandEvent &event) CompareStatusHandler statusHandler(this); cmpStatusHandlerTmp = &statusHandler; - FreeFileSync::CompareProcess comparison(false, &statusHandler); +#ifdef FFS_WIN + FreeFileSync::CompareProcess comparison(false, globalSettings.global.handleDstOnFat32, &statusHandler); +#elif defined FFS_LINUX + FreeFileSync::CompareProcess comparison(false, false, &statusHandler); +#endif comparison.startCompareProcess(directoryPairsFormatted, cfg.compareVar, currentGridData); + //if (output.size < 50000) + statusHandler.updateStatusText(_("Sorting file list...")); + statusHandler.forceUiRefresh(); //keep total number of scanned files up to date + sort(currentGridData.begin(), currentGridData.end(), sortByRelativeName<true, SORT_ON_LEFT>); + //filter currentGridData if option is set if (cfg.filterIsActive) FreeFileSync::filterCurrentGridData(currentGridData, cfg.includeFilter, cfg.excludeFilter); writeGrid(currentGridData); //keep it in try/catch to not overwrite status information if compare is aborted - -#ifdef FFS_WIN - //check if DST time correction needs to be applied - if (globalSettings.global.dstCheckActive) - { - int timeShift = 0; - wxString driveName; - FreeFileSync::checkForDSTChange(currentGridData, directoryPairsFormatted, timeShift, driveName); - if (timeShift) - { - bool hideThisDialog = false; - wxString errorMessage = wxString(_("A file time shift due to a daylight saving time change was detected for a FAT/FAT32 drive.")) + wxT("\n") - + _("You can adjust the file times accordingly to resolve the issue:"); - errorMessage+= wxString(wxT("\n\n")) + _("Drive:") + wxT(" ") + driveName + wxT("\n") - + _("Time shift:") + wxT(" ") + globalFunctions::numberToWxString(timeShift); - - //show popup and ask user how to handle the DST change - WarningDlg* warningDlg = new WarningDlg(this, WarningDlg::BUTTON_RESOLVE | WarningDlg::BUTTON_IGNORE, errorMessage, hideThisDialog); - warningDlg->m_bitmap10->SetBitmap(*globalResource.bitmapClock); - if (warningDlg->ShowModal() == WarningDlg::BUTTON_RESOLVE) - { - ModifyFilesDlg* modifyDlg = new ModifyFilesDlg(this, driveName, timeShift); - if (modifyDlg->ShowModal() == ModifyFilesDlg::BUTTON_APPLY) - throw AbortThisProcess(); - } - else - globalSettings.global.dstCheckActive = !hideThisDialog; - } - } -#endif //FFS_WIN } catch (AbortThisProcess& theException) { @@ -1887,12 +1842,12 @@ void MainDialog::OnCompare(wxCommandEvent &event) if (aborted) { //disable the sync button enableSynchronization(false); - m_bpButtonCompare->SetFocus(); + m_buttonCompare->SetFocus(); } else { //once compare is finished enable the sync button enableSynchronization(true); - m_bpButtonSync->SetFocus(); + m_buttonSync->SetFocus(); //hide sort direction indicator on GUI grids m_gridLeft->setSortMarker(-1); @@ -1914,8 +1869,8 @@ void MainDialog::OnAbortCompare(wxCommandEvent& event) void MainDialog::writeGrid(const FileCompareResult& gridData) { m_gridLeft->BeginBatch(); - m_gridRight->BeginBatch(); m_gridMiddle->BeginBatch(); + m_gridRight->BeginBatch(); mapGridDataToUI(gridRefUI, gridData); //update gridRefUI updateStatusInformation(gridRefUI); //write status information for gridRefUI @@ -1923,8 +1878,8 @@ void MainDialog::writeGrid(const FileCompareResult& gridData) //all three grids retrieve their data directly via gridRefUI!!! //the only thing left to do is notify the grids to update their sizes (nr of rows), since this has to be communicated by the grids via messages m_gridLeft->updateGridSizes(); - m_gridRight->updateGridSizes(); m_gridMiddle->updateGridSizes(); + m_gridRight->updateGridSizes(); //enlarge label width to display row numbers correctly int nrOfRows = m_gridLeft->GetNumberRows(); @@ -1936,8 +1891,8 @@ void MainDialog::writeGrid(const FileCompareResult& gridData) } m_gridLeft->EndBatch(); - m_gridRight->EndBatch(); m_gridMiddle->EndBatch(); + m_gridRight->EndBatch(); } @@ -1947,17 +1902,7 @@ void MainDialog::OnSync(wxCommandEvent& event) if (syncDlg->ShowModal() == SyncDialog::BUTTON_START) { //check if there are files/folders to be sync'ed at all - int objectsToCreate = 0; - int objectsToOverwrite = 0; - int objectsToDelete = 0; - double dataToProcess = 0; - FreeFileSync::calcTotalBytesToSync(objectsToCreate, - objectsToOverwrite, - objectsToDelete, - dataToProcess, - currentGridData, - cfg.syncConfiguration); - if (objectsToCreate + objectsToOverwrite + objectsToDelete == 0) + if (!synchronizationNeeded(currentGridData, cfg.syncConfiguration)) { wxMessageBox(_("Nothing to synchronize according to configuration!"), _("Information"), wxICON_WARNING); return; @@ -1998,43 +1943,44 @@ void MainDialog::OnSync(wxCommandEvent& event) void MainDialog::OnLeftGridDoubleClick(wxGridEvent& event) { - openWithFileBrowser(event.GetRow(), m_gridLeft); + openWithFileManager(event.GetRow(), m_gridLeft); event.Skip(); } void MainDialog::OnRightGridDoubleClick(wxGridEvent& event) { - openWithFileBrowser(event.GetRow(), m_gridRight); + openWithFileManager(event.GetRow(), m_gridRight); event.Skip(); } void MainDialog::OnSortLeftGrid(wxGridEvent& event) { - static bool columnSortAscending[4] = {true, true, false, true}; + static bool columnSortAscending[CustomGrid::COLUMN_TYPE_COUNT] = {true, true, false, true}; int currentSortColumn = event.GetCol(); - if (0 <= currentSortColumn && currentSortColumn <= 3) + if (0 <= currentSortColumn < CustomGrid::COLUMN_TYPE_COUNT) { bool& sortAscending = columnSortAscending[currentSortColumn]; + XmlGlobalSettings::ColumnTypes columnType = m_gridLeft->getTypeAtPos(currentSortColumn); - if (currentSortColumn == 0) + if (columnType == XmlGlobalSettings::FILENAME) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByFileName<true, SORT_ON_LEFT>); else sort(currentGridData.begin(), currentGridData.end(), sortByFileName<false, SORT_ON_LEFT>); } - else if (currentSortColumn == 1) + else if (columnType == XmlGlobalSettings::REL_PATH) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByRelativeName<true, SORT_ON_LEFT>); else sort(currentGridData.begin(), currentGridData.end(), sortByRelativeName<false, SORT_ON_LEFT>); } - else if (currentSortColumn == 2) + else if (columnType == XmlGlobalSettings::SIZE) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByFileSize<true, SORT_ON_LEFT>); else sort(currentGridData.begin(), currentGridData.end(), sortByFileSize<false, SORT_ON_LEFT>); } - else if (currentSortColumn == 3) + else if (columnType == XmlGlobalSettings::DATE) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByDate<true, SORT_ON_LEFT>); else sort(currentGridData.begin(), currentGridData.end(), sortByDate<false, SORT_ON_LEFT>); @@ -2043,11 +1989,12 @@ void MainDialog::OnSortLeftGrid(wxGridEvent& event) writeGrid(currentGridData); //needed to refresh gridRefUI references //set sort direction indicator on UI + m_gridMiddle->setSortMarker(-1); + m_gridRight->setSortMarker(-1); if (sortAscending) m_gridLeft->setSortMarker(currentSortColumn, globalResource.bitmapSmallUp); else m_gridLeft->setSortMarker(currentSortColumn, globalResource.bitmapSmallDown); - m_gridRight->setSortMarker(-1); sortAscending = !sortAscending; } @@ -2057,29 +2004,30 @@ void MainDialog::OnSortLeftGrid(wxGridEvent& event) void MainDialog::OnSortRightGrid(wxGridEvent& event) { - static bool columnSortAscending[4] = {true, true, false, true}; + static bool columnSortAscending[CustomGrid::COLUMN_TYPE_COUNT] = {true, true, false, true}; int currentSortColumn = event.GetCol(); - if (0 <= currentSortColumn && currentSortColumn <= 3) + if (0 <= currentSortColumn < CustomGrid::COLUMN_TYPE_COUNT) { bool& sortAscending = columnSortAscending[currentSortColumn]; + XmlGlobalSettings::ColumnTypes columnType = m_gridRight->getTypeAtPos(currentSortColumn); - if (currentSortColumn == 0) + if (columnType == XmlGlobalSettings::FILENAME) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByFileName<true, SORT_ON_RIGHT>); else sort(currentGridData.begin(), currentGridData.end(), sortByFileName<false, SORT_ON_RIGHT>); } - else if (currentSortColumn == 1) + else if (columnType == XmlGlobalSettings::REL_PATH) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByRelativeName<true, SORT_ON_RIGHT>); else sort(currentGridData.begin(), currentGridData.end(), sortByRelativeName<false, SORT_ON_RIGHT>); } - else if (currentSortColumn == 2) + else if (columnType == XmlGlobalSettings::SIZE) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByFileSize<true, SORT_ON_RIGHT>); else sort(currentGridData.begin(), currentGridData.end(), sortByFileSize<false, SORT_ON_RIGHT>); } - else if (currentSortColumn == 3) + else if (columnType == XmlGlobalSettings::DATE) { if (sortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByDate<true, SORT_ON_RIGHT>); else sort(currentGridData.begin(), currentGridData.end(), sortByDate<false, SORT_ON_RIGHT>); @@ -2089,6 +2037,7 @@ void MainDialog::OnSortRightGrid(wxGridEvent& event) //set sort direction indicator on UI m_gridLeft->setSortMarker(-1); + m_gridMiddle->setSortMarker(-1); if (sortAscending) m_gridRight->setSortMarker(currentSortColumn, globalResource.bitmapSmallUp); else @@ -2100,6 +2049,29 @@ void MainDialog::OnSortRightGrid(wxGridEvent& event) } +void MainDialog::OnSortMiddleGrid(wxGridEvent& event) +{ + static bool columnSortAscending = true; + + if (columnSortAscending) sort(currentGridData.begin(), currentGridData.end(), sortByCmpResult<true>); + else sort(currentGridData.begin(), currentGridData.end(), sortByCmpResult<false>); + + writeGrid(currentGridData); //needed to refresh gridRefUI references + + //set sort direction indicator on UI + m_gridLeft->setSortMarker(-1); + m_gridRight->setSortMarker(-1); + if (columnSortAscending) + m_gridMiddle->setSortMarker(0, globalResource.bitmapSmallUp); + else + m_gridMiddle->setSortMarker(0, globalResource.bitmapSmallDown); + + columnSortAscending = !columnSortAscending; + + event.Skip(); +} + + void MainDialog::OnSwapDirs( wxCommandEvent& event ) { //swap directory names : main pair @@ -2108,7 +2080,7 @@ void MainDialog::OnSwapDirs( wxCommandEvent& event ) m_directoryRight->SetValue(tmp); //additional pairs - for (vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) + for (std::vector<FolderPairGenerated*>::const_iterator i = additionalFolderPairs.begin(); i != additionalFolderPairs.end(); ++i) { FolderPairGenerated* dirPair = *i; tmp = dirPair->m_directoryLeft->GetValue(); @@ -2410,12 +2382,12 @@ void MainDialog::addFolderPair(const wxString& leftDir, const wxString& rightDir //insert directory names if provided newPair->m_directoryLeft->SetValue(leftDir); - wxString leftDirFormatted = FreeFileSync::getFormattedDirectoryName(leftDir); + wxString leftDirFormatted = FreeFileSync::getFormattedDirectoryName(leftDir.c_str()).c_str(); if (wxDirExists(leftDirFormatted)) newPair->m_dirPickerLeft->SetPath(leftDirFormatted); newPair->m_directoryRight->SetValue(rightDir); - wxString rightDirFormatted = FreeFileSync::getFormattedDirectoryName(rightDir); + wxString rightDirFormatted = FreeFileSync::getFormattedDirectoryName(rightDir.c_str()).c_str(); if (wxDirExists(rightDirFormatted)) newPair->m_dirPickerRight->SetPath(rightDirFormatted); } @@ -2468,7 +2440,7 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) : mainDialog->m_bpButtonFilter->Disable(); mainDialog->m_hyperlinkCfgFilter->Disable(); mainDialog->m_checkBoxHideFilt->Disable(); - mainDialog->m_bpButtonSync->Disable(); + mainDialog->m_buttonSync->Disable(); mainDialog->m_dirPickerLeft->Disable(); mainDialog->m_dirPickerRight->Disable(); mainDialog->m_bpButtonSwap->Disable(); @@ -2500,8 +2472,8 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) : //show abort button mainDialog->m_buttonAbort->Enable(); mainDialog->m_buttonAbort->Show(); - mainDialog->m_bpButtonCompare->Disable(); - mainDialog->m_bpButtonCompare->Hide(); + mainDialog->m_buttonCompare->Disable(); + mainDialog->m_buttonCompare->Hide(); mainDialog->m_buttonAbort->SetFocus(); //updateUiNow(); @@ -2521,7 +2493,7 @@ CompareStatusHandler::~CompareStatusHandler() mainDialog->m_bpButtonFilter->Enable(); mainDialog->m_hyperlinkCfgFilter->Enable(); mainDialog->m_checkBoxHideFilt->Enable(); - mainDialog->m_bpButtonSync->Enable(); + mainDialog->m_buttonSync->Enable(); mainDialog->m_dirPickerLeft->Enable(); mainDialog->m_dirPickerRight->Enable(); mainDialog->m_bpButtonSwap->Enable(); @@ -2552,8 +2524,8 @@ CompareStatusHandler::~CompareStatusHandler() mainDialog->m_buttonAbort->Disable(); mainDialog->m_buttonAbort->Hide(); - mainDialog->m_bpButtonCompare->Enable(); //enable compare button - mainDialog->m_bpButtonCompare->Show(); + mainDialog->m_buttonCompare->Enable(); //enable compare button + mainDialog->m_buttonCompare->Show(); //hide status panel from main window mainDialog->compareStatus->Hide(); @@ -2564,7 +2536,7 @@ CompareStatusHandler::~CompareStatusHandler() inline -void CompareStatusHandler::updateStatusText(const wxString& text) +void CompareStatusHandler::updateStatusText(const Zstring& text) { mainDialog->compareStatus->setStatusText_NoUpdate(text); } @@ -2597,7 +2569,7 @@ void CompareStatusHandler::updateProcessedData(int objectsProcessed, double data } -ErrorHandler::Response CompareStatusHandler::reportError(const wxString& text) +ErrorHandler::Response CompareStatusHandler::reportError(const Zstring& text) { if (ignoreErrors) return ErrorHandler::IGNORE_ERROR; @@ -2605,7 +2577,7 @@ ErrorHandler::Response CompareStatusHandler::reportError(const wxString& text) mainDialog->compareStatus->updateStatusPanelNow(); bool ignoreNextErrors = false; - wxString errorMessage = text + wxT("\n\n") + _("Ignore this error, retry or abort?"); + wxString errorMessage = wxString(text.c_str()) + wxT("\n\n") + _("Ignore this error, retry or abort?"); ErrorDlg* errorDlg = new ErrorDlg(mainDialog, errorMessage, ignoreNextErrors); int rv = errorDlg->ShowModal(); @@ -2671,26 +2643,26 @@ SyncStatusHandler::~SyncStatusHandler() if (abortRequested) { result+= wxString(_("Synchronization aborted!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"); - syncStatusFrame->setStatusText_NoUpdate(result); + syncStatusFrame->setStatusText_NoUpdate(result.c_str()); syncStatusFrame->processHasFinished(SyncStatus::ABORTED); //enable okay and close events } else if (failedItems) { result+= wxString(_("Synchronization completed with errors!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!"); - syncStatusFrame->setStatusText_NoUpdate(result); + syncStatusFrame->setStatusText_NoUpdate(result.c_str()); syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_ERROR); } else { - result+= _("Synchronization completed successfully."); - syncStatusFrame->setStatusText_NoUpdate(result); + result+= _("Synchronization completed successfully!"); + syncStatusFrame->setStatusText_NoUpdate(result.c_str()); syncStatusFrame->processHasFinished(SyncStatus::FINISHED_WITH_SUCCESS); } } inline -void SyncStatusHandler::updateStatusText(const wxString& text) +void SyncStatusHandler::updateStatusText(const Zstring& text) { syncStatusFrame->setStatusText_NoUpdate(text); } @@ -2712,18 +2684,18 @@ void SyncStatusHandler::updateProcessedData(int objectsProcessed, double dataPro } -ErrorHandler::Response SyncStatusHandler::reportError(const wxString& text) +ErrorHandler::Response SyncStatusHandler::reportError(const Zstring& text) { if (ignoreErrors) { - unhandledErrors.Add(text); + unhandledErrors.Add(text.c_str()); return ErrorHandler::IGNORE_ERROR; } syncStatusFrame->updateStatusDialogNow(); bool ignoreNextErrors = false; - wxString errorMessage = text + wxT("\n\n") + _("Ignore this error, retry or abort synchronization?"); + wxString errorMessage = wxString(text.c_str()) + wxT("\n\n") + _("Ignore this error, retry or abort synchronization?"); ErrorDlg* errorDlg = new ErrorDlg(syncStatusFrame, errorMessage, ignoreNextErrors); int rv = errorDlg->ShowModal(); @@ -2731,13 +2703,13 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& text) { case ErrorDlg::BUTTON_IGNORE: ignoreErrors = ignoreNextErrors; - unhandledErrors.Add(text); + unhandledErrors.Add(text.c_str()); return ErrorHandler::IGNORE_ERROR; case ErrorDlg::BUTTON_RETRY: return ErrorHandler::RETRY; case ErrorDlg::BUTTON_ABORT: { - unhandledErrors.Add(text); + unhandledErrors.Add(text.c_str()); abortRequested = true; throw AbortThisProcess(); } @@ -2762,6 +2734,15 @@ void SyncStatusHandler::abortThisProcess() //menu events +void MainDialog::OnMenuGlobalSettings(wxCommandEvent& event) +{ + wxDialog* settingsDlg = new GlobalSettingsDlg(this, globalSettings); + settingsDlg->ShowModal(); + + event.Skip(); +} + + void MainDialog::OnMenuExportFileList(wxCommandEvent& event) { //get a filename @@ -2825,22 +2806,9 @@ void MainDialog::OnMenuExportFileList(wxCommandEvent& event) } -void MainDialog::OnMenuAdjustFileTimes(wxCommandEvent& event) -{ - ModifyFilesDlg* modifyDlg = new ModifyFilesDlg(this, FreeFileSync::getFormattedDirectoryName(m_directoryLeft->GetValue()), 0); - if (modifyDlg->ShowModal() == ModifyFilesDlg::BUTTON_APPLY) - { //disable the sync button - enableSynchronization(false); - m_bpButtonCompare->SetFocus(); - } - - event.Skip(); -} - - void MainDialog::OnMenuBatchJob(wxCommandEvent& event) { - vector<FolderPair> folderPairs; + std::vector<FolderPair> folderPairs; getFolderPairs(folderPairs); BatchDialog* batchDlg = new BatchDialog(this, cfg, folderPairs); @@ -2866,56 +2834,76 @@ void MainDialog::OnMenuQuit(wxCommandEvent& event) } -void MainDialog::OnMenuLangEnglish(wxCommandEvent& event) +//######################################################################################################### +//language selection + +void MainDialog::changeProgramLanguage(const int langID) { - programLanguage->setLanguage(wxLANGUAGE_ENGLISH); //language is a global attribute + programLanguage->setLanguage(langID); //language is a global attribute restartOnExit = true; Destroy(); +} + + +void MainDialog::OnMenuLangChineseSimp(wxCommandEvent& event) +{ + changeProgramLanguage(wxLANGUAGE_CHINESE_SIMPLIFIED); event.Skip(); } -void MainDialog::OnMenuLangGerman(wxCommandEvent& event) +void MainDialog::OnMenuLangDutch(wxCommandEvent& event) { - programLanguage->setLanguage(wxLANGUAGE_GERMAN); //language is a global attribute - restartOnExit = true; - Destroy(); + changeProgramLanguage(wxLANGUAGE_DUTCH); + event.Skip(); +} + + +void MainDialog::OnMenuLangEnglish(wxCommandEvent& event) +{ + changeProgramLanguage(wxLANGUAGE_ENGLISH); event.Skip(); } void MainDialog::OnMenuLangFrench(wxCommandEvent& event) { - programLanguage->setLanguage(wxLANGUAGE_FRENCH); //language is a global attribute - restartOnExit = true; - Destroy(); + changeProgramLanguage(wxLANGUAGE_FRENCH); + event.Skip(); +} + + +void MainDialog::OnMenuLangGerman(wxCommandEvent& event) +{ + changeProgramLanguage(wxLANGUAGE_GERMAN); + event.Skip(); +} + + +void MainDialog::OnMenuLangItalian(wxCommandEvent& event) +{ + changeProgramLanguage(wxLANGUAGE_ITALIAN); event.Skip(); } void MainDialog::OnMenuLangJapanese(wxCommandEvent& event) { - programLanguage->setLanguage(wxLANGUAGE_JAPANESE); //language is a global attribute - restartOnExit = true; - Destroy(); + changeProgramLanguage(wxLANGUAGE_JAPANESE); event.Skip(); } -void MainDialog::OnMenuLangDutch(wxCommandEvent& event) +void MainDialog::OnMenuLangPolish(wxCommandEvent& event) { - programLanguage->setLanguage(wxLANGUAGE_DUTCH); //language is a global attribute - restartOnExit = true; - Destroy(); + changeProgramLanguage(wxLANGUAGE_POLISH); event.Skip(); } -void MainDialog::OnMenuLangChineseSimp(wxCommandEvent& event) +void MainDialog::OnMenuLangPortuguese(wxCommandEvent& event) { - programLanguage->setLanguage(wxLANGUAGE_CHINESE_SIMPLIFIED); //language is a global attribute - restartOnExit = true; - Destroy(); + changeProgramLanguage(wxLANGUAGE_PORTUGUESE); event.Skip(); } diff --git a/ui/MainDialog.h b/ui/MainDialog.h index 31214fe4..6c594b14 100644 --- a/ui/MainDialog.h +++ b/ui/MainDialog.h @@ -16,11 +16,9 @@ #include "../library/resources.h" #include "../library/misc.h" #include <wx/dnd.h> -#include <wx/config.h> #include <stack> #include "../library/processXml.h" -using namespace std; //IDs for context menu items enum ContextItem @@ -31,8 +29,8 @@ enum ContextItem CONTEXT_CLIPBOARD, CONTEXT_EXPLORER, CONTEXT_DELETE_FILES, - CONTEXT_HIDE_COLUMN, - CONTEXT_SHOW_ALL_COLUMNS + CONTEXT_CUSTOMIZE_COLUMN_LEFT, + CONTEXT_CUSTOMIZE_COLUMN_RIGHT }; extern const wxGrid* leadGrid; //point to grid that is in focus @@ -72,11 +70,11 @@ private: void updateStatusInformation(const GridView& output); //context menu functions - set<int> getSelectedRows(const wxGrid* grid); - void filterRangeTemp(const set<int>& rowsToFilterOnUI_View); + std::set<int> getSelectedRows(const wxGrid* grid); + void filterRangeManually(const std::set<int>& rowsToFilterOnUiTable); void copySelectionToClipboard(const wxGrid* selectedGrid); - void openWithFileBrowser(int rowNumber, const wxGrid* grid); - void deleteFilesOnGrid(const set<int>& rowsToDeleteOnUI); + void openWithFileManager(int rowNumber, const wxGrid* grid); + void deleteFilesOnGrid(const std::set<int>& rowsToDeleteOnUI); //work to be done in idle time void OnIdleEvent(wxEvent& event); @@ -111,6 +109,7 @@ private: void OnRightGridDoubleClick(wxGridEvent& event); void OnSortLeftGrid( wxGridEvent& event); void OnSortRightGrid( wxGridEvent& event); + void OnSortMiddleGrid( wxGridEvent& event); void OnLeftOnlyFiles( wxCommandEvent& event); void OnLeftNewerFiles( wxCommandEvent& event); @@ -144,18 +143,22 @@ private: //menu events void OnMenuSaveConfig( wxCommandEvent& event); void OnMenuLoadConfig( wxCommandEvent& event); + void OnMenuGlobalSettings( wxCommandEvent& event); void OnMenuExportFileList( wxCommandEvent& event); - void OnMenuAdjustFileTimes( wxCommandEvent& event); void OnMenuBatchJob( wxCommandEvent& event); void OnMenuAbout( wxCommandEvent& event); void OnMenuQuit( wxCommandEvent& event); + void OnMenuLangChineseSimp( wxCommandEvent& event); + void OnMenuLangDutch( wxCommandEvent& event); void OnMenuLangEnglish( wxCommandEvent& event); - void OnMenuLangGerman( wxCommandEvent& event); void OnMenuLangFrench( wxCommandEvent& event); + void OnMenuLangGerman( wxCommandEvent& event); + void OnMenuLangItalian( wxCommandEvent& event); void OnMenuLangJapanese( wxCommandEvent& event); - void OnMenuLangDutch( wxCommandEvent& event); - void OnMenuLangChineseSimp( wxCommandEvent& event); + void OnMenuLangPolish( wxCommandEvent& event); + void OnMenuLangPortuguese( wxCommandEvent& event); + void changeProgramLanguage(const int langID); void enableSynchronization(bool value); //*********************************************** @@ -176,7 +179,7 @@ private: //folder pairs: //m_directoryLeft, m_directoryRight - vector<FolderPairGenerated*> additionalFolderPairs; //additional pairs to the standard pair + std::vector<FolderPairGenerated*> additionalFolderPairs; //additional pairs to the standard pair //gui settings int widthNotMaximized; @@ -187,7 +190,7 @@ private: //------------------------------------- //convenience method to get all folder pairs (unformatted) - void getFolderPairs(vector<FolderPair>& output, bool formatted = false); + void getFolderPairs(std::vector<FolderPair>& output, bool formatted = false); //UI View Filter settings bool leftOnlyFilesActive; @@ -204,15 +207,14 @@ private: //status information wxLongLong lastStatusChange; - stack<wxString> stackObjects; + std::stack<wxString> stackObjects; //compare status panel (hidden on start, shown when comparing) CompareStatus* compareStatus; //save the last used config filenames - wxConfig* cfgFileHistory; - vector<wxString> cfgFileNames; - static const int CfgHistroyLength = 10; + std::vector<wxString> cfgFileNames; + static const unsigned int CFG_HISTORY_LENGTH = 10; //variables for filtering of m_grid3 bool filteringInitialized; @@ -225,7 +227,7 @@ private: wxString relativeName; FileDescrLine::ObjectType type; }; - vector<FilterObject> exFilterCandidateObj; + std::vector<FilterObject> exFilterCandidateObj; bool synchronizationEnabled; //determines whether synchronization should be allowed @@ -265,10 +267,10 @@ public: CompareStatusHandler(MainDialog* dlg); ~CompareStatusHandler(); - void updateStatusText(const wxString& text); + void updateStatusText(const Zstring& text); void initNewProcess(int objectsTotal, double dataTotal, Process processID); void updateProcessedData(int objectsProcessed, double dataProcessed); - ErrorHandler::Response reportError(const wxString& text); + ErrorHandler::Response reportError(const Zstring& text); void forceUiRefresh(); @@ -287,10 +289,10 @@ public: SyncStatusHandler(wxWindow* dlg, bool ignoreAllErrors); ~SyncStatusHandler(); - void updateStatusText(const wxString& text); + void updateStatusText(const Zstring& text); void initNewProcess(int objectsTotal, double dataTotal, Process processID); void updateProcessedData(int objectsProcessed, double dataProcessed); - ErrorHandler::Response reportError(const wxString& text); + ErrorHandler::Response reportError(const Zstring& text); void forceUiRefresh(); diff --git a/ui/SmallDialogs.cpp b/ui/SmallDialogs.cpp index 4c6d0d7b..f451c1fd 100644 --- a/ui/SmallDialogs.cpp +++ b/ui/SmallDialogs.cpp @@ -3,6 +3,7 @@ #include "../library/resources.h" #include "../algorithm.h" #include <wx/msgdlg.h> +#include "../library/customGrid.h" using namespace FreeFileSync; @@ -300,138 +301,158 @@ void WarningDlg::OnOkay(wxCommandEvent& event) dontShowAgain = m_checkBoxDontShowAgain->GetValue(); EndModal(BUTTON_OKAY); } -//######################################################################################## -ModifyFilesDlg::ModifyFilesDlg(wxWindow* window, const wxString& parentDirectory, const int timeShift) : - ModifyFilesDlgGenerated(window) +//######################################################################################## +CustomizeColsDlg::CustomizeColsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings::ColumnAttributes& attr) : + CustomizeColsDlgGenerated(window), + output(attr) { - if (wxDirExists(parentDirectory)) - m_dirPicker->SetPath(parentDirectory); - m_textCtrlDirectory->SetValue(parentDirectory); - m_spinCtrlTimeShift->SetValue(timeShift); - - m_bitmap24->SetBitmap(*globalResource.bitmapClock); - m_buttonApply->SetFocus(); -} + m_bpButton29->SetBitmapLabel(*globalResource.bitmapMoveUp); + m_bpButton30->SetBitmapLabel(*globalResource.bitmapMoveDown); + xmlAccess::XmlGlobalSettings::ColumnAttributes columnSettings = attr; -ModifyFilesDlg::~ModifyFilesDlg() {} + sort(columnSettings.begin(), columnSettings.end(), xmlAccess::sortByPositionOnly); + for (xmlAccess::XmlGlobalSettings::ColumnAttributes::const_iterator i = columnSettings.begin(); i != columnSettings.end(); ++i) //love these iterators! + { + m_checkListColumns->Append(CustomGrid::getTypeName(i->type)); + m_checkListColumns->Check(i - columnSettings.begin(), i->visible); + } -class ModifyErrorHandler : public ErrorHandler -{ -public: - ModifyErrorHandler(wxWindow* parentWindow, bool& unsolvedErrorOccured) : - parent(parentWindow), - ignoreErrors(false), - unsolvedErrors(unsolvedErrorOccured) {} + m_checkListColumns->SetSelection(0); +} - ~ModifyErrorHandler() {} - Response reportError(const wxString& text) +void CustomizeColsDlg::OnOkay(wxCommandEvent& event) +{ + for (int i = 0; i < int(m_checkListColumns->GetCount()); ++i) { - if (ignoreErrors) + const wxString label = m_checkListColumns->GetString(i); + for (xmlAccess::XmlGlobalSettings::ColumnAttributes::iterator j = output.begin(); j != output.end(); ++j) { - unsolvedErrors = true; - return ErrorHandler::IGNORE_ERROR; + if (CustomGrid::getTypeName(j->type) == label) //not nice but short and no performance issue + { + j->position = i; + j->visible = m_checkListColumns->IsChecked(i);; + break; + } } + } + + EndModal(BUTTON_OKAY); +} - bool ignoreNextErrors = false; - ErrorDlg* errorDlg = new ErrorDlg(parent, text, ignoreNextErrors); - int rv = errorDlg->ShowModal(); - switch (rv) - { - case ErrorDlg::BUTTON_IGNORE: - ignoreErrors = ignoreNextErrors; - unsolvedErrors = true; - return ErrorHandler::IGNORE_ERROR; - case ErrorDlg::BUTTON_RETRY: - return ErrorHandler::RETRY; - case ErrorDlg::BUTTON_ABORT: - { - unsolvedErrors = true; - throw AbortThisProcess(); - } - default: - assert (false); - return ErrorHandler::IGNORE_ERROR; //dummy return value - } +void CustomizeColsDlg::OnDefault(wxCommandEvent& event) +{ + for (unsigned i = 0; i < m_checkListColumns->GetCount(); ++i) + { + m_checkListColumns->SetString(i, CustomGrid::getTypeName(xmlAccess::XmlGlobalSettings::ColumnTypes(i))); + m_checkListColumns->Check(i, true); } +} + -private: - wxWindow* parent; - bool ignoreErrors; - bool& unsolvedErrors; -}; +void CustomizeColsDlg::OnCancel(wxCommandEvent& event) +{ + EndModal(0); +} -void ModifyFilesDlg::OnApply(wxCommandEvent& event) +void CustomizeColsDlg::OnClose(wxCloseEvent& event) { - const int timeToShift = m_spinCtrlTimeShift->GetValue(); - const wxString parentDir = m_textCtrlDirectory->GetValue(); + EndModal(0); +} - if (!wxDirExists(parentDir)) + +void CustomizeColsDlg::OnMoveUp(wxCommandEvent& event) +{ + const int pos = m_checkListColumns->GetSelection(); + if (1 <= pos && pos < int(m_checkListColumns->GetCount())) { - wxMessageBox(wxString(_("Directory does not exist:")) + wxT(" \"") + parentDir + wxT("\""), _("Error"), wxOK | wxICON_ERROR); - return; + const bool checked = m_checkListColumns->IsChecked(pos); + const wxString label = m_checkListColumns->GetString(pos); + + m_checkListColumns->SetString(pos, m_checkListColumns->GetString(pos - 1)); + m_checkListColumns->Check(pos, m_checkListColumns->IsChecked(pos - 1)); + m_checkListColumns->SetString(pos - 1, label); + m_checkListColumns->Check(pos - 1, checked); + m_checkListColumns->Select(pos - 1); } + event.Skip(); +} - bool unsolvedErrorOccured = false; //if an error is skipped a re-compare will be necessary! - try - { - wxBusyCursor dummy; //show hourglass cursor - ModifyErrorHandler errorHandler(this, unsolvedErrorOccured); - FreeFileSync::adjustModificationTimes(parentDir, timeToShift, &errorHandler); - } - catch (const AbortThisProcess& theException) +void CustomizeColsDlg::OnMoveDown(wxCommandEvent& event) +{ + const int pos = m_checkListColumns->GetSelection(); + if (0 <= pos && pos < int(m_checkListColumns->GetCount()) - 1) { - EndModal(BUTTON_APPLY); + const bool checked = m_checkListColumns->IsChecked(pos); + const wxString label = m_checkListColumns->GetString(pos); + + m_checkListColumns->SetString(pos, m_checkListColumns->GetString(pos + 1)); + m_checkListColumns->Check(pos, m_checkListColumns->IsChecked(pos + 1)); + m_checkListColumns->SetString(pos + 1, label); + m_checkListColumns->Check(pos + 1, checked); + m_checkListColumns->Select(pos + 1); } + event.Skip(); +} - if (unsolvedErrorOccured) - wxMessageBox(_("Unresolved errors occured during operation!"), _("Information"), wxOK); - else - wxMessageBox(_("All file times have been adjusted successfully!"), _("Information"), wxOK); +//######################################################################################## +GlobalSettingsDlg::GlobalSettingsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings& globalSettings) : + GlobalSettingsDlgGenerated(window), + settings(globalSettings) +{ + m_bitmapSettings->SetBitmap(*globalResource.bitmapSettings); - EndModal(BUTTON_APPLY); +#ifdef FFS_WIN + m_checkBoxHandleDstFat->SetValue(globalSettings.global.handleDstOnFat32); +#else + m_checkBoxHandleDstFat->Hide(); +#endif + m_textCtrlFileManager->SetValue(globalSettings.gui.commandLineFileManager); } -void ModifyFilesDlg::OnCancel(wxCommandEvent& event) +void GlobalSettingsDlg::OnOkay(wxCommandEvent& event) { - EndModal(0); + //write global settings only when okay-button is pressed! +#ifdef FFS_WIN + settings.global.handleDstOnFat32 = m_checkBoxHandleDstFat->GetValue(); +#endif + settings.gui.commandLineFileManager = m_textCtrlFileManager->GetValue(); + + EndModal(BUTTON_OKAY); } -void ModifyFilesDlg::OnClose(wxCloseEvent& event) +void GlobalSettingsDlg::OnDefault(wxCommandEvent& event) { - EndModal(0); + m_checkBoxHandleDstFat->SetValue(true); +#ifdef FFS_WIN + m_textCtrlFileManager->SetValue(wxT("explorer /select, %x")); +#elif defined FFS_LINUX + m_textCtrlFileManager->SetValue(wxT("konqueror \"%path\"")); +#endif } -void ModifyFilesDlg::OnWriteDirManually(wxCommandEvent& event) +void GlobalSettingsDlg::OnCancel(wxCommandEvent& event) { - wxString newDir = FreeFileSync::getFormattedDirectoryName(event.GetString()); - if (wxDirExists(newDir)) - m_dirPicker->SetPath(newDir); - - event.Skip(); + EndModal(0); } -void ModifyFilesDlg::OnDirSelected(wxFileDirPickerEvent& event) +void GlobalSettingsDlg::OnClose(wxCloseEvent& event) { - const wxString newPath = event.GetPath(); - m_textCtrlDirectory->SetValue(newPath); - - event.Skip(); + EndModal(0); } - //######################################################################################## /* class for calculation of remaining time: @@ -587,7 +608,7 @@ void SyncStatus::incProgressIndicator_NoUpdate(int objectsProcessed, double data } -void SyncStatus::setStatusText_NoUpdate(const wxString& text) +void SyncStatus::setStatusText_NoUpdate(const Zstring& text) { currentStatusText = text; } @@ -601,8 +622,8 @@ void SyncStatus::updateStatusDialogNow() m_gauge1->SetValue(int(currentData * scalingFactor)); //status text - if (m_textCtrlInfo->GetValue() != currentStatusText && (screenChanged = true)) //avoid screen flicker - m_textCtrlInfo->SetValue(currentStatusText); + if (m_textCtrlInfo->GetValue() != wxString(currentStatusText.c_str()) && (screenChanged = true)) //avoid screen flicker + m_textCtrlInfo->SetValue(currentStatusText.c_str()); //remaining objects const wxString remainingObjTmp = globalFunctions::numberToWxString(totalObjects - currentObjects); @@ -833,7 +854,7 @@ void CompareStatus::incProcessedCmpData_NoUpdate(int objectsProcessed, double da } -void CompareStatus::setStatusText_NoUpdate(const wxString& text) +void CompareStatus::setStatusText_NoUpdate(const Zstring& text) { currentStatusText = text; } @@ -844,8 +865,8 @@ void CompareStatus::updateStatusPanelNow() bool screenChanged = false; //avoid screen flicker by calling layout() only if necessary //status texts - if (m_textCtrlFilename->GetValue() != currentStatusText && (screenChanged = true)) //avoid screen flicker - m_textCtrlFilename->SetValue(currentStatusText); + if (m_textCtrlFilename->GetValue() != wxString(currentStatusText.c_str()) && (screenChanged = true)) //avoid screen flicker + m_textCtrlFilename->SetValue(currentStatusText.c_str()); //nr of scanned objects const wxString scannedObjTmp = globalFunctions::numberToWxString(scannedObjects); diff --git a/ui/SmallDialogs.h b/ui/SmallDialogs.h index 06e6c407..5be461d2 100644 --- a/ui/SmallDialogs.h +++ b/ui/SmallDialogs.h @@ -3,6 +3,7 @@ #include "../FreeFileSync.h" #include "../library/statusHandler.h" +#include "../library/processXml.h" #include "guiGenerated.h" #include <wx/stopwatch.h> @@ -120,24 +121,48 @@ private: }; -class ModifyFilesDlg : public ModifyFilesDlgGenerated +class CustomizeColsDlg : public CustomizeColsDlgGenerated { public: - ModifyFilesDlg(wxWindow* window, const wxString& parentDirectory, const int timeShift); - ~ModifyFilesDlg(); + CustomizeColsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings::ColumnAttributes& attr); + ~CustomizeColsDlg() {} enum { - BUTTON_APPLY = 10 + BUTTON_OKAY = 10 }; private: - void OnApply(wxCommandEvent& event); + void OnOkay(wxCommandEvent& event); + void OnDefault(wxCommandEvent& event); + void OnCancel(wxCommandEvent& event); + void OnClose(wxCloseEvent& event); + + void OnMoveUp(wxCommandEvent& event); + void OnMoveDown(wxCommandEvent& event); + + xmlAccess::XmlGlobalSettings::ColumnAttributes& output; +}; + + +class GlobalSettingsDlg : public GlobalSettingsDlgGenerated +{ +public: + GlobalSettingsDlg(wxWindow* window, xmlAccess::XmlGlobalSettings& globalSettings); + ~GlobalSettingsDlg() {} + + enum + { + BUTTON_OKAY = 10 + }; + +private: + void OnOkay(wxCommandEvent& event); + void OnDefault(wxCommandEvent& event); void OnCancel(wxCommandEvent& event); void OnClose(wxCloseEvent& event); - void OnWriteDirManually(wxCommandEvent& event); - void OnDirSelected(wxFileDirPickerEvent& event); + xmlAccess::XmlGlobalSettings& settings; }; @@ -160,7 +185,7 @@ public: void resetGauge(int totalObjectsToProcess, double totalDataToProcess); void incProgressIndicator_NoUpdate(int objectsProcessed, double dataProcessed); - void setStatusText_NoUpdate(const wxString& text); + void setStatusText_NoUpdate(const Zstring& text); void updateStatusDialogNow(); void setCurrentStatus(SyncStatusID id); @@ -185,7 +210,7 @@ private: int currentObjects; //each object represents a file or directory processed int totalObjects; - wxString currentStatusText; + Zstring currentStatusText; bool processPaused; }; @@ -226,13 +251,13 @@ public: void switchToCompareBytewise(int totalCmpObjectsToProcess, double totalCmpDataToProcess); void incScannedObjects_NoUpdate(int number); void incProcessedCmpData_NoUpdate(int objectsProcessed, double dataProcessed); - void setStatusText_NoUpdate(const wxString& text); + void setStatusText_NoUpdate(const Zstring& text); void updateStatusPanelNow(); private: //status variables unsigned int scannedObjects; - wxString currentStatusText; + Zstring currentStatusText; wxStopWatch timeElapsed; diff --git a/ui/SyncDialog.cpp b/ui/SyncDialog.cpp index 67ec27dc..f630abc3 100644 --- a/ui/SyncDialog.cpp +++ b/ui/SyncDialog.cpp @@ -5,10 +5,11 @@ #include <wx/msgdlg.h> #include <wx/stdpaths.h> #include <wx/ffile.h> +#include "../library/customButton.h" #include "../synchronization.h" #include "../algorithm.h" -using namespace std; + using namespace xmlAccess; @@ -31,8 +32,6 @@ SyncDialog::SyncDialog(wxWindow* window, calculatePreview(); //set icons for this dialog - m_bpButton18->SetBitmapLabel(*globalResource.bitmapStartSync); - m_bpButton18->SetBitmapDisabled(*globalResource.bitmapStartSyncDis); m_bitmap13->SetBitmap(*globalResource.bitmapLeftOnly); m_bitmap14->SetBitmap(*globalResource.bitmapRightOnly); m_bitmap15->SetBitmap(*globalResource.bitmapLeftNewer); @@ -40,13 +39,22 @@ SyncDialog::SyncDialog(wxWindow* window, m_bitmap17->SetBitmap(*globalResource.bitmapDifferent); if (synchronizationEnabled) - m_bpButton18->Enable(); + { + m_button18->SetForegroundColour(*wxBLACK); + m_button18->setBitmapFront(*globalResource.bitmapStartSync); + m_button18->Enable(); + } else { - m_bpButton18->Disable(); + m_button18->SetForegroundColour(wxColor(94, 94, 94)); //grey + m_button18->setBitmapFront(*globalResource.bitmapStartSyncDis); + m_button18->Disable(); m_button6->SetFocus(); } + bSizer201->Layout(); //wxButtonWithImage size might have changed + + //set radiobutton if ( localSyncConfiguration.exLeftSideOnly == SyncConfiguration::SYNC_DIR_RIGHT && localSyncConfiguration.exRightSideOnly == SyncConfiguration::SYNC_DIR_RIGHT && @@ -72,8 +80,6 @@ SyncDialog::SyncDialog(wxWindow* window, else m_radioBtn3->SetValue(true); //other - m_bpButton18->SetLabel(_("&Start")); - //set tooltip for ambivalent category "different" adjustToolTips(m_bitmap17, config.compareVar); } @@ -195,12 +201,12 @@ void SyncDialog::calculatePreview() int objectsToOverwrite = 0; int objectsToDelete = 0; double dataToProcess = 0; - FreeFileSync::calcTotalBytesToSync(objectsToCreate, + FreeFileSync::calcTotalBytesToSync(gridData, + localSyncConfiguration, + objectsToCreate, objectsToOverwrite, objectsToDelete, - dataToProcess, - gridData, - localSyncConfiguration); + dataToProcess); wxString toCreate = globalFunctions::numberToWxString(objectsToCreate); wxString toUpdate = globalFunctions::numberToWxString(objectsToOverwrite); @@ -378,7 +384,7 @@ void SyncDialog::OnDifferent( wxCommandEvent& event ) BatchDialog::BatchDialog(wxWindow* window, const MainConfiguration& config, - const vector<FolderPair>& folderPairs) : + const std::vector<FolderPair>& folderPairs) : BatchDlgGenerated(window) { //make working copy of mainDialog.cfg.syncConfiguration and recycler setting @@ -411,11 +417,11 @@ BatchDialog::BatchDialog(wxWindow* window, //add folder pairs int scrWindowHeight = 0; - for (vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) + for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i) { BatchFolderPairGenerated* newPair = new BatchFolderPairGenerated(m_scrolledWindow6); - newPair->m_directoryLeft->SetValue(i->leftDirectory); - newPair->m_directoryRight->SetValue(i->rightDirectory); + newPair->m_directoryLeft->SetValue(i->leftDirectory.c_str()); + newPair->m_directoryRight->SetValue(i->rightDirectory.c_str()); bSizerFolderPairs->Add( newPair, 0, wxEXPAND, 5); localFolderPairs.push_back(newPair); @@ -424,7 +430,7 @@ BatchDialog::BatchDialog(wxWindow* window, scrWindowHeight = newPair->GetSize().GetHeight(); } //set size of scrolled window - int pairCount = min(localFolderPairs.size(), size_t(3)); //up to 3 additional pairs shall be shown + int pairCount = std::min(localFolderPairs.size(), size_t(3)); //up to 3 additional pairs shall be shown m_scrolledWindow6->SetMinSize(wxSize( -1, scrWindowHeight * pairCount)); m_scrolledWindow6->Fit(); @@ -553,7 +559,7 @@ void BatchDialog::OnCancel(wxCommandEvent& event) } -void BatchDialog::OnCreateBatchJob(wxCommandEvent& event) +void BatchDialog::OnSaveBatchJob(wxCommandEvent& event) { //get a filename wxString fileName = _("SyncJob.ffs_batch"); //proposal @@ -571,13 +577,13 @@ void BatchDialog::OnCreateBatchJob(wxCommandEvent& event) } //create batch file - if (createBatchFile(fileName)) + if (saveBatchFile(fileName)) EndModal(batchFileCreated); } } -bool BatchDialog::createBatchFile(const wxString& filename) +bool BatchDialog::saveBatchFile(const wxString& filename) { XmlBatchConfig batchCfg; @@ -615,7 +621,7 @@ bool BatchDialog::createBatchFile(const wxString& filename) } catch (const FileError& error) { - wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); + wxMessageBox(error.show().c_str(), _("Error"), wxOK | wxICON_ERROR); return false; } return true; @@ -644,7 +650,6 @@ struct CleanUp bool BatchDialog::createBatchFile(const wxString& filename) { -#ifdef FFS_WIN //create shell link (instead of batch file) for full Unicode support HRESULT hResult = E_FAIL; IShellLink* pShellLink = NULL; diff --git a/ui/SyncDialog.h b/ui/SyncDialog.h index 10f449c8..2f6c5a53 100644 --- a/ui/SyncDialog.h +++ b/ui/SyncDialog.h @@ -63,7 +63,7 @@ class BatchDialog: public BatchDlgGenerated public: BatchDialog(wxWindow* window, const MainConfiguration& config, - const vector<FolderPair>& folderPairs); + const std::vector<FolderPair>& folderPairs); ~BatchDialog(); @@ -82,14 +82,14 @@ private: void OnClose( wxCloseEvent& event); void OnCancel( wxCommandEvent& event); - void OnCreateBatchJob( wxCommandEvent& event); + void OnSaveBatchJob( wxCommandEvent& event); void updateFilterButton(); - bool createBatchFile(const wxString& filename); + bool saveBatchFile(const wxString& filename); SyncConfiguration localSyncConfiguration; - vector<BatchFolderPairGenerated*> localFolderPairs; + std::vector<BatchFolderPairGenerated*> localFolderPairs; bool filterIsActive; }; diff --git a/ui/guiGenerated.cpp b/ui/guiGenerated.cpp index b55b50ed..e1f76b38 100644 --- a/ui/guiGenerated.cpp +++ b/ui/guiGenerated.cpp @@ -5,6 +5,7 @@ // PLEASE DO "NOT" EDIT THIS FILE! /////////////////////////////////////////////////////////////////////////// +#include "../library/customButton.h" #include "../library/customGrid.h" #include "guiGenerated.h" @@ -52,9 +53,18 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_menuItemFrench = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("Français") ) , wxEmptyString, wxITEM_RADIO ); m_menu31->Append( m_menuItemFrench ); + m_menuItemItalian = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("Italiano") ) , wxEmptyString, wxITEM_RADIO ); + m_menu31->Append( m_menuItemItalian ); + + m_menuItemPolish = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("Język Polski") ) , wxEmptyString, wxITEM_RADIO ); + m_menu31->Append( m_menuItemPolish ); + m_menuItemDutch = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("Nederlands") ) , wxEmptyString, wxITEM_RADIO ); m_menu31->Append( m_menuItemDutch ); + m_menuItemPortuguese = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("Português") ) , wxEmptyString, wxITEM_RADIO ); + m_menu31->Append( m_menuItemPortuguese ); + m_menuItemJapanese = new wxMenuItem( m_menu31, wxID_ANY, wxString( _("日本語") ) , wxEmptyString, wxITEM_RADIO ); m_menu31->Append( m_menuItemJapanese ); @@ -65,12 +75,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_menu3->AppendSeparator(); + m_menuItemGlobSett = new wxMenuItem( m_menu3, wxID_ANY, wxString( _("&Global settings") ) , wxEmptyString, wxITEM_NORMAL ); + m_menu3->Append( m_menuItemGlobSett ); + m_menuItem7 = new wxMenuItem( m_menu3, wxID_ANY, wxString( _("&Create batch job") ) , wxEmptyString, wxITEM_NORMAL ); m_menu3->Append( m_menuItem7 ); - m_menuItemAdjustTimes = new wxMenuItem( m_menu3, wxID_ANY, wxString( _("&Adjust file times") ) , wxEmptyString, wxITEM_NORMAL ); - m_menu3->Append( m_menuItemAdjustTimes ); - wxMenuItem* m_menuItem5; m_menuItem5 = new wxMenuItem( m_menu3, wxID_ANY, wxString( _("&Export file list") ) , wxEmptyString, wxITEM_NORMAL ); m_menu3->Append( m_menuItem5 ); @@ -97,13 +107,12 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxBoxSizer* bSizer30; bSizer30 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonCompare = new wxBitmapButton( m_panel71, wxID_OK, wxNullBitmap, wxDefaultPosition, wxSize( 190,37 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); - m_bpButtonCompare->SetDefault(); - m_bpButtonCompare->SetToolTip( _("Compare both sides") ); + m_buttonCompare = new wxButtonWithImage( m_panel71, wxID_OK, _("&Compare"), wxDefaultPosition, wxSize( 180,37 ), 0 ); + m_buttonCompare->SetDefault(); + m_buttonCompare->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + m_buttonCompare->SetToolTip( _("Compare both sides") ); - m_bpButtonCompare->SetToolTip( _("Compare both sides") ); - - bSizer30->Add( m_bpButtonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer30->Add( m_buttonCompare, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); m_buttonAbort = new wxButton( m_panel71, wxID_CANCEL, _("Abort"), wxDefaultPosition, wxSize( 190,37 ), 0 ); m_buttonAbort->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Tahoma") ) ); @@ -186,12 +195,11 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const bSizer6->Add( bSizer56, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonSync = new wxBitmapButton( m_panel71, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 190,37 ), wxBU_AUTODRAW|wxFULL_REPAINT_ON_RESIZE ); - m_bpButtonSync->SetToolTip( _("Open synchronization dialog") ); - - m_bpButtonSync->SetToolTip( _("Open synchronization dialog") ); + m_buttonSync = new wxButtonWithImage( m_panel71, wxID_ANY, _("&Synchronize..."), wxDefaultPosition, wxSize( 180,37 ), 0 ); + m_buttonSync->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); + m_buttonSync->SetToolTip( _("Open synchronization dialog") ); - bSizer6->Add( m_bpButtonSync, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + bSizer6->Add( m_buttonSync, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); bSizer6->Add( 15, 0, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 ); @@ -316,7 +324,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxBoxSizer* bSizer7; bSizer7 = new wxBoxSizer( wxVERTICAL ); - m_gridLeft = new CustomGrid( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_gridLeft = new CustomGridLeft( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); // Grid m_gridLeft->CreateGrid( 15, 4 ); @@ -326,17 +334,9 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_gridLeft->SetMargins( 0, 0 ); // Columns - m_gridLeft->SetColSize( 0, 138 ); - m_gridLeft->SetColSize( 1, 118 ); - m_gridLeft->SetColSize( 2, 67 ); - m_gridLeft->SetColSize( 3, 113 ); - m_gridLeft->EnableDragColMove( true ); + m_gridLeft->EnableDragColMove( false ); m_gridLeft->EnableDragColSize( true ); m_gridLeft->SetColLabelSize( 20 ); - m_gridLeft->SetColLabelValue( 0, _("Filename") ); - m_gridLeft->SetColLabelValue( 1, _("Relative path") ); - m_gridLeft->SetColLabelValue( 2, _("Size") ); - m_gridLeft->SetColLabelValue( 3, _("Date") ); m_gridLeft->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); // Rows @@ -359,7 +359,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxBoxSizer* bSizer18; bSizer18 = new wxBoxSizer( wxVERTICAL ); - m_gridMiddle = new CustomGrid( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_gridMiddle = new CustomGridMiddle( m_panel3, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); // Grid m_gridMiddle->CreateGrid( 15, 1 ); @@ -397,7 +397,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxBoxSizer* bSizer10; bSizer10 = new wxBoxSizer( wxVERTICAL ); - m_gridRight = new CustomGrid( m_panel2, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_gridRight = new CustomGridRight( m_panel2, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); // Grid m_gridRight->CreateGrid( 15, 4 ); @@ -407,17 +407,9 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_gridRight->SetMargins( 0, 0 ); // Columns - m_gridRight->SetColSize( 0, 138 ); - m_gridRight->SetColSize( 1, 118 ); - m_gridRight->SetColSize( 2, 67 ); - m_gridRight->SetColSize( 3, 113 ); - m_gridRight->EnableDragColMove( true ); + m_gridRight->EnableDragColMove( false ); m_gridRight->EnableDragColSize( true ); m_gridRight->SetColLabelSize( 20 ); - m_gridRight->SetColLabelValue( 0, _("Filename") ); - m_gridRight->SetColLabelValue( 1, _("Relative path") ); - m_gridRight->SetColLabelValue( 2, _("Size") ); - m_gridRight->SetColLabelValue( 3, _("Date") ); m_gridRight->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); // Rows @@ -442,7 +434,6 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_panel4 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); bSizer3 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer58; bSizer58 = new wxBoxSizer( wxVERTICAL ); wxStaticBoxSizer* sbSizer16; @@ -457,11 +448,11 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const wxString m_choiceLoadChoices[] = { _("Load from file...") }; int m_choiceLoadNChoices = sizeof( m_choiceLoadChoices ) / sizeof( wxString ); - m_choiceLoad = new wxChoice( m_panel4, wxID_ANY, wxDefaultPosition, wxSize( 140,-1 ), m_choiceLoadNChoices, m_choiceLoadChoices, 0 ); + m_choiceLoad = new wxChoice( m_panel4, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), m_choiceLoadNChoices, m_choiceLoadChoices, 0 ); m_choiceLoad->SetSelection( 0 ); m_choiceLoad->SetToolTip( _("Load configuration via...\n - this list (press DEL to delete items)\n - drag & drop to this window\n - startup parameter") ); - sbSizer16->Add( m_choiceLoad, 0, wxALIGN_CENTER_VERTICAL, 5 ); + sbSizer16->Add( m_choiceLoad, 1, wxALIGN_CENTER_VERTICAL, 5 ); bSizer58->Add( sbSizer16, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); @@ -603,14 +594,17 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const this->Connect( m_menuItemGerman->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangGerman ) ); this->Connect( m_menuItemEnglish->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangEnglish ) ); this->Connect( m_menuItemFrench->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangFrench ) ); + this->Connect( m_menuItemItalian->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangItalian ) ); + this->Connect( m_menuItemPolish->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPolish ) ); this->Connect( m_menuItemDutch->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangDutch ) ); + this->Connect( m_menuItemPortuguese->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortuguese ) ); this->Connect( m_menuItemJapanese->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangJapanese ) ); this->Connect( m_menuItemChineseSimple->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangChineseSimp ) ); + this->Connect( m_menuItemGlobSett->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); this->Connect( m_menuItem7->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); - this->Connect( m_menuItemAdjustTimes->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAdjustFileTimes ) ); this->Connect( m_menuItem5->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); this->Connect( m_menuItem3->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); - m_bpButtonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); + m_buttonCompare->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAbortCompare ), NULL, this ); m_radioBtnSizeDate->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByTimeSize ), NULL, this ); m_radioBtnContent->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByContent ), NULL, this ); @@ -618,7 +612,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const 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_bpButtonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSync ), NULL, this ); + m_buttonSync->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSync ), NULL, this ); m_directoryLeft->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( MainDialogGenerated::OnWriteDirManually ), NULL, this ); m_dirPickerLeft->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); m_bpButtonSwap->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapDirs ), NULL, this ); @@ -631,6 +625,7 @@ MainDialogGenerated::MainDialogGenerated( wxWindow* parent, wxWindowID id, const m_gridLeft->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); m_gridLeft->Connect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnColumnMenuLeft ), NULL, this ); m_gridMiddle->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnOpenContextMenu ), NULL, this ); + m_gridMiddle->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), 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::OnOpenContextMenu ), NULL, this ); m_gridRight->Connect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); @@ -659,14 +654,17 @@ MainDialogGenerated::~MainDialogGenerated() this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangGerman ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangEnglish ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangFrench ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangItalian ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPolish ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangDutch ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangPortuguese ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangJapanese ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuLangChineseSimp ) ); + this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuGlobalSettings ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuBatchJob ) ); - this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAdjustFileTimes ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuExportFileList ) ); this->Disconnect( wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnMenuAbout ) ); - m_bpButtonCompare->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); + m_buttonCompare->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnCompare ), NULL, this ); m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnAbortCompare ), NULL, this ); m_radioBtnSizeDate->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByTimeSize ), NULL, this ); m_radioBtnContent->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainDialogGenerated::OnCompareByContent ), NULL, this ); @@ -674,7 +672,7 @@ MainDialogGenerated::~MainDialogGenerated() 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_bpButtonSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSync ), NULL, this ); + m_buttonSync->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSync ), NULL, this ); m_directoryLeft->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( MainDialogGenerated::OnWriteDirManually ), NULL, this ); m_dirPickerLeft->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainDialogGenerated::OnDirSelected ), NULL, this ); m_bpButtonSwap->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainDialogGenerated::OnSwapDirs ), NULL, this ); @@ -687,6 +685,7 @@ MainDialogGenerated::~MainDialogGenerated() m_gridLeft->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortLeftGrid ), NULL, this ); m_gridLeft->Disconnect( wxEVT_GRID_LABEL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnColumnMenuLeft ), NULL, this ); m_gridMiddle->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( MainDialogGenerated::OnOpenContextMenu ), NULL, this ); + m_gridMiddle->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortMiddleGrid ), 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::OnOpenContextMenu ), NULL, this ); m_gridRight->Disconnect( wxEVT_GRID_LABEL_LEFT_CLICK, wxGridEventHandler( MainDialogGenerated::OnSortRightGrid ), NULL, this ); @@ -804,7 +803,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS wxBoxSizer* bSizer72; bSizer72 = new wxBoxSizer( wxVERTICAL ); - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Create a batch job"), wxDefaultPosition, wxDefaultSize, 0 ); + 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") ) ); @@ -1052,7 +1051,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS wxBoxSizer* bSizer68; bSizer68 = new wxBoxSizer( wxHORIZONTAL ); - m_buttonCreate = new wxButton( this, wxID_ANY, _("&Create"), wxDefaultPosition, wxSize( 120,35 ), 0 ); + m_buttonCreate = new wxButton( this, wxID_ANY, _("&Save"), wxDefaultPosition, wxSize( 120,35 ), 0 ); m_buttonCreate->SetDefault(); m_buttonCreate->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); @@ -1084,7 +1083,7 @@ BatchDlgGenerated::BatchDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_bpButton7->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); m_bpButton8->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); m_bpButton9->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); - m_buttonCreate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCreateBatchJob ), NULL, this ); + m_buttonCreate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); m_button6->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); } @@ -1101,7 +1100,7 @@ BatchDlgGenerated::~BatchDlgGenerated() m_bpButton7->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnLeftNewer ), NULL, this ); m_bpButton8->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnRightNewer ), NULL, this ); m_bpButton9->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnDifferent ), NULL, this ); - m_buttonCreate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCreateBatchJob ), NULL, this ); + m_buttonCreate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnSaveBatchJob ), NULL, this ); m_button6->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BatchDlgGenerated::OnCancel ), NULL, this ); } @@ -1277,16 +1276,14 @@ SyncDlgGenerated::SyncDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr wxBoxSizer* bSizer29; bSizer29 = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bSizer201; bSizer201 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButton18 = new wxBitmapButton( this, wxID_OK, wxNullBitmap, wxDefaultPosition, wxSize( 140,58 ), wxBU_AUTODRAW ); - m_bpButton18->SetDefault(); - m_bpButton18->SetToolTip( _("Start synchronization") ); + m_button18 = new wxButtonWithImage( this, wxID_OK, _("&Start"), wxDefaultPosition, wxSize( 140,58 ), 0 ); + m_button18->SetDefault(); + m_button18->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Arial Black") ) ); + m_button18->SetToolTip( _("Start synchronization") ); - m_bpButton18->SetToolTip( _("Start synchronization") ); - - bSizer201->Add( m_bpButton18, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer201->Add( m_button18, 0, wxALIGN_CENTER_VERTICAL, 5 ); bSizer201->Add( 18, 0, 0, wxEXPAND, 5 ); @@ -1579,7 +1576,7 @@ SyncDlgGenerated::SyncDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr // Connect Events this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncDlgGenerated::OnClose ) ); - m_bpButton18->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnStartSync ), NULL, this ); + m_button18->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnStartSync ), NULL, this ); m_checkBoxUseRecycler->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnSelectRecycleBin ), NULL, this ); m_radioBtn1->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDlgGenerated::OnSyncLeftToRight ), NULL, this ); m_buttonOneWay->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnSyncLeftToRight ), NULL, this ); @@ -1601,7 +1598,7 @@ SyncDlgGenerated::~SyncDlgGenerated() { // Disconnect Events this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SyncDlgGenerated::OnClose ) ); - m_bpButton18->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnStartSync ), NULL, this ); + m_button18->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnStartSync ), NULL, this ); m_checkBoxUseRecycler->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnSelectRecycleBin ), NULL, this ); m_radioBtn1->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( SyncDlgGenerated::OnSyncLeftToRight ), NULL, this ); m_buttonOneWay->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( SyncDlgGenerated::OnSyncLeftToRight ), NULL, this ); @@ -2022,7 +2019,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_staticText73 = new wxStaticText( m_scrolledWindow4, 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 ); - bSizer73->Add( m_staticText73, 0, wxALL|wxEXPAND, 5 ); + bSizer73->Add( m_staticText73, 0, wxEXPAND|wxALL, 5 ); m_staticText74 = new wxStaticText( m_scrolledWindow4, wxID_ANY, _("- ZenJu -"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText74->Wrap( -1 ); @@ -2051,7 +2048,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer72->Add( m_staticText54, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); wxFlexGridSizer* fgSizer9; - fgSizer9 = new wxFlexGridSizer( 4, 2, 5, 20 ); + fgSizer9 = new wxFlexGridSizer( 1, 2, 5, 20 ); fgSizer9->SetFlexibleDirection( wxBOTH ); fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); @@ -2087,6 +2084,30 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS m_staticText92->Wrap( -1 ); fgSizer9->Add( m_staticText92, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText911 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Wojtek Pietruszewski"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText911->Wrap( -1 ); + fgSizer9->Add( m_staticText911, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText921 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Język Polski"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText921->Wrap( -1 ); + fgSizer9->Add( m_staticText921, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText9211 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("QuestMark"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText9211->Wrap( -1 ); + fgSizer9->Add( m_staticText9211, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText9212 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Português"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText9212->Wrap( -1 ); + fgSizer9->Add( m_staticText9212, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText92121 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Emmo"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText92121->Wrap( -1 ); + fgSizer9->Add( m_staticText92121, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + m_staticText92122 = new wxStaticText( m_scrolledWindow3, wxID_ANY, _("Italiano"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText92122->Wrap( -1 ); + fgSizer9->Add( m_staticText92122, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer72->Add( fgSizer9, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); m_scrolledWindow3->SetSizer( bSizer72 ); @@ -2094,7 +2115,7 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer72->Fit( m_scrolledWindow3 ); bSizer53->Add( m_scrolledWindow3, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 ); - bSizer31->Add( bSizer53, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 30 ); + bSizer31->Add( bSizer53, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxRIGHT|wxLEFT, 25 ); m_staticline3 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); bSizer31->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); @@ -2450,7 +2471,7 @@ FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const w wxBoxSizer* bSizer72; bSizer72 = new wxBoxSizer( wxVERTICAL ); - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Set filter for synchronization"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Synchronization filter"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText56->Wrap( -1 ); m_staticText56->SetFont( wxFont( 16, 74, 90, 92, false, wxT("Tahoma") ) ); @@ -2619,7 +2640,7 @@ FilterDlgGenerated::FilterDlgGenerated( wxWindow* parent, wxWindowID id, const w 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|wxTOP, 5 ); + bSizer21->Add( bSizer22, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxTOP|wxBOTTOM, 5 ); this->SetSizer( bSizer21 ); this->Layout(); @@ -2645,18 +2666,101 @@ FilterDlgGenerated::~FilterDlgGenerated() m_button17->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FilterDlgGenerated::OnCancel ), NULL, this ); } -ModifyFilesDlgGenerated::ModifyFilesDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) +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* bSizer80; - bSizer80 = new wxBoxSizer( wxVERTICAL ); + 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 ); + + 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") ) ); - wxBoxSizer* bSizer841; - bSizer841 = new wxBoxSizer( wxHORIZONTAL ); + bSizer97->Add( m_button9, 0, wxALL, 5 ); - m_bitmap24 = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 40,40 ), 0 ); - bSizer841->Add( m_bitmap24, 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 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 ); + + + bSizer96->Add( 0, 0, 0, wxALIGN_CENTER_HORIZONTAL, 20 ); + + 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 ); +} + +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, 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 ) ); @@ -2664,101 +2768,92 @@ ModifyFilesDlgGenerated::ModifyFilesDlgGenerated( wxWindow* parent, wxWindowID i wxBoxSizer* bSizer72; bSizer72 = new wxBoxSizer( wxVERTICAL ); - m_staticText56 = new wxStaticText( m_panel8, wxID_ANY, _("Adjust file times"), wxDefaultPosition, wxDefaultSize, 0 ); + 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|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer72->Add( m_staticText56, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 ); m_panel8->SetSizer( bSizer72 ); m_panel8->Layout(); bSizer72->Fit( m_panel8 ); - bSizer841->Add( m_panel8, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); - - - bSizer841->Add( 0, 0, 1, 0, 5 ); - - bSizer80->Add( bSizer841, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM, 5 ); + bSizer86->Add( m_panel8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - bSizer80->Add( 0, 5, 0, wxEXPAND, 5 ); + bSizer86->Add( 0, 0, 1, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer84; - bSizer84 = new wxBoxSizer( wxHORIZONTAL ); + bSizer95->Add( bSizer86, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer84->Add( 10, 0, 0, wxEXPAND, 5 ); + bSizer95->Add( 0, 10, 0, 0, 5 ); - m_staticTextHeader = new wxStaticText( this, wxID_ANY, _("Adjust modification times of all files contained in the specified folder and its subfolders. This manual adaption might become necessary if you are synchronizing against a FAT32 drive and the daylight saving time is switched. For an overview about the issue see this article:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticTextHeader->Wrap( 400 ); - m_staticTextHeader->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); + wxStaticBoxSizer* sbSizer23; + sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, wxEmptyString ), wxVERTICAL ); - bSizer84->Add( m_staticTextHeader, 0, wxALL, 5 ); + m_checkBoxHandleDstFat = new wxCheckBox( this, wxID_ANY, _("FAT32: Handle Daylight Saving Time"), wxDefaultPosition, wxDefaultSize, 0 ); + m_checkBoxHandleDstFat->SetToolTip( _("Active for FAT/FAT32 drives only: When comparing filetimes treat files that differ by less or equal than 1 hour as equal. This ensures daylight saving time switches are handled properly.") ); - bSizer84->Add( 10, 0, 0, wxEXPAND, 5 ); + sbSizer23->Add( m_checkBoxHandleDstFat, 0, wxALL, 5 ); - bSizer80->Add( bSizer84, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + wxBoxSizer* bSizer104; + bSizer104 = new wxBoxSizer( wxHORIZONTAL ); - m_hyperlink6 = new wxHyperlinkCtrl( this, wxID_ANY, _("http://www.codeproject.com/KB/datetime/dstbugs.aspx"), wxT("http://www.codeproject.com/KB/datetime/dstbugs.aspx"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE ); - bSizer80->Add( m_hyperlink6, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + m_staticText97 = new wxStaticText( this, wxID_ANY, _("File Manager integration:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText97->Wrap( -1 ); + m_staticText97->SetToolTip( _("This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file.") ); + bSizer104->Add( m_staticText97, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - bSizer80->Add( 0, 5, 0, wxEXPAND, 5 ); + m_textCtrlFileManager = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 150,-1 ), 0 ); + m_textCtrlFileManager->SetToolTip( _("This commandline will be executed each time you doubleclick on a filename. %x serves as a placeholder for the selected file.") ); - wxStaticBoxSizer* sbSizer24; - sbSizer24 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Select a folder") ), wxHORIZONTAL ); + bSizer104->Add( m_textCtrlFileManager, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_textCtrlDirectory = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer24->Add( m_textCtrlDirectory, 1, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + sbSizer23->Add( bSizer104, 1, wxEXPAND, 5 ); - m_dirPicker = new wxDirPickerCtrl( this, wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DIR_MUST_EXIST ); - sbSizer24->Add( m_dirPicker, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 ); + bSizer95->Add( sbSizer23, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT, 5 ); - bSizer80->Add( sbSizer24, 0, wxEXPAND|wxALL, 5 ); - wxStaticBoxSizer* sbSizer23; - sbSizer23 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Time shift in seconds") ), wxVERTICAL ); + bSizer95->Add( 0, 10, 0, 0, 5 ); - m_spinCtrlTimeShift = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -2100000000, 2100000000, 0 ); - sbSizer23->Add( m_spinCtrlTimeShift, 0, wxRIGHT|wxLEFT, 5 ); + wxBoxSizer* bSizer97; + bSizer97 = new wxBoxSizer( wxHORIZONTAL ); - bSizer80->Add( sbSizer23, 0, wxALL|wxEXPAND, 5 ); + 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") ) ); - wxBoxSizer* bSizer83; - bSizer83 = new wxBoxSizer( wxHORIZONTAL ); + bSizer97->Add( m_button28, 0, wxALL, 5 ); - m_buttonApply = new wxButton( this, wxID_APPLY, _("Apply"), wxDefaultPosition, wxSize( -1,35 ), 0 ); - m_buttonApply->SetDefault(); - m_buttonApply->SetFont( wxFont( 10, 74, 90, 92, false, wxT("Tahoma") ) ); + m_button9 = new wxButton( this, wxID_DEFAULT, _("&Default"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button9->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - bSizer83->Add( m_buttonApply, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer97->Add( m_button9, 0, wxALL, 5 ); - m_button21 = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); - m_button21->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + m_button29 = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 ); + m_button29->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); - bSizer83->Add( m_button21, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer97->Add( m_button29, 0, wxALL, 5 ); - bSizer80->Add( bSizer83, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer95->Add( bSizer97, 0, wxALIGN_CENTER_HORIZONTAL, 5 ); - this->SetSizer( bSizer80 ); + this->SetSizer( bSizer95 ); this->Layout(); - bSizer80->Fit( this ); + bSizer95->Fit( this ); // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ModifyFilesDlgGenerated::OnClose ) ); - m_textCtrlDirectory->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnWriteDirManually ), NULL, this ); - m_dirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( ModifyFilesDlgGenerated::OnDirSelected ), NULL, this ); - m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnApply ), NULL, this ); - m_button21->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnCancel ), NULL, this ); + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); + m_button28->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 ); } -ModifyFilesDlgGenerated::~ModifyFilesDlgGenerated() +GlobalSettingsDlgGenerated::~GlobalSettingsDlgGenerated() { // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( ModifyFilesDlgGenerated::OnClose ) ); - m_textCtrlDirectory->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnWriteDirManually ), NULL, this ); - m_dirPicker->Disconnect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( ModifyFilesDlgGenerated::OnDirSelected ), NULL, this ); - m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnApply ), NULL, this ); - m_button21->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( ModifyFilesDlgGenerated::OnCancel ), NULL, this ); + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( GlobalSettingsDlgGenerated::OnClose ) ); + m_button28->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 ); } diff --git a/ui/guiGenerated.h b/ui/guiGenerated.h index d2c64166..75f0fb28 100644 --- a/ui/guiGenerated.h +++ b/ui/guiGenerated.h @@ -10,7 +10,10 @@ #include <wx/intl.h> -class CustomGrid; +class CustomGridLeft; +class CustomGridMiddle; +class CustomGridRight; +class wxButtonWithImage; #include <wx/string.h> #include <wx/bitmap.h> @@ -21,10 +24,10 @@ class CustomGrid; #include <wx/font.h> #include <wx/colour.h> #include <wx/settings.h> -#include <wx/bmpbuttn.h> #include <wx/button.h> #include <wx/sizer.h> #include <wx/radiobut.h> +#include <wx/bmpbuttn.h> #include <wx/statbox.h> #include <wx/hyperlink.h> #include <wx/checkbox.h> @@ -43,7 +46,7 @@ class CustomGrid; #include <wx/animate.h> #include <wx/treectrl.h> #include <wx/notebook.h> -#include <wx/spinctrl.h> +#include <wx/checklst.h> /////////////////////////////////////////////////////////////////////////// @@ -65,17 +68,20 @@ class MainDialogGenerated : public wxFrame wxMenuItem* m_menuItemGerman; wxMenuItem* m_menuItemEnglish; wxMenuItem* m_menuItemFrench; + wxMenuItem* m_menuItemItalian; + wxMenuItem* m_menuItemPolish; wxMenuItem* m_menuItemDutch; + wxMenuItem* m_menuItemPortuguese; wxMenuItem* m_menuItemJapanese; wxMenuItem* m_menuItemChineseSimple; + wxMenuItem* m_menuItemGlobSett; wxMenuItem* m_menuItem7; - wxMenuItem* m_menuItemAdjustTimes; wxMenu* m_menu2; wxBoxSizer* bSizer1; wxPanel* m_panel71; wxBoxSizer* bSizer6; - wxBitmapButton* m_bpButtonCompare; + wxButtonWithImage* m_buttonCompare; wxButton* m_buttonAbort; wxRadioButton* m_radioBtnSizeDate; wxRadioButton* m_radioBtnContent; @@ -86,7 +92,7 @@ class MainDialogGenerated : public wxFrame wxHyperlinkCtrl* m_hyperlinkCfgFilter; wxCheckBox* m_checkBoxHideFilt; - wxBitmapButton* m_bpButtonSync; + wxButtonWithImage* m_buttonSync; wxPanel* m_panel11; wxStaticBoxSizer* sbSizer2; @@ -106,12 +112,13 @@ class MainDialogGenerated : public wxFrame wxScrolledWindow* m_scrolledWindowFolderPairs; wxBoxSizer* bSizerFolderPairs; wxPanel* m_panel1; - CustomGrid* m_gridLeft; + CustomGridLeft* m_gridLeft; wxPanel* m_panel3; - CustomGrid* m_gridMiddle; + CustomGridMiddle* m_gridMiddle; wxPanel* m_panel2; - CustomGrid* m_gridRight; + CustomGridRight* m_gridRight; wxBoxSizer* bSizer3; + wxBoxSizer* bSizer58; wxBitmapButton* m_bpButton201; wxChoice* m_choiceLoad; @@ -149,11 +156,14 @@ class MainDialogGenerated : public wxFrame virtual void OnMenuLangGerman( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuLangEnglish( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuLangFrench( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMenuLangItalian( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMenuLangPolish( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuLangDutch( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMenuLangPortuguese( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuLangJapanese( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuLangChineseSimp( wxCommandEvent& event ){ event.Skip(); } + virtual void OnMenuGlobalSettings( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuBatchJob( wxCommandEvent& event ){ event.Skip(); } - virtual void OnMenuAdjustFileTimes( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuExportFileList( wxCommandEvent& event ){ event.Skip(); } virtual void OnMenuAbout( wxCommandEvent& event ){ event.Skip(); } virtual void OnAbortCompare( wxCommandEvent& event ){ event.Skip(); } @@ -172,6 +182,7 @@ class MainDialogGenerated : public wxFrame virtual void OnOpenContextMenu( wxGridEvent& event ){ event.Skip(); } virtual void OnSortLeftGrid( wxGridEvent& event ){ event.Skip(); } virtual void OnColumnMenuLeft( wxGridEvent& event ){ event.Skip(); } + virtual void OnSortMiddleGrid( wxGridEvent& event ){ event.Skip(); } virtual void OnRightGridDoubleClick( wxGridEvent& event ){ event.Skip(); } virtual void OnSortRightGrid( wxGridEvent& event ){ event.Skip(); } virtual void OnColumnMenuRight( wxGridEvent& event ){ event.Skip(); } @@ -284,12 +295,12 @@ class BatchDlgGenerated : public wxDialog virtual void OnLeftNewer( wxCommandEvent& event ){ event.Skip(); } virtual void OnRightNewer( wxCommandEvent& event ){ event.Skip(); } virtual void OnDifferent( wxCommandEvent& event ){ event.Skip(); } - virtual void OnCreateBatchJob( wxCommandEvent& event ){ event.Skip(); } + virtual void OnSaveBatchJob( wxCommandEvent& event ){ event.Skip(); } virtual void OnCancel( wxCommandEvent& event ){ event.Skip(); } public: - BatchDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE ); + 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 ); ~BatchDlgGenerated(); }; @@ -356,7 +367,8 @@ class SyncDlgGenerated : public wxDialog private: protected: - wxBitmapButton* m_bpButton18; + wxBoxSizer* bSizer201; + wxButtonWithImage* m_button18; wxCheckBox* m_checkBoxUseRecycler; wxCheckBox* m_checkBoxIgnoreErrors; @@ -552,6 +564,12 @@ class AboutDlgGenerated : public wxDialog wxStaticText* m_staticText712; wxStaticText* m_staticText91; wxStaticText* m_staticText92; + wxStaticText* m_staticText911; + wxStaticText* m_staticText921; + wxStaticText* m_staticText9211; + wxStaticText* m_staticText9212; + wxStaticText* m_staticText92121; + wxStaticText* m_staticText92122; wxStaticLine* m_staticline3; wxStaticText* m_staticText131; wxStaticBitmap* m_bitmap9; @@ -730,40 +748,67 @@ class FilterDlgGenerated : public wxDialog }; /////////////////////////////////////////////////////////////////////////////// -/// Class ModifyFilesDlgGenerated +/// Class CustomizeColsDlgGenerated /////////////////////////////////////////////////////////////////////////////// -class ModifyFilesDlgGenerated : public wxDialog +class CustomizeColsDlgGenerated : public wxDialog { private: protected: - wxStaticBitmap* m_bitmap24; - wxPanel* m_panel8; - wxStaticText* m_staticText56; + wxCheckListBox* m_checkListColumns; + wxBitmapButton* m_bpButton29; + wxBitmapButton* m_bpButton30; + 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 +{ + private: + + protected: + wxStaticBitmap* m_bitmapSettings; + wxPanel* m_panel8; + wxStaticText* m_staticText56; - wxStaticText* m_staticTextHeader; - wxHyperlinkCtrl* m_hyperlink6; + wxCheckBox* m_checkBoxHandleDstFat; + wxStaticText* m_staticText97; + wxTextCtrl* m_textCtrlFileManager; - wxTextCtrl* m_textCtrlDirectory; - wxDirPickerCtrl* m_dirPicker; - wxSpinCtrl* m_spinCtrlTimeShift; - wxButton* m_buttonApply; - wxButton* m_button21; + 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 OnWriteDirManually( wxCommandEvent& event ){ event.Skip(); } - virtual void OnDirSelected( wxFileDirPickerEvent& event ){ event.Skip(); } - virtual void OnApply( 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: - ModifyFilesDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE ); - ~ModifyFilesDlgGenerated(); + 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(); }; |