diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/MainDialog.cpp | 129 | ||||
-rw-r--r-- | ui/MainDialog.h | 10 | ||||
-rw-r--r-- | ui/SmallDialogs.cpp | 17 | ||||
-rw-r--r-- | ui/batchStatusHandler.cpp | 34 | ||||
-rw-r--r-- | ui/gridView.cpp | 10 | ||||
-rw-r--r-- | ui/gridView.h | 10 | ||||
-rw-r--r-- | ui/guiGenerated.cpp | 11 | ||||
-rw-r--r-- | ui/guiGenerated.h | 1 | ||||
-rw-r--r-- | ui/guiStatusHandler.cpp | 94 | ||||
-rw-r--r-- | ui/guiStatusHandler.h | 3 | ||||
-rw-r--r-- | ui/progressIndicator.cpp | 415 | ||||
-rw-r--r-- | ui/progressIndicator.h | 17 | ||||
-rw-r--r-- | ui/search.cpp | 7 | ||||
-rw-r--r-- | ui/settingsDialog.cpp | 15 | ||||
-rw-r--r-- | ui/trayIcon.cpp | 4 | ||||
-rw-r--r-- | ui/util.cpp | 252 | ||||
-rw-r--r-- | ui/util.h | 38 |
17 files changed, 492 insertions, 575 deletions
diff --git a/ui/MainDialog.cpp b/ui/MainDialog.cpp index 932d0b4a..9c5e0f46 100644 --- a/ui/MainDialog.cpp +++ b/ui/MainDialog.cpp @@ -18,7 +18,7 @@ #include "../comparison.h" #include "../synchronization.h" #include "../algorithm.h" -#include "util.h" +#include "../shared/util.h" #include "checkVersion.h" #include "guiStatusHandler.h" #include "settingsDialog.h" @@ -269,8 +269,8 @@ MainDialog::MainDialog(wxFrame* frame, wxWindowUpdateLocker dummy(this); //avoid display distortion //avoid mirroring this dialog in RTL languages like Hebrew or Arabic -SetLayoutDirection(wxLayout_LeftToRight); -m_panelStatusBar->SetLayoutDirection(wxLayout_LeftToRight); + SetLayoutDirection(wxLayout_LeftToRight); + m_panelStatusBar->SetLayoutDirection(wxLayout_LeftToRight); //init handling of first folder pair @@ -513,11 +513,11 @@ void MainDialog::writeGlobalSettings() } -void MainDialog::setSyncDirManually(const std::set<unsigned int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir) +void MainDialog::setSyncDirManually(const std::set<size_t>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir) { if (rowsToSetOnUiTable.size() > 0) { - for (std::set<unsigned int>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i) + for (std::set<size_t>::const_iterator i = rowsToSetOnUiTable.begin(); i != rowsToSetOnUiTable.end(); ++i) { FileSystemObject* fsObj = gridDataView->getObject(*i); if (fsObj) @@ -532,7 +532,7 @@ void MainDialog::setSyncDirManually(const std::set<unsigned int>& rowsToSetOnUiT } -void MainDialog::filterRangeManually(const std::set<unsigned int>& rowsToFilterOnUiTable, const int leadingRow) +void MainDialog::filterRangeManually(const std::set<size_t>& rowsToFilterOnUiTable, int leadingRow) { if (rowsToFilterOnUiTable.size() > 0) { @@ -584,16 +584,16 @@ void MainDialog::OnIdleEvent(wxEvent& event) void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid) { - const std::set<unsigned int> selectedRows = getSelectedRows(selectedGrid); + const std::set<size_t> selectedRows = getSelectedRows(selectedGrid); if (selectedRows.size() > 0) { wxString clipboardString; - for (std::set<unsigned int>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i) + for (std::set<size_t>::const_iterator i = selectedRows.begin(); i != selectedRows.end(); ++i) { for (int k = 0; k < const_cast<CustomGrid*>(selectedGrid)->GetNumberCols(); ++k) { - clipboardString+= const_cast<CustomGrid*>(selectedGrid)->GetCellValue(*i, k); + clipboardString+= const_cast<CustomGrid*>(selectedGrid)->GetCellValue(static_cast<int>(*i), k); if (k != const_cast<CustomGrid*>(selectedGrid)->GetNumberCols() - 1) clipboardString+= '\t'; } @@ -613,9 +613,9 @@ void MainDialog::copySelectionToClipboard(const CustomGrid* selectedGrid) } -std::set<unsigned int> MainDialog::getSelectedRows(const CustomGrid* grid) const +std::set<size_t> MainDialog::getSelectedRows(const CustomGrid* grid) const { - std::set<unsigned int> output = grid->getAllSelectedRows(); + std::set<size_t> output = grid->getAllSelectedRows(); //remove invalid rows output.erase(output.lower_bound(gridDataView->rowsOnView()), output.end()); @@ -624,11 +624,11 @@ std::set<unsigned int> MainDialog::getSelectedRows(const CustomGrid* grid) const } -std::set<unsigned int> MainDialog::getSelectedRows() const +std::set<size_t> MainDialog::getSelectedRows() const { //merge selections from left and right grid - std::set<unsigned int> selection = getSelectedRows(m_gridLeft); - std::set<unsigned int> additional = getSelectedRows(m_gridRight); + std::set<size_t> selection = getSelectedRows(m_gridLeft); + std::set<size_t> additional = getSelectedRows(m_gridRight); selection.insert(additional.begin(), additional.end()); return selection; } @@ -637,7 +637,7 @@ std::set<unsigned int> MainDialog::getSelectedRows() const class ManualDeletionHandler : private wxEvtHandler, public DeleteFilesHandler { public: - ManualDeletionHandler(MainDialog* main, int totalObjToDel) : + ManualDeletionHandler(MainDialog* main, size_t totalObjToDel) : mainDlg(main), totalObjToDelete(totalObjToDel), abortRequested(false), @@ -695,8 +695,8 @@ public: if (updateUiIsAllowed()) //test if specific time span between ui updates is over { wxString statusMessage = _("%x / %y objects deleted successfully"); - statusMessage.Replace(wxT("%x"), globalFunctions::numberToWxString(deletionCount), false); - statusMessage.Replace(wxT("%y"), globalFunctions::numberToWxString(totalObjToDelete), false); + statusMessage.Replace(wxT("%x"), FreeFileSync::numberToWxString(deletionCount, true), false); + statusMessage.Replace(wxT("%y"), FreeFileSync::numberToWxString(totalObjToDelete, true), false); mainDlg->m_staticTextStatusMiddle->SetLabel(statusMessage); mainDlg->m_panelStatusBar->Layout(); @@ -715,19 +715,19 @@ private: } MainDialog* const mainDlg; - const int totalObjToDelete; + const size_t totalObjToDelete; bool abortRequested; bool ignoreErrors; - unsigned int deletionCount; + size_t deletionCount; }; void MainDialog::deleteSelectedFiles() { //get set of selected rows on view - const std::set<unsigned int> viewSelectionLeft = getSelectedRows(m_gridLeft); - const std::set<unsigned int> viewSelectionRight = getSelectedRows(m_gridRight); + const std::set<size_t> viewSelectionLeft = getSelectedRows(m_gridLeft); + const std::set<size_t> viewSelectionRight = getSelectedRows(m_gridRight); if (viewSelectionLeft.size() + viewSelectionRight.size()) { @@ -806,7 +806,7 @@ void exstractNames(const FileSystemObject& fsObj, wxString& name, wxString& dir) } -void MainDialog::openExternalApplication(unsigned int rowNumber, bool leftSide, const wxString& commandline) +void MainDialog::openExternalApplication(size_t rowNumber, bool leftSide, const wxString& commandline) { if (commandline.empty()) return; @@ -1241,10 +1241,10 @@ void MainDialog::OnContextRim(wxGridEvent& event) //------------------------------------------------------------------------------ - const std::set<unsigned int> selectionLeft = getSelectedRows(m_gridLeft); - const std::set<unsigned int> selectionRight = getSelectedRows(m_gridRight); + const std::set<size_t> selectionLeft = getSelectedRows(m_gridLeft); + const std::set<size_t> selectionRight = getSelectedRows(m_gridRight); - const unsigned int selectionBegin = selectionLeft.size() + selectionRight.size() == 0 ? 0 : + const size_t selectionBegin = selectionLeft.size() + selectionRight.size() == 0 ? 0 : selectionLeft.size() == 0 ? *selectionRight.begin() : selectionRight.size() == 0 ? *selectionLeft.begin() : std::min(*selectionLeft.begin(), *selectionRight.begin()); @@ -1312,14 +1312,14 @@ void MainDialog::OnContextRim(wxGridEvent& event) //############################################################################################### //get list of relative file/dir-names for filtering FilterObjList exFilterCandidateObj; - for (std::set<unsigned int>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i) + for (std::set<size_t>::const_iterator i = selectionLeft.begin(); i != selectionLeft.end(); ++i) { const FileSystemObject* currObj = gridDataView->getObject(*i); if (currObj && !currObj->isEmpty<LEFT_SIDE>()) exFilterCandidateObj.push_back( FilterObject(currObj->getRelativeName<LEFT_SIDE>(), isDirectoryMapping(*currObj))); } - for (std::set<unsigned int>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i) + for (std::set<size_t>::const_iterator i = selectionRight.begin(); i != selectionRight.end(); ++i) { const FileSystemObject* currObj = gridDataView->getObject(*i); if (currObj && !currObj->isEmpty<RIGHT_SIDE>()) @@ -1441,9 +1441,9 @@ void MainDialog::OnContextRim(wxGridEvent& event) void MainDialog::OnContextFilterTemp(wxCommandEvent& event) { //merge selections from left and right grid - std::set<unsigned int> selection = getSelectedRows(); + std::set<size_t> selection = getSelectedRows(); if (!selection.empty()) - filterRangeManually(selection, *selection.begin()); + filterRangeManually(selection, static_cast<int>(*selection.begin())); } @@ -1524,12 +1524,12 @@ void MainDialog::OnContextOpenWith(wxCommandEvent& event) const CustomGrid* leadGrid = m_gridLeft->isLeadGrid() ? static_cast<CustomGrid*>(m_gridLeft) : static_cast<CustomGrid*>(m_gridRight); - std::set<unsigned int> selection = getSelectedRows(leadGrid); + std::set<size_t> selection = getSelectedRows(leadGrid); const int index = event.GetId() - externalAppIDFirst; if ( selection.size() == 1 && - 0 <= index && static_cast<unsigned>(index) < globalSettings.gui.externelApplications.size()) + 0 <= index && static_cast<size_t>(index) < globalSettings.gui.externelApplications.size()) openExternalApplication(*selection.begin(), m_gridLeft->isLeadGrid(), globalSettings.gui.externelApplications[index].second); } } @@ -1544,7 +1544,7 @@ void MainDialog::OnContextDeleteFiles(wxCommandEvent& event) void MainDialog::OnContextSyncDirLeft(wxCommandEvent& event) { //merge selections from left and right grid - const std::set<unsigned int> selection = getSelectedRows(); + const std::set<size_t> selection = getSelectedRows(); setSyncDirManually(selection, FreeFileSync::SYNC_DIR_LEFT); } @@ -1552,7 +1552,7 @@ void MainDialog::OnContextSyncDirLeft(wxCommandEvent& event) void MainDialog::OnContextSyncDirNone(wxCommandEvent& event) { //merge selections from left and right grid - const std::set<unsigned int> selection = getSelectedRows(); + const std::set<size_t> selection = getSelectedRows(); setSyncDirManually(selection, FreeFileSync::SYNC_DIR_NONE); } @@ -1560,7 +1560,7 @@ void MainDialog::OnContextSyncDirNone(wxCommandEvent& event) void MainDialog::OnContextSyncDirRight(wxCommandEvent& event) { //merge selections from left and right grid - const std::set<unsigned int> selection = getSelectedRows(); + const std::set<size_t> selection = getSelectedRows(); setSyncDirManually(selection, FreeFileSync::SYNC_DIR_RIGHT); } @@ -1963,7 +1963,7 @@ void MainDialog::OnCheckRows(FFSCheckRowsEvent& event) if (0 <= lowerBound) { - std::set<unsigned int> selectedRowsOnView; + std::set<size_t> selectedRowsOnView; for (int i = lowerBound; i <= std::min(upperBound, int(gridDataView->rowsOnView()) - 1); ++i) selectedRowsOnView.insert(i); @@ -2010,15 +2010,15 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program ; else { + parsingError = true; + if (error.getSeverity() == xmlAccess::XmlError::WARNING) - { wxMessageBox(error.show(), _("Warning"), wxOK | wxICON_WARNING); - parsingError = true; - } else { wxMessageBox(error.show(), _("Error"), wxOK | wxICON_ERROR); - return false; + if (!programStartup) + return false; } } } @@ -2028,8 +2028,6 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program //########################################################### addFileToCfgHistory(filename); //put filename on list of last used config files - lastConfigurationSaved = parsingError ? xmlAccess::XmlGuiConfig() : currentCfg; //simulate changed config on parsing errors - //set title if (filename == lastConfigFileName()) { @@ -2040,9 +2038,11 @@ bool MainDialog::readConfigurationFromXml(const wxString& filename, bool program { SetTitle(wxString(wxT("FreeFileSync - ")) + filename); currentConfigFileName = filename; + + lastConfigurationSaved = parsingError ? xmlAccess::XmlGuiConfig() : currentCfg; //simulate changed config on parsing errors } - return true; + return !parsingError; } @@ -2611,9 +2611,9 @@ void MainDialog::calculatePreview() { //update preview of bytes to be transferred: const SyncStatistics st(gridDataView->getDataTentative()); - const wxString toCreate = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getCreate())); - const wxString toUpdate = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getOverwrite())); - const wxString toDelete = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(st.getDelete())); + const wxString toCreate = FreeFileSync::numberToWxString(st.getCreate(), true); + const wxString toUpdate = FreeFileSync::numberToWxString(st.getOverwrite(), true); + const wxString toDelete = FreeFileSync::numberToWxString(st.getDelete(), true); const wxString data = FreeFileSync::formatFilesizeToShortString(st.getDataToProcess()); m_textCtrlCreate->SetValue(toCreate); @@ -2948,10 +2948,10 @@ void MainDialog::OnSwapSides(wxCommandEvent& event) void MainDialog::updateGridViewData() { - unsigned int filesOnLeftView = 0; - unsigned int foldersOnLeftView = 0; - unsigned int filesOnRightView = 0; - unsigned int foldersOnRightView = 0; + size_t filesOnLeftView = 0; + size_t foldersOnLeftView = 0; + size_t filesOnRightView = 0; + size_t foldersOnRightView = 0; wxULongLong filesizeLeftView; wxULongLong filesizeRightView; @@ -3086,7 +3086,7 @@ void MainDialog::updateGridViewData() statusLeftNew += _("1 directory"); else { - wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(foldersOnLeftView)); + wxString folderCount = FreeFileSync::numberToWxString(foldersOnLeftView, true); wxString outputString = _("%x directories"); outputString.Replace(wxT("%x"), folderCount, false); @@ -3103,7 +3103,7 @@ void MainDialog::updateGridViewData() statusLeftNew += _("1 file,"); else { - wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(filesOnLeftView)); + wxString fileCount = FreeFileSync::numberToWxString(filesOnLeftView, true); wxString outputString = _("%x files,"); outputString.Replace(wxT("%x"), fileCount, false); @@ -3113,8 +3113,7 @@ void MainDialog::updateGridViewData() statusLeftNew += FreeFileSync::formatFilesizeToShortString(filesizeLeftView); } - const wxString objectsView = FreeFileSync::includeNumberSeparator( - globalFunctions::numberToWxString(static_cast<unsigned int>(gridDataView->rowsOnView()))); + const wxString objectsView = FreeFileSync::numberToWxString(gridDataView->rowsOnView(), true); if (gridDataView->rowsTotal() == 1) { wxString outputString = _("%x of 1 row in view"); @@ -3123,8 +3122,7 @@ void MainDialog::updateGridViewData() } else { - const wxString objectsTotal = FreeFileSync::includeNumberSeparator( - globalFunctions::numberToWxString(static_cast<unsigned int>(gridDataView->rowsTotal()))); + const wxString objectsTotal = FreeFileSync::numberToWxString(gridDataView->rowsTotal(), true); wxString outputString = _("%x of %y rows in view"); outputString.Replace(wxT("%x"), objectsView, false); @@ -3138,7 +3136,7 @@ void MainDialog::updateGridViewData() statusRightNew += _("1 directory"); else { - wxString folderCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(foldersOnRightView)); + wxString folderCount = FreeFileSync::numberToWxString(foldersOnRightView, true); wxString outputString = _("%x directories"); outputString.Replace(wxT("%x"), folderCount, false); @@ -3155,7 +3153,7 @@ void MainDialog::updateGridViewData() statusRightNew += _("1 file,"); else { - wxString fileCount = FreeFileSync::includeNumberSeparator(globalFunctions::numberToWxString(filesOnRightView)); + wxString fileCount = FreeFileSync::numberToWxString(filesOnRightView, true); wxString outputString = _("%x files,"); outputString.Replace(wxT("%x"), fileCount, false); @@ -3383,8 +3381,8 @@ void MainDialog::addFolderPair(const std::vector<FolderPairEnh>& newPairs, bool } //set size of scrolled window - const int visiblePairs = std::min(additionalFolderPairs.size(), MAX_ADD_FOLDER_PAIRS); //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown - m_scrolledWindowFolderPairs->SetMinSize(wxSize( -1, pairHeight * visiblePairs)); + const size_t visiblePairs = std::min(additionalFolderPairs.size(), MAX_ADD_FOLDER_PAIRS); //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown + m_scrolledWindowFolderPairs->SetMinSize(wxSize( -1, pairHeight * static_cast<int>(visiblePairs))); //update controls m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size @@ -3413,7 +3411,7 @@ void MainDialog::removeAddFolderPair(const unsigned int pos) //set size of scrolled window const size_t additionalRows = additionalFolderPairs.size(); if (additionalRows <= MAX_ADD_FOLDER_PAIRS) //up to MAX_ADD_FOLDER_PAIRS additional pairs shall be shown - m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, pairHeight * additionalRows)); + m_scrolledWindowFolderPairs->SetMinSize(wxSize(-1, pairHeight * static_cast<int>(additionalRows))); //update controls m_scrolledWindowFolderPairs->Fit(); //adjust scrolled window size @@ -3586,7 +3584,7 @@ void MainDialog::OnRegularUpdateCheck(wxIdleEvent& event) //execute just once per startup! Disconnect(wxEVT_IDLE, wxIdleEventHandler(MainDialog::OnRegularUpdateCheck), NULL, this); - FreeFileSync::checkForUpdatePeriodically(globalSettings.lastUpdateCheck); + FreeFileSync::checkForUpdatePeriodically(globalSettings.gui.lastUpdateCheck); } @@ -3613,7 +3611,7 @@ void MainDialog::OnMenuAbout(wxCommandEvent& event) void MainDialog::OnShowHelp(wxCommandEvent& event) { -FreeFileSync::displayHelpEntry(); + FreeFileSync::displayHelpEntry(); } @@ -3712,10 +3710,3 @@ bool MainDialog::SyncPreview::synchronizationIsEnabled() const { return synchronizationEnabled; } - - - - - - - diff --git a/ui/MainDialog.h b/ui/MainDialog.h index 7c30f8a3..5f28b36c 100644 --- a/ui/MainDialog.h +++ b/ui/MainDialog.h @@ -121,14 +121,14 @@ private: void updateGridViewData(); //context menu functions - std::set<unsigned int> getSelectedRows(const CustomGrid* grid) const; - std::set<unsigned int> getSelectedRows() const; - void setSyncDirManually(const std::set<unsigned int>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir); - void filterRangeManually(const std::set<unsigned int>& rowsToFilterOnUiTable, const int leadingRow); + std::set<size_t> getSelectedRows(const CustomGrid* grid) const; + std::set<size_t> getSelectedRows() const; + void setSyncDirManually(const std::set<size_t>& rowsToSetOnUiTable, const FreeFileSync::SyncDirection dir); + void filterRangeManually(const std::set<size_t>& rowsToFilterOnUiTable, int leadingRow); void copySelectionToClipboard(const CustomGrid* selectedGrid); void deleteSelectedFiles(); - void openExternalApplication(unsigned int rowNumber, bool leftSide, const wxString& commandline); + void openExternalApplication(size_t rowNumber, bool leftSide, const wxString& commandline); static const int externalAppIDFirst = 1000; //id of first external app item //work to be done in idle time diff --git a/ui/SmallDialogs.cpp b/ui/SmallDialogs.cpp index 346b0ae6..bd90f14d 100644 --- a/ui/SmallDialogs.cpp +++ b/ui/SmallDialogs.cpp @@ -10,7 +10,7 @@ #include "../library/resources.h" #include "../algorithm.h" #include "../shared/stringConv.h" -#include "util.h" +#include "../shared/util.h" #include "../synchronization.h" #include "../library/customGrid.h" #include "../shared/customButton.h" @@ -617,8 +617,7 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parentWindow, SyncPreviewDlgGenerated(parentWindow), m_dontShowAgain(dontShowAgain) { - using FreeFileSync::includeNumberSeparator; - using globalFunctions::numberToWxString; + using FreeFileSync::numberToWxString; m_buttonStartSync->setBitmapFront(GlobalResources::getInstance().getImageByName(wxT("startSync"))); m_bitmapCreate->SetBitmap(GlobalResources::getInstance().getImageByName(wxT("create"))); @@ -629,13 +628,13 @@ SyncPreviewDlg::SyncPreviewDlg(wxWindow* parentWindow, m_staticTextVariant->SetLabel(variantName); m_textCtrlData->SetValue(FreeFileSync::formatFilesizeToShortString(statistics.getDataToProcess())); - m_textCtrlCreateL->SetValue(includeNumberSeparator(numberToWxString(statistics.getCreate( true, false)))); - m_textCtrlUpdateL->SetValue(includeNumberSeparator(numberToWxString(statistics.getOverwrite(true, false)))); - m_textCtrlDeleteL->SetValue(includeNumberSeparator(numberToWxString(statistics.getDelete( true, false)))); + m_textCtrlCreateL->SetValue(numberToWxString(statistics.getCreate( true, false), true)); + m_textCtrlUpdateL->SetValue(numberToWxString(statistics.getOverwrite(true, false), true)); + m_textCtrlDeleteL->SetValue(numberToWxString(statistics.getDelete( true, false), true)); - m_textCtrlCreateR->SetValue(includeNumberSeparator(numberToWxString(statistics.getCreate( false, true)))); - m_textCtrlUpdateR->SetValue(includeNumberSeparator(numberToWxString(statistics.getOverwrite(false, true)))); - m_textCtrlDeleteR->SetValue(includeNumberSeparator(numberToWxString(statistics.getDelete( false, true)))); + m_textCtrlCreateR->SetValue(numberToWxString(statistics.getCreate( false, true), true)); + m_textCtrlUpdateR->SetValue(numberToWxString(statistics.getOverwrite(false, true), true)); + m_textCtrlDeleteR->SetValue(numberToWxString(statistics.getDelete( false, true), true)); m_checkBoxDontShowAgain->SetValue(dontShowAgain); diff --git a/ui/batchStatusHandler.cpp b/ui/batchStatusHandler.cpp index f6e59924..e8b2b31b 100644 --- a/ui/batchStatusHandler.cpp +++ b/ui/batchStatusHandler.cpp @@ -14,6 +14,7 @@ #include "../shared/stringConv.h" #include "../shared/globalFunctions.h" #include "../shared/appMain.h" +#include "../shared/util.h" using namespace FreeFileSync; @@ -108,10 +109,10 @@ private: { //if it's not unique, add a postfix number int postfix = 1; - while (FreeFileSync::fileExists(wxToZ(logfileName + wxT('_') + numberToWxString(postfix) + wxT(".log")))) + while (FreeFileSync::fileExists(wxToZ(logfileName + wxT('_') + FreeFileSync::numberToWxString(postfix, false) + wxT(".log")))) ++postfix; - output = logfileName + wxT('_') + numberToWxString(postfix) + wxT(".log"); + output = logfileName + wxT('_') + numberToWxString(postfix, false) + wxT(".log"); } return output; @@ -183,7 +184,7 @@ BatchStatusHandler::~BatchStatusHandler() if (totalErrors > 0) { wxString header(_("Warning: Synchronization failed for %x item(s):")); - header.Replace(wxT("%x"), globalFunctions::numberToWxString(totalErrors), false); + header.Replace(wxT("%x"), FreeFileSync::numberToWxString(totalErrors, true), false); finalMessage += header + wxT("\n\n"); } @@ -227,7 +228,7 @@ void BatchStatusHandler::initNewProcess(int objectsTotal, wxLongLong dataTotal, switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: - syncStatusFrame.resetGauge(0, 0); //dummy call to initialize some gui elements (remaining time, speed) + syncStatusFrame.resetGauge(0, 0); //initialize some gui elements (remaining time, speed) syncStatusFrame.setCurrentStatus(SyncStatus::SCANNING); break; case StatusHandler::PROCESS_COMPARING_CONTENT: @@ -251,6 +252,7 @@ void BatchStatusHandler::updateProcessedData(int objectsProcessed, wxLongLong da switch (currentProcess) { case StatusHandler::PROCESS_SCANNING: + syncStatusFrame.incScannedObjects_NoUpdate(objectsProcessed); break; case StatusHandler::PROCESS_COMPARING_CONTENT: case StatusHandler::PROCESS_SYNCHRONIZING: @@ -282,12 +284,12 @@ void BatchStatusHandler::reportWarning(const wxString& warningMessage, bool& war { //show popup and ask user how to handle warning bool dontWarnAgain = false; - WarningDlg* warningDlg = new WarningDlg(NULL, - WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, - warningMessage, - dontWarnAgain); - const WarningDlg::Response rv = static_cast<WarningDlg::Response>(warningDlg->ShowModal()); - warningDlg->Destroy(); + WarningDlg warningDlg(NULL, + WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, + warningMessage, + dontWarnAgain); + warningDlg.Raise(); + const WarningDlg::Response rv = static_cast<WarningDlg::Response>(warningDlg.ShowModal()); switch (rv) { case WarningDlg::BUTTON_ABORT: @@ -318,12 +320,12 @@ ErrorHandler::Response BatchStatusHandler::reportError(const wxString& errorMess case xmlAccess::ON_ERROR_POPUP: { bool ignoreNextErrors = false; - ErrorDlg* errorDlg = new ErrorDlg(NULL, - ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, - errorMessage + wxT("\n\n\n") + _("Ignore this error, retry or abort?"), - ignoreNextErrors); - const ErrorDlg::ReturnCodes rv = static_cast<ErrorDlg::ReturnCodes>(errorDlg->ShowModal()); - errorDlg->Destroy(); + ErrorDlg errorDlg(NULL, + ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, + errorMessage + wxT("\n\n\n") + _("Ignore this error, retry or abort?"), + ignoreNextErrors); + errorDlg.Raise(); + const ErrorDlg::ReturnCodes rv = static_cast<ErrorDlg::ReturnCodes>(errorDlg.ShowModal()); switch (rv) { case ErrorDlg::BUTTON_IGNORE: diff --git a/ui/gridView.cpp b/ui/gridView.cpp index 585296a9..4989db3d 100644 --- a/ui/gridView.cpp +++ b/ui/gridView.cpp @@ -227,13 +227,13 @@ GridView::StatusSyncPreview GridView::updateSyncPreview(bool hideFiltered, //map } -void GridView::getAllFileRef(const std::set<unsigned int>& guiRows, std::vector<FileSystemObject*>& output) +void GridView::getAllFileRef(const std::set<size_t>& guiRows, std::vector<FileSystemObject*>& output) { - std::set<unsigned int>::const_iterator upperEnd = guiRows.lower_bound(rowsOnView()); //loop over valid rows only! + std::set<size_t>::const_iterator upperEnd = guiRows.lower_bound(rowsOnView()); //loop over valid rows only! output.clear(); output.reserve(guiRows.size()); - for (std::set<unsigned int>::const_iterator i = guiRows.begin(); i != upperEnd; ++i) + for (std::set<size_t>::const_iterator i = guiRows.begin(); i != upperEnd; ++i) { FileSystemObject* fsObj = getReferencedRow(viewRef[*i]); if (fsObj) @@ -277,10 +277,10 @@ public: void execute(const HierarchyObject& hierObj) { //add file references - std::for_each(hierObj.subFiles.begin(), hierObj.subFiles.end(), *this); + std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), *this); //add dir references - std::for_each(hierObj.subDirs.begin(), hierObj.subDirs.end(), *this); + std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), *this); } void operator()(const FileMapping& fileObj) diff --git a/ui/gridView.h b/ui/gridView.h index 8cd21915..5310eb7e 100644 --- a/ui/gridView.h +++ b/ui/gridView.h @@ -17,13 +17,13 @@ class GridView { public: //direct data access via row number - const FileSystemObject* getObject(unsigned int row) const; //returns NULL if object is not found; logarithmic complexity - FileSystemObject* getObject(unsigned int row); // + const FileSystemObject* getObject(size_t row) const; //returns NULL if object is not found; logarithmic complexity + FileSystemObject* getObject(size_t row); // size_t rowsOnView() const; //only the currently visible elements size_t rowsTotal() const; //total number of rows available //get references to FileSystemObject: no NULL-check needed! Everything's bound. - void getAllFileRef(const std::set<unsigned int>& guiRows, std::vector<FileSystemObject*>& output); + void getAllFileRef(const std::set<size_t>& guiRows, std::vector<FileSystemObject*>& output); struct StatusCmpResult { @@ -180,7 +180,7 @@ private: //inline implementation inline -const FileSystemObject* GridView::getObject(unsigned int row) const +const FileSystemObject* GridView::getObject(size_t row) const { if (row < rowsOnView()) return getReferencedRow(viewRef[row]); @@ -189,7 +189,7 @@ const FileSystemObject* GridView::getObject(unsigned int row) const } inline -FileSystemObject* GridView::getObject(unsigned int row) +FileSystemObject* GridView::getObject(size_t row) { //code re-use of const method: see Meyers Effective C++ return const_cast<FileSystemObject*>(static_cast<const GridView&>(*this).getObject(row)); diff --git a/ui/guiGenerated.cpp b/ui/guiGenerated.cpp index 573c7b1c..90929704 100644 --- a/ui/guiGenerated.cpp +++ b/ui/guiGenerated.cpp @@ -1919,7 +1919,7 @@ SyncCfgDlgGenerated::SyncCfgDlgGenerated( wxWindow* parent, wxWindowID id, const bSizer1151 = new wxBoxSizer( wxHORIZONTAL ); m_textCtrlCustomDelFolder = new wxTextCtrl( m_panelCustomDeletionDir, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - m_textCtrlCustomDelFolder->SetMinSize( wxSize( 160,-1 ) ); + m_textCtrlCustomDelFolder->SetMinSize( wxSize( 200,-1 ) ); bSizer1151->Add( m_textCtrlCustomDelFolder, 1, wxALIGN_CENTER_VERTICAL, 5 ); @@ -2389,9 +2389,10 @@ SyncStatusDlgGenerated::SyncStatusDlgGenerated( wxWindow* parent, wxWindowID id, m_buttonOK = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxSize( 100,32 ), 0 ); m_buttonOK->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); + m_buttonOK->Enable( false ); m_buttonOK->Hide(); - bSizer28->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + bSizer28->Add( m_buttonOK, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 ); m_buttonPause = new wxButton( this, wxID_ANY, _("&Pause"), wxDefaultPosition, wxSize( 100,32 ), 0 ); m_buttonPause->SetFont( wxFont( 10, 74, 90, 90, false, wxT("Tahoma") ) ); @@ -2685,12 +2686,6 @@ AboutDlgGenerated::AboutDlgGenerated( wxWindow* parent, wxWindowID id, const wxS bSizer36->Fit( m_panel5 ); bSizer31->Add( m_panel5, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); - m_staticText15 = new wxStaticText( this, wxID_ANY, _("-Open-Source file synchronization-"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText15->Wrap( -1 ); - m_staticText15->SetFont( wxFont( 8, 74, 90, 92, false, wxT("Tahoma") ) ); - - bSizer31->Add( m_staticText15, 0, wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); - m_build = new wxStaticText( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 ); m_build->Wrap( -1 ); m_build->SetFont( wxFont( 8, 74, 90, 90, false, wxT("Tahoma") ) ); diff --git a/ui/guiGenerated.h b/ui/guiGenerated.h index ff1c4ddc..2c5659b5 100644 --- a/ui/guiGenerated.h +++ b/ui/guiGenerated.h @@ -682,7 +682,6 @@ class AboutDlgGenerated : public wxDialog wxPanel* m_panel5; wxStaticBitmap* m_bitmap11; - wxStaticText* m_staticText15; wxStaticText* m_build; wxScrolledWindow* m_scrolledWindowCodeInfo; diff --git a/ui/guiStatusHandler.cpp b/ui/guiStatusHandler.cpp index bd5f001e..19eccb1c 100644 --- a/ui/guiStatusHandler.cpp +++ b/ui/guiStatusHandler.cpp @@ -12,6 +12,7 @@ #include <wx/wupdlock.h> #include "../shared/globalFunctions.h" #include "../shared/stringConv.h" +#include "../shared/util.h" using namespace FreeFileSync; @@ -27,15 +28,17 @@ CompareStatusHandler::CompareStatusHandler(MainDialog* dlg) : mainDialog->disableAllElements(); //display status panel during compare - mainDialog->compareStatus.init(); //clear old values - mainDialog->compareStatus.getAsWindow()->Show(); + mainDialog->compareStatus.init(); //clear old values and make visible mainDialog->bSizer1->Layout(); //both sizers need to recalculate! mainDialog->bSizer6->Layout(); //adapt layout for wxBitmapWithImage mainDialog->Refresh(); //register abort button - mainDialog->m_buttonAbort->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CompareStatusHandler::OnAbortCompare ), NULL, this ); + mainDialog->m_buttonAbort->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CompareStatusHandler::OnAbortCompare ), NULL, this); + + //register key event + mainDialog->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), NULL, this); } @@ -50,18 +53,32 @@ CompareStatusHandler::~CompareStatusHandler() mainDialog->pushStatusInformation(_("Operation aborted!")); //hide status panel from main window - mainDialog->compareStatus.getAsWindow()->Hide(); + mainDialog->compareStatus.finalize(); mainDialog->bSizer6->Layout(); //adapt layout for wxBitmapWithImage mainDialog->Layout(); mainDialog->Refresh(); + //register key event + mainDialog->Disconnect(wxEVT_CHAR_HOOK, wxKeyEventHandler(CompareStatusHandler::OnKeyPressed), NULL, this); //de-register abort button - mainDialog->m_buttonAbort->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CompareStatusHandler::OnAbortCompare ), NULL, this ); + mainDialog->m_buttonAbort->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CompareStatusHandler::OnAbortCompare ), NULL, this); +} + + +void CompareStatusHandler::OnKeyPressed(wxKeyEvent& event) +{ + const int keyCode = event.GetKeyCode(); + if (keyCode == WXK_ESCAPE) + { + wxCommandEvent dummy; + OnAbortCompare(dummy); + } + + event.Skip(); } -inline void CompareStatusHandler::updateStatusText(const Zstring& text) { mainDialog->compareStatus.setStatusText_NoUpdate(text); @@ -116,10 +133,11 @@ ErrorHandler::Response CompareStatusHandler::reportError(const wxString& message bool ignoreNextErrors = false; const wxString errorMessage = message + wxT("\n\n\n") + _("Ignore this error, retry or abort?"); - ErrorDlg* errorDlg = new ErrorDlg(mainDialog, - ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, - errorMessage, ignoreNextErrors); - switch (static_cast<ErrorDlg::ReturnCodes>(errorDlg->ShowModal())) + ErrorDlg errorDlg(NULL, + ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, + errorMessage, ignoreNextErrors); + errorDlg.Raise(); + switch (static_cast<ErrorDlg::ReturnCodes>(errorDlg.ShowModal())) { case ErrorDlg::BUTTON_IGNORE: ignoreErrors = ignoreNextErrors; @@ -142,10 +160,11 @@ void CompareStatusHandler::reportFatalError(const wxString& errorMessage) mainDialog->compareStatus.updateStatusPanelNow(); bool dummy = false; - ErrorDlg* errorDlg = new ErrorDlg(mainDialog, - ErrorDlg::BUTTON_ABORT, - errorMessage, dummy); - errorDlg->ShowModal(); + ErrorDlg errorDlg(NULL, + ErrorDlg::BUTTON_ABORT, + errorMessage, dummy); + errorDlg.Raise(); + errorDlg.ShowModal(); abortThisProcess(); } @@ -159,11 +178,12 @@ void CompareStatusHandler::reportWarning(const wxString& warningMessage, bool& w //show popup and ask user how to handle warning bool dontWarnAgain = false; - WarningDlg* warningDlg = new WarningDlg(mainDialog, - WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, - warningMessage, - dontWarnAgain); - switch (static_cast<WarningDlg::Response>(warningDlg->ShowModal())) + WarningDlg warningDlg(NULL, + WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, + warningMessage, + dontWarnAgain); + warningDlg.Raise(); + switch (static_cast<WarningDlg::Response>(warningDlg.ShowModal())) { case WarningDlg::BUTTON_ABORT: abortThisProcess(); @@ -197,8 +217,8 @@ void CompareStatusHandler::abortThisProcess() //######################################################################################################## -SyncStatusHandler::SyncStatusHandler(wxWindow* dlg, bool ignoreAllErrors) : - syncStatusFrame(*this, dlg, false), +SyncStatusHandler::SyncStatusHandler(wxTopLevelWindow* parentDlg, bool ignoreAllErrors) : + syncStatusFrame(*this, parentDlg, false), ignoreErrors(ignoreAllErrors) {} @@ -208,9 +228,9 @@ SyncStatusHandler::~SyncStatusHandler() //finalize error log if (abortIsRequested()) - errorLog.logError(wxString(_("Synchronization aborted!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!")); + errorLog.logError(wxString(_("Synchronization aborted!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!")); else if (totalErrors) - errorLog.logWarning(wxString(_("Synchronization completed with errors!")) + wxT(" ") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!")); + errorLog.logWarning(wxString(_("Synchronization completed with errors!")) + wxT(" \n") + _("You may try to synchronize remaining items again (WITHOUT having to re-compare)!")); else errorLog.logInfo(_("Synchronization completed successfully!")); @@ -220,7 +240,7 @@ SyncStatusHandler::~SyncStatusHandler() if (totalErrors > 0) { wxString header(_("Warning: Synchronization failed for %x item(s):")); - header.Replace(wxT("%x"), globalFunctions::numberToWxString(totalErrors), false); + header.Replace(wxT("%x"), FreeFileSync::numberToWxString(totalErrors, true), false); finalMessage += header + wxT("\n\n"); } @@ -283,13 +303,12 @@ ErrorHandler::Response SyncStatusHandler::reportError(const wxString& errorMessa syncStatusFrame.updateStatusDialogNow(); bool ignoreNextErrors = false; - ErrorDlg* errorDlg = new ErrorDlg(NULL, - ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, - errorMessage + wxT("\n\n\n") + _("Ignore this error, retry or abort synchronization?"), - ignoreNextErrors); - const ErrorDlg::ReturnCodes rv = static_cast<ErrorDlg::ReturnCodes>(errorDlg->ShowModal()); - errorDlg->Destroy(); - + ErrorDlg errorDlg(NULL, + ErrorDlg::BUTTON_IGNORE | ErrorDlg::BUTTON_RETRY | ErrorDlg::BUTTON_ABORT, + errorMessage + wxT("\n\n\n") + _("Ignore this error, retry or abort synchronization?"), + ignoreNextErrors); + errorDlg.Raise(); + const ErrorDlg::ReturnCodes rv = static_cast<ErrorDlg::ReturnCodes>(errorDlg.ShowModal()); switch (rv) { case ErrorDlg::BUTTON_IGNORE: @@ -330,13 +349,12 @@ void SyncStatusHandler::reportWarning(const wxString& warningMessage, bool& warn //show popup and ask user how to handle warning bool dontWarnAgain = false; - WarningDlg* warningDlg = new WarningDlg(NULL, - WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, - warningMessage, - dontWarnAgain); - const WarningDlg::Response rv = static_cast<WarningDlg::Response>(warningDlg->ShowModal()); - warningDlg->Destroy(); - + WarningDlg warningDlg(NULL, + WarningDlg::BUTTON_IGNORE | WarningDlg::BUTTON_ABORT, + warningMessage, + dontWarnAgain); + warningDlg.Raise(); + const WarningDlg::Response rv = static_cast<WarningDlg::Response>(warningDlg.ShowModal()); switch (rv) { case WarningDlg::BUTTON_IGNORE: //no unhandled error situation! diff --git a/ui/guiStatusHandler.h b/ui/guiStatusHandler.h index cb64069a..3dab9a85 100644 --- a/ui/guiStatusHandler.h +++ b/ui/guiStatusHandler.h @@ -35,6 +35,7 @@ public: virtual void reportWarning(const wxString& warningMessage, bool& warningActive); private: +void OnKeyPressed(wxKeyEvent& event); void OnAbortCompare(wxCommandEvent& event); //handle abort button click virtual void abortThisProcess(); @@ -47,7 +48,7 @@ private: class SyncStatusHandler : public StatusHandler { public: - SyncStatusHandler(wxWindow* dlg, bool ignoreAllErrors); + SyncStatusHandler(wxTopLevelWindow* parentDlg, bool ignoreAllErrors); ~SyncStatusHandler(); virtual void updateStatusText(const Zstring& text); diff --git a/ui/progressIndicator.cpp b/ui/progressIndicator.cpp index 1ba70888..e2680b0e 100644 --- a/ui/progressIndicator.cpp +++ b/ui/progressIndicator.cpp @@ -10,23 +10,49 @@ #include <wx/stopwatch.h> #include "../library/resources.h" #include "../shared/stringConv.h" -#include "util.h" +#include "../shared/util.h" #include "../library/statistics.h" -#include "../library/statusHandler.h" #include <wx/wupdlock.h> #include "../shared/globalFunctions.h" #include "trayIcon.h" #include <boost/shared_ptr.hpp> +#ifdef FFS_WIN +#include "../shared/taskbar.h" +#endif + using namespace FreeFileSync; -class CompareStatusImpl : public CompareStatusGenerated +namespace +{ +void setNewText(const wxString& newText, wxTextCtrl& control, bool& updateLayout) +{ + if (control.GetValue().length() != newText.length()) + updateLayout = true; //avoid screen flicker: apply only when necessary + + if (control.GetValue() != newText) + control.ChangeValue(newText); +} + +void setNewText(const wxString& newText, wxStaticText& control, bool& updateLayout) +{ + if (control.GetLabel().length() != newText.length()) + updateLayout = true; //avoid screen flicker + + if (control.GetLabel() != newText) + control.SetLabel(newText); +} +} + + +class CompareStatus::CompareStatusImpl : public CompareStatusGenerated { public: - CompareStatusImpl(wxWindow& parentWindow); + CompareStatusImpl(wxTopLevelWindow& parentWindow); - void init(); //initialize all status values + void init(); //make visible, initialize all status values + void finalize(); //hide again void switchToCompareBytewise(int totalObjectsToProcess, wxLongLong totalDataToProcess); void incScannedObjects_NoUpdate(int number); @@ -35,8 +61,11 @@ public: void updateStatusPanelNow(); private: + wxTopLevelWindow& parentWindow_; + wxString titleTextBackup; + //status variables - unsigned int scannedObjects; + size_t scannedObjects; Zstring currentStatusText; wxStopWatch timeElapsed; @@ -48,6 +77,20 @@ private: wxLongLong currentData; double scalingFactor; //nr of elements has to be normalized to smaller nr. because of range of int limitation + void showProgressExternally(const wxString& progressText, float percent = 0); + + enum CurrentStatus + { + SCANNING, + COMPARING_CONTENT, + }; + + CurrentStatus status; + +#ifdef FFS_WIN + std::auto_ptr<Utility::TaskbarProgress> taskbar_; +#endif + //remaining time std::auto_ptr<Statistics> statistics; long lastStatCallSpeed; //used for calculating intervals between statistics update @@ -55,7 +98,7 @@ private: }; //redirect to implementation -CompareStatus::CompareStatus(wxWindow& parentWindow) : +CompareStatus::CompareStatus(wxTopLevelWindow& parentWindow) : pimpl(new CompareStatusImpl(parentWindow)) {} CompareStatus::~CompareStatus() @@ -73,6 +116,11 @@ void CompareStatus::init() pimpl->init(); } +void CompareStatus::finalize() +{ + pimpl->finalize(); +} + void CompareStatus::switchToCompareBytewise(int totalObjectsToProcess, wxLongLong totalDataToProcess) { pimpl->switchToCompareBytewise(totalObjectsToProcess, totalDataToProcess); @@ -100,15 +148,16 @@ void CompareStatus::updateStatusPanelNow() //######################################################################################## -CompareStatusImpl::CompareStatusImpl(wxWindow& parentWindow) : +CompareStatus::CompareStatusImpl::CompareStatusImpl(wxTopLevelWindow& parentWindow) : CompareStatusGenerated(&parentWindow), + parentWindow_(parentWindow), scannedObjects(0), totalObjects(0), totalData(0), currentObjects(0), currentData(0), scalingFactor(0), - statistics(NULL), + status(SCANNING), lastStatCallSpeed(-1000000), //some big number lastStatCallRemTime(-1000000) { @@ -116,8 +165,20 @@ CompareStatusImpl::CompareStatusImpl(wxWindow& parentWindow) : } -void CompareStatusImpl::init() +void CompareStatus::CompareStatusImpl::init() { + titleTextBackup = parentWindow_.GetTitle(); + +#ifdef FFS_WIN + try //try to get access to Windows 7 Taskbar + { + taskbar_.reset(new Utility::TaskbarProgress(parentWindow_)); + } + catch (const Utility::TaskbarNotAvailable&) {} +#endif + + status = SCANNING; + //initialize gauge m_gauge2->SetRange(50000); m_gauge2->SetValue(0); @@ -141,11 +202,26 @@ void CompareStatusImpl::init() timeElapsed.Start(); //measure total time updateStatusPanelNow(); + + Show(); //make visible +} + + +void CompareStatus::CompareStatusImpl::finalize() //hide again +{ +#ifdef FFS_WIN + taskbar_.reset(); +#endif + + Hide(); + parentWindow_.SetTitle(titleTextBackup); } -void CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, wxLongLong totalDataToProcess) +void CompareStatus::CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, wxLongLong totalDataToProcess) { + status = COMPARING_CONTENT; + currentData = 0; totalData = totalDataToProcess; @@ -169,33 +245,74 @@ void CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, wxLon } -void CompareStatusImpl::incScannedObjects_NoUpdate(int number) +void CompareStatus::CompareStatusImpl::incScannedObjects_NoUpdate(int number) { scannedObjects += number; } -void CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsProcessed, wxLongLong dataProcessed) +void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsProcessed, wxLongLong dataProcessed) { currentData += dataProcessed; currentObjects += objectsProcessed; } -void CompareStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void CompareStatus::CompareStatusImpl::setStatusText_NoUpdate(const Zstring& text) { currentStatusText = text; } -void CompareStatusImpl::updateStatusPanelNow() +void CompareStatus::CompareStatusImpl::showProgressExternally(const wxString& progressText, float percent) +{ + if (parentWindow_.GetTitle() != progressText) + parentWindow_.SetTitle(progressText); + + //show progress on Windows 7 taskbar +#ifdef FFS_WIN + using namespace Utility; + + if (taskbar_.get()) + { + const size_t current = 100000 * percent / 100; + const size_t total = 100000; + switch (status) + { + case SCANNING: + taskbar_->setStatus(TaskbarProgress::STATUS_INDETERMINATE); + break; + case COMPARING_CONTENT: + taskbar_->setStatus(TaskbarProgress::STATUS_NORMAL); + taskbar_->setProgress(current, total); + break; + } + } +#endif +} + + +void CompareStatus::CompareStatusImpl::updateStatusPanelNow() { //static RetrieveStatistics statistic; //statistic.writeEntry(currentData, currentObjects); { - wxWindowUpdateLocker dummy(this); //reduce display distortion + //wxWindowUpdateLocker dummy(this) -> not needed + + //write status information to taskbar, parent title ect. + switch (status) + { + case SCANNING: + showProgressExternally(numberToWxString(scannedObjects, true) + wxT(" - ") + _("Scanning...")); + break; + case COMPARING_CONTENT: + showProgressExternally(formatPercentage(currentData, totalData) + wxT(" - ") + _("Comparing content..."), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + } + - bool screenChanged = false; //avoid screen flicker by calling layout() only if necessary + bool updateLayout = false; //avoid screen flicker by calling layout() only if necessary //remove linebreaks from currentStatusText wxString formattedStatusText = zToWx(currentStatusText); @@ -204,26 +321,22 @@ void CompareStatusImpl::updateStatusPanelNow() *i = wxChar(' '); //status texts - if (m_textCtrlStatus->GetValue() != formattedStatusText && (screenChanged = true)) //avoid screen flicker - m_textCtrlStatus->SetValue(formattedStatusText); + if (m_textCtrlStatus->GetValue() != formattedStatusText) //no layout update for status texts! + m_textCtrlStatus->ChangeValue(formattedStatusText); //nr of scanned objects - const wxString scannedObjTmp = globalFunctions::numberToWxString(scannedObjects); - if (m_staticTextScanned->GetLabel() != scannedObjTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextScanned->SetLabel(scannedObjTmp); + setNewText(numberToWxString(scannedObjects, true), *m_staticTextScanned, updateLayout); //progress indicator for "compare file content" m_gauge2->SetValue(int(currentData.ToDouble() * scalingFactor)); //remaining files left for file comparison - const wxString filesToCompareTmp = globalFunctions::numberToWxString(totalObjects - currentObjects); - if (m_staticTextFilesRemaining->GetLabel() != filesToCompareTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextFilesRemaining->SetLabel(filesToCompareTmp); + const wxString filesToCompareTmp = numberToWxString(totalObjects - currentObjects, true); + setNewText(filesToCompareTmp, *m_staticTextFilesRemaining, updateLayout); //remaining bytes left for file comparison const wxString remainingBytesTmp = FreeFileSync::formatFilesizeToShortString(totalData - currentData); - if (m_staticTextDataRemaining->GetLabel() != remainingBytesTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextDataRemaining->SetLabel(remainingBytesTmp); + setNewText(remainingBytesTmp, *m_staticTextDataRemaining, updateLayout); if (statistics.get()) { @@ -234,29 +347,23 @@ void CompareStatusImpl::updateStatusPanelNow() statistics->addMeasurement(currentObjects, currentData.ToDouble()); //current speed - const wxString speedTmp = statistics->getBytesPerSecond(); - if (m_staticTextSpeed->GetLabel() != speedTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextSpeed->SetLabel(speedTmp); + setNewText(statistics->getBytesPerSecond(), *m_staticTextSpeed, updateLayout); if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //call method every two seconds only { lastStatCallRemTime = timeElapsed.Time(); //remaining time - const wxString timeRemainingTmp = statistics->getRemainingTime(); - if (m_staticTextTimeRemaining->GetLabel() != timeRemainingTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextTimeRemaining->SetLabel(timeRemainingTmp); + setNewText(statistics->getRemainingTime(), *m_staticTextTimeRemaining, updateLayout); } } } //time elapsed - const wxString timeElapsedTmp = (wxTimeSpan::Milliseconds(timeElapsed.Time())).Format(); - if (m_staticTextTimeElapsed->GetLabel() != timeElapsedTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextTimeElapsed->SetLabel(timeElapsedTmp); + setNewText(wxTimeSpan::Milliseconds(timeElapsed.Time()).Format(), *m_staticTextTimeElapsed, updateLayout); //do the ui update - if (screenChanged) + if (updateLayout) bSizer42->Layout(); } updateUiNow(); @@ -264,14 +371,15 @@ void CompareStatusImpl::updateStatusPanelNow() //######################################################################################## -class SyncStatusImpl : public SyncStatusDlgGenerated +class SyncStatus::SyncStatusImpl : public SyncStatusDlgGenerated { public: - SyncStatusImpl(StatusHandler& updater, wxWindow* parentWindow); + SyncStatusImpl(StatusHandler& updater, wxTopLevelWindow* parentWindow); ~SyncStatusImpl(); void resetGauge(int totalObjectsToProcess, wxLongLong totalDataToProcess); void incProgressIndicator_NoUpdate(int objectsProcessed, wxLongLong dataProcessed); + void incScannedObjects_NoUpdate(int number); void setStatusText_NoUpdate(const Zstring& text); void updateStatusDialogNow(); @@ -290,11 +398,12 @@ private: void resumeFromSystray(); bool currentProcessIsRunning(); + void showProgressExternally(const wxString& progressText, float percent = 0); //percent may already be included in progressText wxStopWatch timeElapsed; StatusHandler* processStatusHandler; - wxWindow* mainDialog; + wxTopLevelWindow* mainDialog; //gauge variables int totalObjects; @@ -303,21 +412,30 @@ private: wxLongLong currentData; //each data element represents one byte for proper progress indicator scaling double scalingFactor; //nr of elements has to be normalized to smaller nr. because of range of int limitation + //status variables + size_t scannedObjects; Zstring currentStatusText; + bool processPaused; SyncStatus::SyncStatusID currentStatus; +#ifdef FFS_WIN + std::auto_ptr<Utility::TaskbarProgress> taskbar_; +#endif + //remaining time std::auto_ptr<Statistics> statistics; long lastStatCallSpeed; //used for calculating intervals between statistics update long lastStatCallRemTime; // + wxString titelTextBackup; + boost::shared_ptr<MinimizeToTray> minimizedToSysTray; //optional: if filled, hides all visible windows, shows again if destroyed }; //redirect to implementation -SyncStatus::SyncStatus(StatusHandler& updater, wxWindow* parentWindow, bool startSilent) : +SyncStatus::SyncStatus(StatusHandler& updater, wxTopLevelWindow* parentWindow, bool startSilent) : pimpl(new SyncStatusImpl(updater, parentWindow)) { if (startSilent) @@ -349,6 +467,11 @@ void SyncStatus::resetGauge(int totalObjectsToProcess, wxLongLong totalDataToPro pimpl->resetGauge(totalObjectsToProcess, totalDataToProcess); } +void SyncStatus::incScannedObjects_NoUpdate(int number) +{ + pimpl->incScannedObjects_NoUpdate(number); +} + void SyncStatus::incProgressIndicator_NoUpdate(int objectsProcessed, wxLongLong dataProcessed) { pimpl->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); @@ -376,13 +499,13 @@ void SyncStatus::processHasFinished(SyncStatusID id, const wxString& finalMessag //######################################################################################## -SyncStatusImpl::SyncStatusImpl(StatusHandler& updater, wxWindow* parentWindow) : +SyncStatus::SyncStatusImpl::SyncStatusImpl(StatusHandler& updater, wxTopLevelWindow* parentWindow) : SyncStatusDlgGenerated(parentWindow, wxID_ANY, parentWindow ? wxEmptyString : _("FreeFileSync - Folder Comparison and Synchronization"), wxDefaultPosition, wxSize(638, 376), parentWindow ? - wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT : + wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT : //wxTAB_TRAVERSAL is needed for standard button handling: wxID_OK/wxID_CANCEL wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL), processStatusHandler(&updater), mainDialog(parentWindow), @@ -391,12 +514,15 @@ SyncStatusImpl::SyncStatusImpl(StatusHandler& updater, wxWindow* parentWindow) : currentObjects(0), currentData(0), scalingFactor(0), + scannedObjects(0), processPaused(false), currentStatus(SyncStatus::ABORTED), - statistics(NULL), lastStatCallSpeed(-1000000), //some big number lastStatCallRemTime(-1000000) { + if (mainDialog) //save old title (will be used as progress indicator) + titelTextBackup = mainDialog->GetTitle(); + m_animationControl1->SetAnimation(*GlobalResources::getInstance().animationSync); m_animationControl1->Play(); @@ -407,18 +533,26 @@ SyncStatusImpl::SyncStatusImpl(StatusHandler& updater, wxWindow* parentWindow) : m_gauge1->SetRange(50000); m_gauge1->SetValue(0); - m_buttonAbort->SetFocus(); + if (IsShown()) //don't steal focus when starting in sys-tray! + m_buttonAbort->SetFocus(); if (mainDialog) //disable (main) window while this status dialog is shown mainDialog->Disable(); timeElapsed.Start(); //measure total time +#ifdef FFS_WIN + try //try to get access to Windows 7 Taskbar + { + taskbar_.reset(new Utility::TaskbarProgress(mainDialog != NULL ? *mainDialog : *this)); + } + catch (const Utility::TaskbarNotAvailable&) {} +#endif + //hide "processed" statistics until end of process bSizerObjectsProcessed->Show(false); bSizerDataProcessed->Show(false); - SetIcon(*GlobalResources::getInstance().programIcon); //set application icon //register key event @@ -426,21 +560,24 @@ SyncStatusImpl::SyncStatusImpl(StatusHandler& updater, wxWindow* parentWindow) : } -SyncStatusImpl::~SyncStatusImpl() +SyncStatus::SyncStatusImpl::~SyncStatusImpl() { if (mainDialog) { + //restore title text + mainDialog->SetTitle(titelTextBackup); + mainDialog->Enable(); mainDialog->Raise(); mainDialog->SetFocus(); } if (minimizedToSysTray.get()) - minimizedToSysTray->keepHidden(); //avoid window flashing shortly before it is destroyed + minimizedToSysTray->keepHidden(); //prevent window from flashing shortly before it is destroyed } -void SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) +void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) { const int keyCode = event.GetKeyCode(); if (keyCode == WXK_ESCAPE) @@ -450,7 +587,7 @@ void SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) } -void SyncStatusImpl::resetGauge(int totalObjectsToProcess, wxLongLong totalDataToProcess) +void SyncStatus::SyncStatusImpl::resetGauge(int totalObjectsToProcess, wxLongLong totalDataToProcess) { currentData = 0; totalData = totalDataToProcess; @@ -470,52 +607,117 @@ void SyncStatusImpl::resetGauge(int totalObjectsToProcess, wxLongLong totalDataT } -void SyncStatusImpl::incProgressIndicator_NoUpdate(int objectsProcessed, wxLongLong dataProcessed) +void SyncStatus::SyncStatusImpl::incProgressIndicator_NoUpdate(int objectsProcessed, wxLongLong dataProcessed) { currentData += dataProcessed; currentObjects += objectsProcessed; } -void SyncStatusImpl::setStatusText_NoUpdate(const Zstring& text) +void SyncStatus::SyncStatusImpl::incScannedObjects_NoUpdate(int number) { - currentStatusText = text; + scannedObjects += number; } -void SyncStatusImpl::updateStatusDialogNow() +void SyncStatus::SyncStatusImpl::setStatusText_NoUpdate(const Zstring& text) { - //static RetrieveStatistics statistic; - //statistic.writeEntry(currentData, currentObjects); + currentStatusText = text; +} + +void SyncStatus::SyncStatusImpl::showProgressExternally(const wxString& progressText, float percent) +{ //write status information to systray, if window is minimized if (minimizedToSysTray.get()) + minimizedToSysTray->setToolTip(progressText, percent); + //minimizedToSysTray may be a zombie... so set title text anyway + + if (mainDialog) //show percentage in maindialog title (and thereby in taskbar) + { + if (mainDialog->GetTitle() != progressText) + mainDialog->SetTitle(progressText); + } + else //show percentage in this dialog's title (and thereby in taskbar) + { + if (this->GetTitle() != progressText) + this->SetTitle(progressText); + } + +#ifdef FFS_WIN + using namespace Utility; + + //show progress on Windows 7 taskbar + if (taskbar_.get()) + { + const size_t current = 100000 * percent / 100; + const size_t total = 100000; + switch (currentStatus) { case SyncStatus::SCANNING: - minimizedToSysTray->setToolTip(wxString(wxT("FreeFileSync - ")) + wxString(_("Scanning..."))); - //+ wxT(" ") + globalFunctions::numberToWxString(currentObjects)); + taskbar_->setStatus(TaskbarProgress::STATUS_INDETERMINATE); break; + case SyncStatus::FINISHED_WITH_SUCCESS: case SyncStatus::COMPARING_CONTENT: - minimizedToSysTray->setToolTip(wxString(wxT("FreeFileSync - ")) + wxString(_("Comparing content...")) + wxT(" ") + - formatPercentage(currentData, totalData), currentData.ToDouble() * 100 / totalData.ToDouble()); - break; case SyncStatus::SYNCHRONIZING: - minimizedToSysTray->setToolTip(wxString(wxT("FreeFileSync - ")) + wxString(_("Synchronizing...")) + wxT(" ") + - formatPercentage(currentData, totalData), currentData.ToDouble() * 100 / totalData.ToDouble()); + taskbar_->setStatus(TaskbarProgress::STATUS_NORMAL); + taskbar_->setProgress(current, total); + break; + case SyncStatus::PAUSE: + taskbar_->setStatus(TaskbarProgress::STATUS_PAUSED); + taskbar_->setProgress(current, total); break; case SyncStatus::ABORTED: - case SyncStatus::FINISHED_WITH_SUCCESS: case SyncStatus::FINISHED_WITH_ERROR: - case SyncStatus::PAUSE: - minimizedToSysTray->setToolTip(wxT("FreeFileSync")); + taskbar_->setStatus(TaskbarProgress::STATUS_ERROR); + taskbar_->setProgress(current, total); + break; } + } +#endif +} + + +void SyncStatus::SyncStatusImpl::updateStatusDialogNow() +{ + //static RetrieveStatistics statistic; + //statistic.writeEntry(currentData, currentObjects); - //write regular status information (if dialog is visible or not) + //write status information to systray, taskbar, parent title ect. + switch (currentStatus) { - wxWindowUpdateLocker dummy(this); //reduce display distortion + case SyncStatus::SCANNING: + showProgressExternally(numberToWxString(scannedObjects, true) + wxT(" - ") + _("Scanning...")); + break; + case SyncStatus::COMPARING_CONTENT: + showProgressExternally(formatPercentage(currentData, totalData) + wxT(" - ") + _("Comparing content..."), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + case SyncStatus::SYNCHRONIZING: + showProgressExternally(formatPercentage(currentData, totalData) + wxT(" - ") + _("Synchronizing..."), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + case SyncStatus::PAUSE: + showProgressExternally((totalData != 0 ? formatPercentage(currentData, totalData) + wxT(" - ") : wxString()) + _("Paused"), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + case SyncStatus::ABORTED: + showProgressExternally(_("Aborted"), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + case SyncStatus::FINISHED_WITH_SUCCESS: + case SyncStatus::FINISHED_WITH_ERROR: + showProgressExternally(_("Completed"), + currentData.ToDouble() * 100 / totalData.ToDouble()); + break; + } + + //write regular status information (whether dialog is visible or not) + { + //wxWindowUpdateLocker dummy(this); -> not needed - bool screenChanged = false; //avoid screen flicker by calling layout() only if necessary + bool updateLayout = false; //avoid screen flicker by calling layout() only if necessary //progress indicator if (currentStatus == SyncStatus::SCANNING) @@ -525,18 +727,16 @@ void SyncStatusImpl::updateStatusDialogNow() //status text const wxString statusTxt = zToWx(currentStatusText); - if (m_textCtrlInfo->GetValue() != statusTxt && (screenChanged = true)) //avoid screen flicker - m_textCtrlInfo->SetValue(statusTxt); + if (m_textCtrlInfo->GetValue() != statusTxt) //no layout update for status texts! + m_textCtrlInfo->ChangeValue(statusTxt); //remaining objects - const wxString remainingObjTmp = globalFunctions::numberToWxString(totalObjects - currentObjects); - if (m_staticTextRemainingObj->GetLabel() != remainingObjTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextRemainingObj->SetLabel(remainingObjTmp); + const wxString remainingObjTmp = numberToWxString(totalObjects - currentObjects, true); + setNewText(remainingObjTmp, *m_staticTextRemainingObj, updateLayout); //remaining bytes left for copy const wxString remainingBytesTmp = FreeFileSync::formatFilesizeToShortString(totalData - currentData); - if (m_staticTextDataRemaining->GetLabel() != remainingBytesTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextDataRemaining->SetLabel(remainingBytesTmp); + setNewText(remainingBytesTmp, *m_staticTextDataRemaining, updateLayout); if (statistics.get()) { @@ -547,53 +747,47 @@ void SyncStatusImpl::updateStatusDialogNow() statistics->addMeasurement(currentObjects, currentData.ToDouble()); //current speed - const wxString speedTmp = statistics->getBytesPerSecond(); - if (m_staticTextSpeed->GetLabel() != speedTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextSpeed->SetLabel(speedTmp); + setNewText(statistics->getBytesPerSecond(), *m_staticTextSpeed, updateLayout); if (timeElapsed.Time() - lastStatCallRemTime >= 2000) //call method every two seconds only { lastStatCallRemTime = timeElapsed.Time(); //remaining time - const wxString timeRemainingTmp = statistics->getRemainingTime(); - if (m_staticTextTimeRemaining->GetLabel() != timeRemainingTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextTimeRemaining->SetLabel(timeRemainingTmp); + setNewText(statistics->getRemainingTime(), *m_staticTextTimeRemaining, updateLayout); } } } //time elapsed - const wxString timeElapsedTmp = wxTimeSpan::Milliseconds(timeElapsed.Time()).Format(); - if (m_staticTextTimeElapsed->GetLabel() != timeElapsedTmp && (screenChanged = true)) //avoid screen flicker - m_staticTextTimeElapsed->SetLabel(timeElapsedTmp); - + setNewText(wxTimeSpan::Milliseconds(timeElapsed.Time()).Format(), *m_staticTextTimeElapsed, updateLayout); //do the ui update - if (screenChanged) + if (updateLayout) { bSizer28->Layout(); bSizer31->Layout(); } } - updateUiNow(); -//support for pause button + //support for pause button while (processPaused && currentProcessIsRunning()) { wxMilliSleep(UI_UPDATE_INTERVAL); updateUiNow(); } + + updateUiNow(); } -bool SyncStatusImpl::currentProcessIsRunning() +bool SyncStatus::SyncStatusImpl::currentProcessIsRunning() { return processStatusHandler != NULL; } -void SyncStatusImpl::setCurrentStatus(SyncStatus::SyncStatusID id) +void SyncStatus::SyncStatusImpl::setCurrentStatus(SyncStatus::SyncStatusID id) { switch (id) { @@ -638,7 +832,7 @@ void SyncStatusImpl::setCurrentStatus(SyncStatus::SyncStatusID id) } -void SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const wxString& finalMessage) //essential to call this in StatusHandler derived class destructor +void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const wxString& finalMessage) //essential to call this in StatusHandler derived class destructor { //at the LATEST(!) to prevent access to currentStatusHandler //enable okay and close events; may be set in this method ONLY @@ -654,7 +848,10 @@ void SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const wxStr m_buttonPause->Disable(); m_buttonPause->Hide(); m_buttonOK->Show(); - m_buttonOK->SetFocus(); + m_buttonOK->Enable(); + + if (IsShown()) //don't steal focus when residing in sys-tray! + m_buttonOK->SetFocus(); m_animationControl1->Stop(); m_animationControl1->Hide(); @@ -676,7 +873,7 @@ void SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const wxStr bSizerObjectsProcessed->Show(true); bSizerDataProcessed ->Show(true); - m_staticTextProcessedObj->SetLabel(globalFunctions::numberToWxString(currentObjects)); + m_staticTextProcessedObj->SetLabel(numberToWxString(currentObjects, true)); m_staticTextDataProcessed->SetLabel(FreeFileSync::formatFilesizeToShortString(currentData)); } } @@ -684,16 +881,24 @@ void SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, const wxStr updateStatusDialogNow(); //keep this sequence to avoid display distortion, if e.g. only 1 item is sync'ed m_textCtrlInfo->SetValue(finalMessage); // Layout(); // + + Raise(); +} + + +void SyncStatus::SyncStatusImpl::OnOkay(wxCommandEvent& event) +{ + Close(); //generate close event: do NOT destroy window unconditionally! } -void SyncStatusImpl::OnOkay(wxCommandEvent& event) +void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event) { - if (!currentProcessIsRunning()) Destroy(); + Close(); //generate close event: do NOT destroy window unconditionally! } -void SyncStatusImpl::OnPause(wxCommandEvent& event) +void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event) { static SyncStatus::SyncStatusID previousStatus = SyncStatus::ABORTED; @@ -726,7 +931,7 @@ void SyncStatusImpl::OnPause(wxCommandEvent& event) } -void SyncStatusImpl::OnAbort(wxCommandEvent& event) +void SyncStatus::SyncStatusImpl::OnClose(wxCloseEvent& event) { processPaused = false; if (currentProcessIsRunning()) @@ -741,33 +946,25 @@ void SyncStatusImpl::OnAbort(wxCommandEvent& event) processStatusHandler->requestAbortion(); } -} - - -void SyncStatusImpl::OnClose(wxCloseEvent& event) -{ - processPaused = false; - if (processStatusHandler) - processStatusHandler->requestAbortion(); else Destroy(); } -void SyncStatusImpl::OnIconize(wxIconizeEvent& event) +void SyncStatus::SyncStatusImpl::OnIconize(wxIconizeEvent& event) { if (event.Iconized()) //ATTENTION: iconize event is also triggered on "Restore"! (at least under Linux) minimizeToTray(); } -void SyncStatusImpl::minimizeToTray() +void SyncStatus::SyncStatusImpl::minimizeToTray() { minimizedToSysTray.reset(new MinimizeToTray(this, mainDialog)); } -void SyncStatusImpl::resumeFromSystray() +void SyncStatus::SyncStatusImpl::resumeFromSystray() { minimizedToSysTray.reset(); } diff --git a/ui/progressIndicator.h b/ui/progressIndicator.h index 78044653..b6964fe6 100644 --- a/ui/progressIndicator.h +++ b/ui/progressIndicator.h @@ -8,22 +8,20 @@ #define PROGRESSINDICATOR_H_INCLUDED #include "../shared/zstring.h" -#include <wx/window.h> - -class CompareStatusImpl; -class SyncStatusImpl; -class StatusHandler; +#include <wx/toplevel.h> +#include "../library/statusHandler.h" class CompareStatus { public: - CompareStatus(wxWindow& parentWindow); //CompareStatus will be owned by parentWindow! + CompareStatus(wxTopLevelWindow& parentWindow); //CompareStatus will be owned by parentWindow! ~CompareStatus(); wxWindow* getAsWindow(); //convenience! don't abuse! - void init(); //initialize all status values + void init(); //make visible, initialize all status values + void finalize(); //hide again void switchToCompareBytewise(int totalObjectsToProcess, wxLongLong totalDataToProcess); void incScannedObjects_NoUpdate(int number); @@ -32,6 +30,7 @@ public: void updateStatusPanelNow(); private: + class CompareStatusImpl; CompareStatusImpl* const pimpl; }; @@ -40,7 +39,7 @@ class SyncStatus { public: SyncStatus(StatusHandler& updater, - wxWindow* parentWindow, //may be NULL + wxTopLevelWindow* parentWindow, //may be NULL bool startSilent); ~SyncStatus(); @@ -58,6 +57,7 @@ public: }; void resetGauge(int totalObjectsToProcess, wxLongLong totalDataToProcess); + void incScannedObjects_NoUpdate(int number); void incProgressIndicator_NoUpdate(int objectsProcessed, wxLongLong dataProcessed); void setStatusText_NoUpdate(const Zstring& text); void updateStatusDialogNow(); @@ -70,6 +70,7 @@ public: void closeWindowDirectly(); //don't wait for user private: + class SyncStatusImpl; SyncStatusImpl* const pimpl; }; diff --git a/ui/search.cpp b/ui/search.cpp index 494be608..418ef2ac 100644 --- a/ui/search.cpp +++ b/ui/search.cpp @@ -198,11 +198,15 @@ void executeSearch(bool forceShowDialog, wxGrid& leftGrid, wxGrid& rightGrid) { + bool searchDialogWasShown = false; + if (forceShowDialog || lastSearchString.IsEmpty()) { SearchDlg* searchDlg = new SearchDlg(parentWindow, lastSearchString, respectCase); //wxWidgets deletion handling -> deleted by parentWindow if (static_cast<SearchDlg::ReturnCodes>(searchDlg->ShowModal()) != SearchDlg::BUTTON_OKAY) return; + + searchDialogWasShown = true; } wxGrid* targetGrid = NULL; //filled if match is found @@ -246,7 +250,8 @@ void executeSearch(bool forceShowDialog, wxMessageBox(messageNotFound, _("Find"), wxOK); //show search dialog again - executeSearch(true, respectCase, parentWindow, leftGrid, rightGrid); + if (searchDialogWasShown) + executeSearch(true, respectCase, parentWindow, leftGrid, rightGrid); } } //########################################################################################### diff --git a/ui/settingsDialog.cpp b/ui/settingsDialog.cpp index 754f9e01..5199b987 100644 --- a/ui/settingsDialog.cpp +++ b/ui/settingsDialog.cpp @@ -11,7 +11,7 @@ #include "../shared/customButton.h" #include "../synchronization.h" #include "../shared/stringConv.h" -#include "util.h" +#include "../shared/util.h" #include <wx/dnd.h> #include "../shared/dragAndDrop.h" #include "../shared/fileHandling.h" @@ -874,10 +874,9 @@ void BatchDialog::showNotebookpage(wxWindow* page, const wxString& pageName, boo { int windowPosition = -1; for (size_t i = 0; i < m_notebookSettings->GetPageCount(); ++i) - if ( static_cast<wxWindow*>(m_notebookSettings->GetPage(i)) == - static_cast<wxWindow*>(page)) + if (m_notebookSettings->GetPage(i) == page) { - windowPosition = i; + windowPosition = static_cast<int>(i); break; } @@ -1260,8 +1259,8 @@ void BatchDialog::addFolderPair(const std::vector<FreeFileSync::FolderPairEnh>& i->localFilter); } //set size of scrolled window - const int visiblePairs = std::min(additionalFolderPairs.size() + 1, MAX_FOLDER_PAIRS); //up to MAX_FOLDER_PAIRS pairs shall be shown - m_scrolledWindow6->SetMinSize(wxSize( -1, pairHeight * visiblePairs)); + const size_t visiblePairs = std::min(additionalFolderPairs.size() + 1, MAX_FOLDER_PAIRS); //up to MAX_FOLDER_PAIRS pairs shall be shown + m_scrolledWindow6->SetMinSize(wxSize( -1, pairHeight * static_cast<int>(visiblePairs))); //update controls m_scrolledWindow6->Fit(); //adjust scrolled window size @@ -1291,8 +1290,8 @@ void BatchDialog::removeAddFolderPair(const int pos) additionalFolderPairs.erase(additionalFolderPairs.begin() + pos); //remove last element in vector //set size of scrolled window - const int visiblePairs = std::min(additionalFolderPairs.size() + 1, MAX_FOLDER_PAIRS); //up to MAX_FOLDER_PAIRS pairs shall be shown - m_scrolledWindow6->SetMinSize(wxSize(-1, pairHeight * visiblePairs)); + const size_t visiblePairs = std::min(additionalFolderPairs.size() + 1, MAX_FOLDER_PAIRS); //up to MAX_FOLDER_PAIRS pairs shall be shown + m_scrolledWindow6->SetMinSize(wxSize(-1, pairHeight * static_cast<int>(visiblePairs))); //update controls m_scrolledWindow6->Fit(); //adjust scrolled window size diff --git a/ui/trayIcon.cpp b/ui/trayIcon.cpp index b7f74d1d..554309ca 100644 --- a/ui/trayIcon.cpp +++ b/ui/trayIcon.cpp @@ -123,7 +123,7 @@ private: //event handling contextMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MinimizeToTray::OnContextMenuSelection), NULL, parent_); - return contextMenu; //ownership transferred to library + return contextMenu; //ownership transferred to caller } MinimizeToTray* parent_; @@ -167,12 +167,12 @@ void MinimizeToTray::resumeFromTray() //remove trayIcon and restore windows: Mi } trayIcon->RemoveIcon(); //hide icon until final deletion takes place trayIcon->Disconnect(wxEVT_TASKBAR_LEFT_DCLICK, wxCommandEventHandler(MinimizeToTray::OnDoubleClick), NULL, this); + trayIcon->parentHasDied(); //TaskBarImpl (potentially) has longer lifetime than MinimizeToTray: avoid callback! //use wxWidgets delayed destruction: delete during next idle loop iteration (handle late window messages, e.g. when double-clicking) if (!wxPendingDelete.Member(trayIcon)) wxPendingDelete.Append(trayIcon); - trayIcon->parentHasDied(); //TaskBarImpl (potentially) has longer lifetime than MinimizeToTray: avoid callback! trayIcon = NULL; //avoid reentrance } } diff --git a/ui/util.cpp b/ui/util.cpp deleted file mode 100644 index c611e252..00000000 --- a/ui/util.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** -// -#include "util.h" -#include <wx/scrolwin.h> -#include <wx/textctrl.h> -#include <wx/combobox.h> -#include <wx/filepicker.h> -#include "../shared/globalFunctions.h" -#include "../shared/localization.h" -#include "../shared/fileHandling.h" -#include "../shared/stringConv.h" -#include <stdexcept> -#include "../shared/systemFunctions.h" - -#ifdef FFS_WIN -#include <wx/msw/wrapwin.h> //includes "windows.h" -#endif - - -wxString FreeFileSync::formatFilesizeToShortString(const wxLongLong& filesize) -{ - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); -} - - -wxString FreeFileSync::formatFilesizeToShortString(const wxULongLong& filesize) -{ - return FreeFileSync::formatFilesizeToShortString(filesize.ToDouble()); -} - - -wxString FreeFileSync::formatFilesizeToShortString(const double filesize) -{ - if (filesize < 0) - return _("Error"); - - if (filesize <= 999) - return wxString::Format(wxT("%i"), static_cast<int>(filesize)) + _(" Byte"); //no decimal places in case of bytes - - double nrOfBytes = filesize; - - nrOfBytes /= 1024; - wxString unit = _(" kB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" MB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" GB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" TB"); - if (nrOfBytes > 999) - { - nrOfBytes /= 1024; - unit = _(" PB"); - } - } - } - } - - //print just three significant digits: 0,01 | 0,11 | 1,11 | 11,1 | 111 - - const unsigned int leadDigitCount = globalFunctions::getDigitCount(static_cast<unsigned int>(nrOfBytes)); //number of digits before decimal point - if (leadDigitCount == 0 || leadDigitCount > 3) - return _("Error"); - - if (leadDigitCount == 3) - return wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes)) + unit; - else if (leadDigitCount == 2) - { - wxString output = wxString::Format(wxT("%i"), static_cast<int>(nrOfBytes * 10)); - output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); - return output + unit; - } - else //leadDigitCount == 1 - { - wxString output = wxString::Format(wxT("%03i"), static_cast<int>(nrOfBytes * 100)); - output.insert(leadDigitCount, FreeFileSync::DECIMAL_POINT); - return output + unit; - } - - //return wxString::Format(wxT("%.*f"), 3 - leadDigitCount, nrOfBytes) + unit; -} - - -wxString FreeFileSync::formatPercentage(const wxLongLong& dividend, const wxLongLong& divisor) -{ - const double ratio = divisor != 0 ? dividend.ToDouble() * 100 / divisor.ToDouble() : 0; - wxString output = _("%x Percent"); - output.Replace(wxT("%x"), wxString::Format(wxT("%3.2f"), ratio), false); - return output; -} - - - -wxString FreeFileSync::includeNumberSeparator(const wxString& number) -{ - wxString output(number); - for (int i = output.size() - 3; i > 0; i -= 3) - output.insert(i, FreeFileSync::THOUSANDS_SEPARATOR); - - return output; -} - - -template <class T> -void setDirectoryNameImpl(const wxString& dirname, T* txtCtrl, wxDirPickerCtrl* dirPicker) -{ - using namespace FreeFileSync; - - txtCtrl->SetValue(dirname); - const Zstring leftDirFormatted = FreeFileSync::getFormattedDirectoryName(wxToZ(dirname)); - if (FreeFileSync::dirExists(leftDirFormatted)) - dirPicker->SetPath(zToWx(leftDirFormatted)); -} - - -void FreeFileSync::setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker) -{ - setDirectoryNameImpl(dirname, txtCtrl, dirPicker); -} - - -void FreeFileSync::setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker) -{ - txtCtrl->SetSelection(wxNOT_FOUND); - setDirectoryNameImpl(dirname, txtCtrl, dirPicker); -} - - -void FreeFileSync::scrollToBottom(wxScrolledWindow* scrWindow) -{ - int height = 0; - scrWindow->GetClientSize(NULL, &height); - - int pixelPerLine = 0; - scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine); - - if (height > 0 && pixelPerLine > 0) - { - const int scrollLinesTotal = scrWindow->GetScrollLines(wxVERTICAL); - const int scrollLinesOnScreen = height / pixelPerLine; - const int scrollPosBottom = scrollLinesTotal - scrollLinesOnScreen; - - if (0 <= scrollPosBottom) - scrWindow->Scroll(0, scrollPosBottom); - } -} - - - - - -inline -void writeTwoDigitNumber(unsigned int number, wxString& string) -{ - assert (number < 100); - - string += '0' + number / 10; - string += '0' + number % 10; -} - - -inline -void writeFourDigitNumber(unsigned int number, wxString& string) -{ - assert (number < 10000); - - string += '0' + number / 1000; - number %= 1000; - string += '0' + number / 100; - number %= 100; - string += '0' + number / 10; - number %= 10; - string += '0' + number; -} - - -wxString FreeFileSync::utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename) -{ -#ifdef FFS_WIN - //convert ansi C time to FILETIME - wxLongLong fileTimeLong(utcTime); - - fileTimeLong += wxLongLong(2, 3054539008UL); //timeshift between ansi C time and FILETIME in seconds == 11644473600s - fileTimeLong *= 10000000; - - FILETIME lastWriteTimeUtc; - lastWriteTimeUtc.dwLowDateTime = fileTimeLong.GetLo(); //GetLo() returns unsigned - lastWriteTimeUtc.dwHighDateTime = unsigned(fileTimeLong.GetHi()); //GetHi() returns signed - - - FILETIME localFileTime; - if (::FileTimeToLocalFileTime( //convert to local time - &lastWriteTimeUtc, //pointer to UTC file time to convert - &localFileTime //pointer to converted file time - ) == 0) - throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" FILETIME -> local FILETIME: ") + - wxT("(") + wxULongLong(lastWriteTimeUtc.dwHighDateTime, lastWriteTimeUtc.dwLowDateTime).ToString() + wxT(") ") + - filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); - - if (localFileTime.dwHighDateTime > 0x7fffffff) - return _("Error"); //this actually CAN happen if UTC time is just below this border and ::FileTimeToLocalFileTime() adds 2 hours due to DST or whatever! - //Testcase (UTC): dateHigh = 2147483647 (=0x7fffffff) -> year 30000 - // dateLow = 4294967295 - - SYSTEMTIME time; - if (::FileTimeToSystemTime( - &localFileTime, //pointer to file time to convert - &time //pointer to structure to receive system time - ) == 0) - throw std::runtime_error(std::string((wxString(_("Conversion error:")) + wxT(" local FILETIME -> SYSTEMTIME: ") + - wxT("(") + wxULongLong(localFileTime.dwHighDateTime, localFileTime.dwLowDateTime).ToString() + wxT(") ") + - filename.c_str() + wxT("\n\n") + getLastErrorFormatted()).ToAscii())); - - //assemble time string (performance optimized) - wxString formattedTime; - formattedTime.reserve(20); - - writeFourDigitNumber(time.wYear, formattedTime); - formattedTime += wxChar('-'); - writeTwoDigitNumber(time.wMonth, formattedTime); - formattedTime += wxChar('-'); - writeTwoDigitNumber(time.wDay, formattedTime); - formattedTime += wxChar(' '); - formattedTime += wxChar(' '); - writeTwoDigitNumber(time.wHour, formattedTime); - formattedTime += wxChar(':'); - writeTwoDigitNumber(time.wMinute, formattedTime); - formattedTime += wxChar(':'); - writeTwoDigitNumber(time.wSecond, formattedTime); - - return formattedTime; - -#elif defined FFS_LINUX - tm* timeinfo; - const time_t fileTime = utcTime.ToLong(); - timeinfo = localtime(&fileTime); //convert to local time - char buffer[50]; - strftime(buffer, 50, "%Y-%m-%d %H:%M:%S", timeinfo); - - return zToWx(buffer); -#endif -} diff --git a/ui/util.h b/ui/util.h deleted file mode 100644 index de986554..00000000 --- a/ui/util.h +++ /dev/null @@ -1,38 +0,0 @@ -// ************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * -// ************************************************************************** -// -#ifndef UTIL_H_INCLUDED -#define UTIL_H_INCLUDED - -#include "../shared/zstring.h" -#include <wx/string.h> -#include <wx/longlong.h> - -class wxComboBox; -class wxTextCtrl; -class wxDirPickerCtrl; -class wxScrolledWindow; - - -namespace FreeFileSync -{ -wxString formatFilesizeToShortString(const wxLongLong& filesize); -wxString formatFilesizeToShortString(const wxULongLong& filesize); -wxString formatFilesizeToShortString(const double filesize); - -wxString formatPercentage(const wxLongLong& dividend, const wxLongLong& divisor); - -wxString includeNumberSeparator(const wxString& number); - -void setDirectoryName(const wxString& dirname, wxTextCtrl* txtCtrl, wxDirPickerCtrl* dirPicker); -void setDirectoryName(const wxString& dirname, wxComboBox* txtCtrl, wxDirPickerCtrl* dirPicker); -void scrollToBottom(wxScrolledWindow* scrWindow); - -wxString utcTimeToLocalString(const wxLongLong& utcTime, const Zstring& filename); -} - - -#endif // UTIL_H_INCLUDED |