summaryrefslogtreecommitdiff
path: root/ui/progress_indicator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/progress_indicator.cpp')
-rw-r--r--ui/progress_indicator.cpp560
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();
+}
bgstack15