diff options
Diffstat (limited to 'ui/progress_indicator.cpp')
-rw-r--r-- | ui/progress_indicator.cpp | 560 |
1 files changed, 341 insertions, 219 deletions
diff --git a/ui/progress_indicator.cpp b/ui/progress_indicator.cpp index 092cb182..03ec9ca0 100644 --- a/ui/progress_indicator.cpp +++ b/ui/progress_indicator.cpp @@ -23,7 +23,7 @@ #include "../lib/statistics.h" #include "tray_icon.h" #include "taskbar.h" - +#include "exec_finished_box.h" using namespace zen; @@ -43,12 +43,14 @@ class CompareStatus::CompareStatusImpl : public CompareStatusGenerated public: CompareStatusImpl(wxTopLevelWindow& parentWindow); - void init(); //make visible, initialize all status values - void finalize(); //hide again + void init(); //constructor/destructor semantics, but underlying Window is reused + void finalize(); // - void switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess); + void switchToCompareBytewise(int totalObjectsToProcess, Int64 totalDataToProcess); void incScannedObjects_NoUpdate(int number); - void incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); + void incProcessedCmpData_NoUpdate(int objectsProcessed, Int64 dataProcessed); + void incTotalCmpData_NoUpdate (int objectsProcessed, Int64 dataProcessed); + void setStatusText_NoUpdate(const wxString& text); void updateStatusPanelNow(); @@ -63,10 +65,10 @@ private: wxStopWatch timeElapsed; //gauge variables - int totalObjects; - zen::Int64 totalData; //each data element represents one byte for proper progress indicator scaling - int currentObjects; //each object represents a file or directory processed - zen::Int64 currentData; + int totalObjects; //file/dir/symlink/operation count + Int64 totalData; //unit: [bytes] + int currentObjects; + Int64 currentData; void showProgressExternally(const wxString& progressText, double fraction = 0); //between [0, 1] @@ -87,56 +89,6 @@ private: long lastStatCallRemTime; // }; -//redirect to implementation -CompareStatus::CompareStatus(wxTopLevelWindow& parentWindow) : - pimpl(new CompareStatusImpl(parentWindow)) {} - -CompareStatus::~CompareStatus() -{ - //DON'T delete pimpl! it relies on wxWidgets destruction (parent window destroys child windows!) -} - -wxWindow* CompareStatus::getAsWindow() -{ - return pimpl; -} - -void CompareStatus::init() -{ - pimpl->init(); -} - -void CompareStatus::finalize() -{ - pimpl->finalize(); -} - -void CompareStatus::switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess) -{ - pimpl->switchToCompareBytewise(totalObjectsToProcess, totalDataToProcess); -} - -void CompareStatus::incScannedObjects_NoUpdate(int number) -{ - pimpl->incScannedObjects_NoUpdate(number); -} - -void CompareStatus::incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed) -{ - pimpl->incProcessedCmpData_NoUpdate(objectsProcessed, dataProcessed); -} - -void CompareStatus::setStatusText_NoUpdate(const wxString& text) -{ - pimpl->setStatusText_NoUpdate(text); -} - -void CompareStatus::updateStatusPanelNow() -{ - pimpl->updateStatusPanelNow(); -} -//######################################################################################## - CompareStatus::CompareStatusImpl::CompareStatusImpl(wxTopLevelWindow& parentWindow) : CompareStatusGenerated(&parentWindow), @@ -171,10 +123,10 @@ void CompareStatus::CompareStatusImpl::init() m_gauge2->SetValue(0); //initially hide status that's relevant for comparing bytewise only - bSizerFilesFound->Show(true); + bSizerFilesFound ->Show(true); bSizerFilesRemaining->Show(false); - sSizerSpeed->Show(false); - sSizerTimeRemaining->Show(false); + sSizerSpeed ->Show(false); + sSizerTimeRemaining ->Show(false); m_gauge2->Hide(); bSizer42->Layout(); @@ -197,21 +149,20 @@ void CompareStatus::CompareStatusImpl::init() } -void CompareStatus::CompareStatusImpl::finalize() //hide again +void CompareStatus::CompareStatusImpl::finalize() { taskbar_.reset(); parentWindow_.SetTitle(titleTextBackup); } -void CompareStatus::CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess) +void CompareStatus::CompareStatusImpl::switchToCompareBytewise(int totalObjectsToProcess, Int64 totalDataToProcess) { status = COMPARING_CONTENT; - currentData = 0; - totalData = totalDataToProcess; - + currentData = 0; currentObjects = 0; + totalData = totalDataToProcess; totalObjects = totalObjectsToProcess; //set new statistics handler: 10 seconds "window" for remaining time, 5 seconds for speed @@ -237,10 +188,20 @@ void CompareStatus::CompareStatusImpl::incScannedObjects_NoUpdate(int number) } -void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed) +void CompareStatus::CompareStatusImpl::incProcessedCmpData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + currentData += dataDelta; + currentObjects += objectsDelta; +} + + +void CompareStatus::CompareStatusImpl::incTotalCmpData_NoUpdate(int objectsDelta, Int64 dataDelta) { - currentData += dataProcessed; - currentObjects += objectsProcessed; + totalData += dataDelta; + totalObjects += objectsDelta; + + if (statistics) + statistics->setNewTotal(totalObjects, to<double>(totalData)); } @@ -279,7 +240,7 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() //wxWindowUpdateLocker dummy(this) -> not needed //add both data + obj-count, to handle "deletion-only" cases - const double fraction = totalData + totalObjects == 0 ? 0 : to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects); + const double fraction = totalData + totalObjects == 0 ? 0 : std::max(0.0, to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects)); //write status information to taskbar, parent title ect. switch (status) @@ -313,7 +274,7 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() setText(*m_staticTextFilesRemaining, filesToCompareTmp, &layoutChanged); //remaining bytes left for file comparison - const wxString remainingBytesTmp = zen::filesizeToShortString(to<zen::UInt64>(totalData - currentData)); + const wxString remainingBytesTmp = zen::filesizeToShortString(totalData - currentData); setText(*m_staticTextDataRemaining, remainingBytesTmp, &layoutChanged); if (statistics.get()) @@ -338,7 +299,11 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() } //time elapsed - setText(*m_staticTextTimeElapsed, wxTimeSpan::Milliseconds(timeElapsed.Time()).Format(), &layoutChanged); + const long timeElapSec = timeElapsed.Time() / 1000; + setText(*m_staticTextTimeElapsed, + timeElapSec < 3600 ? + wxTimeSpan::Seconds(timeElapSec).Format( L"%M:%S") : + wxTimeSpan::Seconds(timeElapSec).Format(L"%H:%M:%S"), &layoutChanged); //do the ui update if (layoutChanged) @@ -348,6 +313,60 @@ void CompareStatus::CompareStatusImpl::updateStatusPanelNow() } //######################################################################################## +//redirect to implementation +CompareStatus::CompareStatus(wxTopLevelWindow& parentWindow) : + pimpl(new CompareStatusImpl(parentWindow)) {} + +CompareStatus::~CompareStatus() +{ + //DON'T delete pimpl! it relies on wxWidgets destruction (parent window destroys child windows!) +} + +wxWindow* CompareStatus::getAsWindow() +{ + return pimpl; +} + +void CompareStatus::init() +{ + pimpl->init(); +} + +void CompareStatus::finalize() +{ + pimpl->finalize(); +} + +void CompareStatus::switchToCompareBytewise(int totalObjectsToProcess, zen::Int64 totalDataToProcess) +{ + pimpl->switchToCompareBytewise(totalObjectsToProcess, totalDataToProcess); +} + +void CompareStatus::incScannedObjects_NoUpdate(int number) +{ + pimpl->incScannedObjects_NoUpdate(number); +} + +void CompareStatus::incProcessedCmpData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + pimpl->incProcessedCmpData_NoUpdate(objectsDelta, dataDelta); +} + +void CompareStatus::incTotalCmpData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + pimpl->incTotalCmpData_NoUpdate(objectsDelta, dataDelta); +} + +void CompareStatus::setStatusText_NoUpdate(const wxString& text) +{ + pimpl->setStatusText_NoUpdate(text); +} + +void CompareStatus::updateStatusPanelNow() +{ + pimpl->updateStatusPanelNow(); +} +//######################################################################################## namespace { @@ -497,6 +516,9 @@ public: void pauseTimer () { timer.Pause(); } void resumeTimer() { timer.Resume(); } + virtual double getXBegin() const { return 0; } //{ return data.empty() ? 0 : data.begin()->first / 1000.0; } + virtual double getXEnd () const { return data.empty() ? 0 : (--data.end())->first / 1000.0; } + private: static const size_t MAX_BUFFER_SIZE = 2500000; //sizeof(single node) worst case ~ 3 * 8 byte ptr + 16 byte key/value = 40 byte @@ -507,8 +529,6 @@ private: return data.empty() ? 0 : (--data.end())->second; return iter->second; } - virtual double getXBegin() const { return 0; } //{ return data.empty() ? 0 : data.begin()->first / 1000.0; } - virtual double getXEnd () const { return data.empty() ? 0 : (--data.end())->first / 1000.0; } //example: two-element range is accessible within [0, 2) wxStopWatch timer; @@ -516,6 +536,22 @@ private: }; +class GraphDataConstLine : public GraphData //a constant line +{ +public: + GraphDataConstLine() : value_(0) {} + + void setValue(double val) { value_ = val; } + +private: + virtual double getValue(double x) const { return value_; } + virtual double getXBegin() const { return -std::numeric_limits<double>::infinity(); } + virtual double getXEnd () const { return std::numeric_limits<double>::infinity(); } + + double value_; +}; + + inline double bestFit(double val, double low, double high) { return val < (high + low) / 2 ? low : high; } @@ -524,10 +560,13 @@ struct LabelFormatterBytes : public LabelFormatter { virtual double getOptimalBlockSize(double bytesProposed) const { - bytesProposed *= 2; //make blocks twice the default size + if (bytesProposed <= 0) + return 0; + + bytesProposed *= 1.5; //enlarge block default size - if (bytesProposed <= 1024 * 1024) //set 1 MB min size: reduce initial rapid changes in y-label - return 1024 * 1024; + //if (bytesProposed <= 1024 * 1024) //set 1 MB min size: reduce initial rapid changes in y-label + // return 1024 * 1024; //round to next number which is a convenient to read block size @@ -540,7 +579,7 @@ struct LabelFormatterBytes : public LabelFormatter return bestFit(a, 1, 2) * e; } - virtual wxString formatText(double value, double optimalBlockSize) const { return filesizeToShortString(UInt64(value)); }; + virtual wxString formatText(double value, double optimalBlockSize) const { return filesizeToShortString(Int64(value)); }; }; @@ -589,24 +628,47 @@ struct LabelFormatterTimeElapsed : public LabelFormatter wxTimeSpan::Seconds(timeElapsed).Format(L"%H:%M:%S"); } }; + +//void fitHeight(wxTopLevelWindow& wnd) +//{ +// if (wnd.IsMaximized()) +// return; +// //Fit() height only: +// int width = wnd.GetSize().GetWidth(); +// wnd.Fit(); +// int height = wnd.GetSize().GetHeight(); +// wnd.SetSize(wxSize(width, height)); +//} } class SyncStatus::SyncStatusImpl : public SyncStatusDlgGenerated { public: - SyncStatusImpl(AbortCallback& abortCb, MainDialog* parentWindow, SyncStatusID startStatus, const wxString& jobName); + SyncStatusImpl(AbortCallback& abortCb, + MainDialog* parentWindow, + SyncStatusID startStatus, + const wxString& jobName, + const std::wstring& execWhenFinished, + std::vector<std::wstring>& execFinishedHistory); ~SyncStatusImpl(); - void resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess); - void incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed); + void initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess); + void incScannedObjects_NoUpdate(int number); + void incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta); + void incTotalData_NoUpdate (int objectsDelta, Int64 dataDelta); + void setStatusText_NoUpdate(const wxString& text); void updateStatusDialogNow(bool allowYield = true); - void setCurrentStatus(SyncStatus::SyncStatusID id); void processHasFinished(SyncStatus::SyncStatusID id, const ErrorLogging& log); //essential to call this in StatusUpdater derived class destructor at the LATEST(!) to prevent access to currentStatusUpdater + std::wstring getExecWhenFinishedCommand() const; + + void stopTimer(); //halt all internal counters! + void resumeTimer(); // + void minimizeToTray(); private: @@ -617,6 +679,8 @@ private: virtual void OnClose(wxCloseEvent& event); virtual void OnIconize(wxIconizeEvent& event); + void setCurrentStatus(SyncStatus::SyncStatusID id); + void resumeFromSystray(); void OnResumeFromTray(wxCommandEvent& event); @@ -630,17 +694,17 @@ private: MainDialog* mainDialog; //optional //gauge variables - int totalObjects; - zen::Int64 totalData; - int currentObjects; //each object represents a file or directory processed - zen::Int64 currentData; //each data element represents one byte for proper progress indicator scaling + int totalObjects; //file/dir/symlink/operation count + Int64 totalData; //unit: [bytes] + int currentObjects; + Int64 currentData; //status variables size_t scannedObjects; wxString currentStatusText; - bool processPaused; SyncStatus::SyncStatusID currentStatus; + SyncStatus::SyncStatusID previousStatus; //save old status if "currentStatus == SyncStatus::PAUSED" std::unique_ptr<Taskbar> taskbar_; @@ -650,6 +714,8 @@ private: long lastStatCallRemTime; // std::shared_ptr<GraphDataBytes> graphDataBytes; + //std::shared_ptr<GraphDataConstLine> graphDataBytesCurrent; + std::shared_ptr<GraphDataConstLine> graphDataBytesTotal; wxString titelTextBackup; @@ -657,96 +723,16 @@ private: }; -//redirect to implementation -SyncStatus::SyncStatus(AbortCallback& abortCb, - MainDialog* parentWindow, - SyncStatusID startStatus, - bool startSilent, - const wxString& jobName) : - pimpl(new SyncStatusImpl(abortCb, parentWindow, startStatus, jobName)) -{ - if (startSilent) - pimpl->minimizeToTray(); - else - { - pimpl->Show(); - pimpl->updateStatusDialogNow(false); //update visual statistics to get rid of "dummy" texts - } -} - -SyncStatus::~SyncStatus() -{ - //DON'T delete pimpl! it will be deleted by the user clicking "OK/Cancel" -> (wxWindow::Destroy()) -} - -wxWindow* SyncStatus::getAsWindow() -{ - return pimpl; -} - -void SyncStatus::closeWindowDirectly() //don't wait for user (silent mode) -{ - pimpl->Destroy(); -} - -void SyncStatus::resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess) -{ - pimpl->resetGauge(totalObjectsToProcess, totalDataToProcess); -} - -void SyncStatus::incScannedObjects_NoUpdate(int number) -{ - pimpl->incScannedObjects_NoUpdate(number); -} - -void SyncStatus::incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed) -{ - pimpl->incProgressIndicator_NoUpdate(objectsProcessed, dataProcessed); -} - -void SyncStatus::setStatusText_NoUpdate(const wxString& text) -{ - pimpl->setStatusText_NoUpdate(text); -} - -void SyncStatus::updateStatusDialogNow() -{ - pimpl->updateStatusDialogNow(); -} - -void SyncStatus::setCurrentStatus(SyncStatusID id) -{ - pimpl->setCurrentStatus(id); -} - -void SyncStatus::processHasFinished(SyncStatusID id, const ErrorLogging& log) -{ - pimpl->processHasFinished(id, log); -} -//######################################################################################## - -namespace -{ -void fitHeight(wxTopLevelWindow& wnd) -{ - if (wnd.IsMaximized()) - return; - //Fit() height only: - int width = wnd.GetSize().GetWidth(); - wnd.Fit(); - int height = wnd.GetSize().GetHeight(); - wnd.SetSize(wxSize(width, height)); -} -} - SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, MainDialog* parentWindow, SyncStatusID startStatus, - const wxString& jobName) : + const wxString& jobName, + const std::wstring& execWhenFinished, + std::vector<std::wstring>& execFinishedHistory) : SyncStatusDlgGenerated(parentWindow, wxID_ANY, parentWindow ? wxString(wxEmptyString) : (wxString(wxT("FreeFileSync - ")) + _("Folder Comparison and Synchronization")), - wxDefaultPosition, wxSize(620, 330), + wxDefaultPosition, wxSize(640, 350), parentWindow ? 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), @@ -758,8 +744,8 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, currentObjects(0), currentData(0), scannedObjects(0), - processPaused(false), - currentStatus(SyncStatus::ABORTED), + currentStatus (SyncStatus::ABORTED), + previousStatus(SyncStatus::ABORTED), lastStatCallSpeed(-1000000), //some big number lastStatCallRemTime(-1000000) { @@ -795,10 +781,10 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, catch (const TaskbarNotAvailable&) {} //hide "processed" statistics until end of process - bSizerFinalStat->Show(false); - m_buttonOK->Show(false); + bSizerFinalStat ->Show(false); + m_buttonOK ->Show(false); m_staticTextItemsProc->Show(false); - bSizerItemsProc->Show(false); + bSizerItemsProc ->Show(false); SetIcon(GlobalResources::instance().programIcon); //set application icon @@ -808,11 +794,21 @@ SyncStatus::SyncStatusImpl::SyncStatusImpl(AbortCallback& abortCb, setCurrentStatus(startStatus); //first state: will be shown while waiting for dir locks (if at all) //init graph - graphDataBytes = std::make_shared<GraphDataBytes>(); + graphDataBytes = std::make_shared<GraphDataBytes>(); + //graphDataBytesCurrent = std::make_shared<GraphDataConstLine>(); + graphDataBytesTotal = std::make_shared<GraphDataConstLine>(); + m_panelGraph->setAttributes(Graph2D::GraphAttributes(). setLabelX(Graph2D::X_LABEL_BOTTOM, 20, std::make_shared<LabelFormatterTimeElapsed>()). setLabelY(Graph2D::Y_LABEL_RIGHT, 60, std::make_shared<LabelFormatterBytes>())); - m_panelGraph->setData(graphDataBytes, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0))); //medium green + + m_panelGraph->setData(graphDataBytesTotal, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 64, 0))); //green + //m_panelGraph->addData(graphDataBytesCurrent, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 128, 0))); //green + m_panelGraph->addData(graphDataBytes, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0))); //medium green + + //allow changing on completion command + m_comboBoxExecFinished->setValue(execWhenFinished); + m_comboBoxExecFinished->setHistoryRef(execFinishedHistory); //Fit() height only: //fitHeight(*this); @@ -855,14 +851,18 @@ void SyncStatus::SyncStatusImpl::OnKeyPressed(wxKeyEvent& event) } -void SyncStatus::SyncStatusImpl::resetGauge(int totalObjectsToProcess, zen::Int64 totalDataToProcess) +void SyncStatus::SyncStatusImpl::initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess) { - currentData = 0; - totalData = totalDataToProcess; + setCurrentStatus(id); + currentData = 0; currentObjects = 0; + totalData = totalDataToProcess; totalObjects = totalObjectsToProcess; + incProcessedData_NoUpdate(0, 0); //update graph + incTotalData_NoUpdate (0, 0); // + //set new statistics handler: 10 seconds "window" for remaining time, 5 seconds for speed statistics.reset(new Statistics(totalObjectsToProcess, to<double>(totalDataToProcess), windowSizeRemainingTime, windowSizeBytesPerSec)); @@ -872,21 +872,34 @@ void SyncStatus::SyncStatusImpl::resetGauge(int totalObjectsToProcess, zen::Int6 //set to 0 even if totalDataToProcess is 0: due to a bug in wxGauge::SetValue, it doesn't change to determinate mode when setting the old value again //so give updateStatusDialogNow() a chance to set a different value m_gauge1->SetValue(0); + + updateStatusDialogNow(false); //get rid of "dummy" texts! } -void SyncStatus::SyncStatusImpl::incProgressIndicator_NoUpdate(int objectsProcessed, zen::Int64 dataProcessed) +void SyncStatus::SyncStatusImpl::incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta) { - //assert(dataProcessed >= 0); - - currentData += dataProcessed; - currentObjects += objectsProcessed; + currentData += dataDelta; + currentObjects += objectsDelta; //update graph data graphDataBytes->addCurrentValue(to<double>(currentData)); } +void SyncStatus::SyncStatusImpl::incTotalData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + totalData += dataDelta; + totalObjects += objectsDelta; + + if (statistics) + statistics->setNewTotal(totalObjects, to<double>(totalData)); + + graphDataBytesTotal->setValue(to<double>(totalData)); + //m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxY(to<double>(totalDataToProcess))); +} + + void SyncStatus::SyncStatusImpl::incScannedObjects_NoUpdate(int number) { scannedObjects += number; @@ -984,7 +997,8 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) //statistic.writeEntry(currentData.ToDouble(), currentObjects); //add both data + obj-count, to handle "deletion-only" cases - const double fraction = totalData + totalObjects == 0 ? 1 : to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects); + const double fraction = totalData + totalObjects == 0 ? 1 : std::max(0.0, to<double>(currentData + currentObjects) / to<double>(totalData + totalObjects)); + //yes, this may legitimately become < 0: failed rename operation falls-back to copy + delete, reducing "currentData" to potentially < 0! //write status information to systray, taskbar, parent title ect. @@ -1048,7 +1062,7 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) setText(*m_staticTextRemainingObj, remainingObjTmp, &layoutChanged); //remaining bytes left for copy - const wxString remainingBytesTmp = zen::filesizeToShortString(to<zen::UInt64>(totalData - currentData)); + const wxString remainingBytesTmp = zen::filesizeToShortString(totalData - currentData); setText(*m_staticTextDataRemaining, remainingBytesTmp, &layoutChanged); //statistics @@ -1073,7 +1087,12 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) } } - m_panelGraph->Refresh(); + { + m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMinX(graphDataBytes->getXBegin())); + m_panelGraph->setAttributes(m_panelGraph->getAttributes().setMaxX(graphDataBytes->getXEnd())); + + m_panelGraph->Refresh(); + } //time elapsed const long timeElapSec = timeElapsed.Time() / 1000; @@ -1090,7 +1109,8 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) // bSizer171->Layout(); bSizerProgressStat->Layout(); // m_panelProgress->Layout(); //both needed - m_panelBackground->Layout(); //we use a dummy panel as actual background: replaces simple "Layout()" call + //m_panelBackground->Layout(); //we use a dummy panel as actual background: replaces simple "Layout()" call + //-> it seems this layout is not required, and even harmful: resets m_comboBoxExecFinished dropdown while user is selecting! } } @@ -1112,13 +1132,10 @@ void SyncStatus::SyncStatusImpl::updateStatusDialogNow(bool allowYield) if (allowYield) { //support for pause button - if (processPaused) + while (currentStatus == SyncStatus::PAUSE && currentProcessIsRunning()) { - while (processPaused && currentProcessIsRunning()) - { - wxMilliSleep(UI_UPDATE_INTERVAL); - updateUiNow(); - } + wxMilliSleep(UI_UPDATE_INTERVAL); + updateUiNow(); } /* @@ -1137,6 +1154,12 @@ bool SyncStatus::SyncStatusImpl::currentProcessIsRunning() } +std::wstring SyncStatus::SyncStatusImpl::getExecWhenFinishedCommand() const +{ + return m_comboBoxExecFinished->getValue(); +} + + void SyncStatus::SyncStatusImpl::setCurrentStatus(SyncStatus::SyncStatusID id) { switch (id) @@ -1212,6 +1235,8 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, //hide current operation status bSizerCurrentOperation->Show(false); + bSizerExecFinished->Show(false); + //show and prepare final statistics bSizerFinalStat->Show(true); @@ -1225,7 +1250,7 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, m_staticTextItemsProc->Show(true); bSizerItemsProc ->Show(true); m_staticTextProcessedObj ->SetLabel(toStringSep(currentObjects)); - m_staticTextDataProcessed->SetLabel(zen::filesizeToShortString(to<zen::UInt64>(currentData))); + m_staticTextDataProcessed->SetLabel(zen::filesizeToShortString(currentData)); m_staticTextRemTimeDescr->Show(false); m_staticTextRemTime ->Show(false); @@ -1234,7 +1259,7 @@ void SyncStatus::SyncStatusImpl::processHasFinished(SyncStatus::SyncStatusID id, //changed meaning: overall speed: -> make sure to call after "updateStatusDialogNow" const long timeElapMs = timeElapsed.Time(); - m_staticTextSpeed->SetLabel(timeElapMs <= 0 ? L"-" : zen::filesizeToShortString(zen::to<UInt64>(currentData * 1000 / timeElapMs)) + _("/sec")); + m_staticTextSpeed->SetLabel(timeElapMs <= 0 ? L"-" : zen::filesizeToShortString(currentData * 1000 / timeElapMs) + _("/sec")); //fill result listbox: @@ -1268,7 +1293,12 @@ void SyncStatus::SyncStatusImpl::OnOkay(wxCommandEvent& event) void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event) { - processPaused = false; + if (currentStatus == SyncStatus::PAUSE) + { + wxCommandEvent dummy; + OnPause(dummy); + } + if (currentProcessIsRunning()) { m_buttonAbort->Disable(); @@ -1284,36 +1314,40 @@ void SyncStatus::SyncStatusImpl::OnAbort(wxCommandEvent& event) } -void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event) +void SyncStatus::SyncStatusImpl::stopTimer() { - static SyncStatus::SyncStatusID previousStatus = SyncStatus::ABORTED; + timeElapsed.Pause(); + if (statistics.get()) statistics->pauseTimer(); + graphDataBytes->pauseTimer(); +} - processPaused = !processPaused; - if (processPaused) - { - previousStatus = currentStatus; //save current status - setCurrentStatus(SyncStatus::PAUSE); +void SyncStatus::SyncStatusImpl::resumeTimer() +{ + timeElapsed.Resume(); + if (statistics.get()) statistics->resumeTimer(); + graphDataBytes->resumeTimer(); +} - m_buttonPause->SetLabel(_("Continue")); - m_animationControl1->Stop(); - //pause timers - timeElapsed.Pause(); - if (statistics.get()) statistics->pauseTimer(); - graphDataBytes->pauseTimer(); - } - else +void SyncStatus::SyncStatusImpl::OnPause(wxCommandEvent& event) +{ + if (currentStatus == SyncStatus::PAUSE) { + resumeTimer(); setCurrentStatus(previousStatus); m_buttonPause->SetLabel(_("Pause")); m_animationControl1->Play(); + } + else + { + stopTimer(); + previousStatus = currentStatus; //save current status + setCurrentStatus(SyncStatus::PAUSE); - //resume timers - timeElapsed.Resume(); - if (statistics.get()) statistics->resumeTimer(); - graphDataBytes->resumeTimer(); + m_buttonPause->SetLabel(_("Continue")); + m_animationControl1->Stop(); } } @@ -1382,3 +1416,91 @@ void SyncStatus::SyncStatusImpl::resumeFromSystray() updateStatusDialogNow(false); //restore Windows 7 task bar status (e.g. required in pause mode) } + + +//######################################################################################## + + +//redirect to implementation +SyncStatus::SyncStatus(AbortCallback& abortCb, + MainDialog* parentWindow, + SyncStatusID startStatus, + bool showProgress, + const wxString& jobName, + const std::wstring& execWhenFinished, + std::vector<std::wstring>& execFinishedHistory) : + pimpl(new SyncStatusImpl(abortCb, parentWindow, startStatus, jobName, execWhenFinished, execFinishedHistory)) +{ + if (showProgress) + { + pimpl->Show(); + pimpl->updateStatusDialogNow(false); //update visual statistics to get rid of "dummy" texts + } + else + pimpl->minimizeToTray(); +} + +SyncStatus::~SyncStatus() +{ + //DON'T delete pimpl! it will be deleted by the user clicking "OK/Cancel" -> (wxWindow::Destroy()) +} + +wxWindow* SyncStatus::getAsWindow() +{ + return pimpl; +} + +void SyncStatus::initNewProcess(SyncStatusID id, int totalObjectsToProcess, Int64 totalDataToProcess) +{ + pimpl->initNewProcess(id, totalObjectsToProcess, totalDataToProcess); +} + +void SyncStatus::incScannedObjects_NoUpdate(int number) +{ + pimpl->incScannedObjects_NoUpdate(number); +} + +void SyncStatus::incProcessedData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + pimpl->incProcessedData_NoUpdate(objectsDelta, dataDelta); +} + +void SyncStatus::incTotalData_NoUpdate(int objectsDelta, Int64 dataDelta) +{ + pimpl->incTotalData_NoUpdate(objectsDelta, dataDelta); +} + +void SyncStatus::setStatusText_NoUpdate(const wxString& text) +{ + pimpl->setStatusText_NoUpdate(text); +} + +void SyncStatus::updateStatusDialogNow() +{ + pimpl->updateStatusDialogNow(); +} + +std::wstring SyncStatus::getExecWhenFinishedCommand() const +{ + return pimpl->getExecWhenFinishedCommand(); +} + +void SyncStatus::stopTimer() +{ + return pimpl->stopTimer(); +} + +void SyncStatus::resumeTimer() +{ + return pimpl->resumeTimer(); +} + +void SyncStatus::processHasFinished(SyncStatusID id, const ErrorLogging& log) +{ + pimpl->processHasFinished(id, log); +} + +void SyncStatus::closeWindowDirectly() //don't wait for user (silent mode) +{ + pimpl->Destroy(); +} |