mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-24 16:20:05 +02:00
Introduce further enhancement of the Timer Recording process:
* Disk space warning if the recording potentially will not fit in disk space available. * ProgressDialog enhancements that allow the Stop/Cancel button to be confirmed and the elapsed time to be hidden. * Messages enhanced to clearly show the actions being taken.
This commit is contained in:
parent
726efcf5c8
commit
6686d0e314
@ -6316,8 +6316,7 @@ void AudacityProject::OnTimerRecord()
|
|||||||
// it is now safer to disable Timer Recording when there is more than
|
// it is now safer to disable Timer Recording when there is more than
|
||||||
// one open project.
|
// one open project.
|
||||||
if (GetOpenProjectCount() > 1) {
|
if (GetOpenProjectCount() > 1) {
|
||||||
wxMessageBox(_("Timer Recording cannot be used with more than one open project.\n\n\
|
wxMessageBox(_("Timer Recording cannot be used with more than one open project.\n\nPlease close any additional projects and try again."),
|
||||||
Please close any additional projects and try again."),
|
|
||||||
_("Timer Recording"),
|
_("Timer Recording"),
|
||||||
wxICON_INFORMATION | wxOK);
|
wxICON_INFORMATION | wxOK);
|
||||||
return;
|
return;
|
||||||
|
@ -5254,3 +5254,36 @@ bool AudacityProject::ProjectHasTracks() {
|
|||||||
bool bHasTracks = (iter2.First() != NULL);
|
bool bHasTracks = (iter2.First() != NULL);
|
||||||
return bHasTracks;
|
return bHasTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MY: This routine will give an estimate of how many
|
||||||
|
// minutes of recording time we have available.
|
||||||
|
// This is called from TimerRecordDialog::OnOK() to allow
|
||||||
|
// the user to resolve a potential disk space issue before
|
||||||
|
// Timer Recording starts.
|
||||||
|
// The calculations made are based on the user's current
|
||||||
|
// preferences.
|
||||||
|
int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk() {
|
||||||
|
|
||||||
|
// Obtain the current settings
|
||||||
|
sampleFormat oCaptureFormat = (sampleFormat)
|
||||||
|
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||||
|
long lCaptureChannels;
|
||||||
|
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &lCaptureChannels, 2L);
|
||||||
|
|
||||||
|
// Find out how much free space we have on disk
|
||||||
|
wxLongLong lFreeSpace = mDirManager->GetFreeDiskSpace();
|
||||||
|
if (lFreeSpace < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the remaining time
|
||||||
|
double dRecTime = 0.0;
|
||||||
|
dRecTime = lFreeSpace.GetHi() * 4294967296.0 + lFreeSpace.GetLo();
|
||||||
|
dRecTime /= SAMPLE_SIZE_DISK(oCaptureFormat);
|
||||||
|
dRecTime /= lCaptureChannels;
|
||||||
|
dRecTime /= GetRate();
|
||||||
|
|
||||||
|
// Convert to minutes before returning
|
||||||
|
int iRecMins = (int)(dRecTime / 60.0);
|
||||||
|
return iRecMins;
|
||||||
|
}
|
||||||
|
@ -283,6 +283,9 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame,
|
|||||||
|
|
||||||
bool ProjectHasTracks();
|
bool ProjectHasTracks();
|
||||||
|
|
||||||
|
// Routine to estimate how many minutes of recording time are left on disk
|
||||||
|
int GetEstimatedRecordingMinsLeftOnDisk();
|
||||||
|
|
||||||
#include "Menus.h"
|
#include "Menus.h"
|
||||||
|
|
||||||
CommandManager *GetCommandManager() { return &mCommandManager; }
|
CommandManager *GetCommandManager() { return &mCommandManager; }
|
||||||
|
@ -371,6 +371,33 @@ void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MY: Estimate here if we have enough disk space to
|
||||||
|
// complete this Timer Recording.
|
||||||
|
// If we dont think there is enough space then ask the user
|
||||||
|
// if they want to continue.
|
||||||
|
// We don't stop the user from starting the recording
|
||||||
|
// as its possible that they plan to free up some
|
||||||
|
// space before the recording begins
|
||||||
|
AudacityProject* pProject = GetActiveProject();
|
||||||
|
|
||||||
|
// How many minutes do we have left on the recording?
|
||||||
|
int iMinsLeft = pProject->GetEstimatedRecordingMinsLeftOnDisk();
|
||||||
|
|
||||||
|
// How many minutes will this recording require?
|
||||||
|
int iMinsRecording = m_TimeSpan_Duration.GetMinutes();
|
||||||
|
|
||||||
|
// Do we have enough space?
|
||||||
|
if (iMinsRecording >= iMinsLeft) {
|
||||||
|
wxMessageDialog dlgMessage(NULL,
|
||||||
|
_("You may not have enough free disk space to complete this timer recording, based on your current settings.\n\nDo you wish to continue?"),
|
||||||
|
_("Timer Recording Disk Space Warning"),
|
||||||
|
wxYES_NO | wxNO_DEFAULT | wxICON_WARNING);
|
||||||
|
if (dlgMessage.ShowModal() != wxID_YES) {
|
||||||
|
// User decided not to continue - bail out!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_timer.Stop(); // Don't need to keep updating m_DateTime_Start to prevent backdating.
|
m_timer.Stop(); // Don't need to keep updating m_DateTime_Start to prevent backdating.
|
||||||
this->EndModal(wxID_OK);
|
this->EndModal(wxID_OK);
|
||||||
wxLongLong duration = m_TimeSpan_Duration.GetSeconds();
|
wxLongLong duration = m_TimeSpan_Duration.GetSeconds();
|
||||||
@ -465,17 +492,26 @@ int TimerRecordDialog::RunWaitDialog()
|
|||||||
pProject->OnRecord();
|
pProject->OnRecord();
|
||||||
bool bIsRecording = true;
|
bool bIsRecording = true;
|
||||||
|
|
||||||
wxString strMsg =
|
wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection());
|
||||||
_("Recording start") + (wxString)wxT(":\t\t")
|
wxString strMsg;
|
||||||
+ GetDisplayDate(m_DateTime_Start) + wxT("\n") + _("Recording end")
|
strMsg.Printf(_("Recording start:\t\t\t%s\n") +
|
||||||
+ wxT(":\t\t") + GetDisplayDate(m_DateTime_End) + wxT("\n")
|
_("Recording end:\t\t\t%s\n") +
|
||||||
+ _("Duration") + wxT(":\t\t") + m_TimeSpan_Duration.Format();
|
_("Duration:\t\t\t%s\n\n") +
|
||||||
|
_("Automatic Save Enabled:\t\t%s\n") +
|
||||||
|
_("Automatic Export Enabled:\t\t%s\n") +
|
||||||
|
_("Post Timer Recording Action:\t%s"),
|
||||||
|
GetDisplayDate(m_DateTime_Start).c_str(),
|
||||||
|
m_TimeSpan_Duration.Format(),
|
||||||
|
GetDisplayDate(m_DateTime_End).c_str(),
|
||||||
|
(m_bAutoSaveEnabled ? _("Yes") : _("No")),
|
||||||
|
(m_bAutoExportEnabled ? _("Yes") : _("No")),
|
||||||
|
sPostAction);
|
||||||
|
|
||||||
TimerProgressDialog
|
TimerProgressDialog
|
||||||
progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
|
progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(),
|
||||||
_("Audacity Timer Record Progress"),
|
_("Audacity Timer Record Progress"),
|
||||||
strMsg,
|
strMsg,
|
||||||
pdlgHideCancelButton);
|
pdlgHideCancelButton | pdlgConfirmStopCancel);
|
||||||
|
|
||||||
// Make sure that start and end time are updated, so we always get the full
|
// Make sure that start and end time are updated, so we always get the full
|
||||||
// duration, even if there's some delay getting here.
|
// duration, even if there's some delay getting here.
|
||||||
@ -593,11 +629,20 @@ int TimerRecordDialog::ExecutePostRecordActions(bool bWasStopped) {
|
|||||||
// MY: Lets do some actions that only apply to Exit/Restart/Shutdown
|
// MY: Lets do some actions that only apply to Exit/Restart/Shutdown
|
||||||
if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
|
if (iPostRecordAction >= POST_TIMER_RECORD_CLOSE) {
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
// Set the flags as appropriate based on what we have done
|
||||||
|
wxUint32 eActionFlags = TR_ACTION_NOTHING;
|
||||||
|
if (m_bAutoSaveEnabled && bSaveOK) {
|
||||||
|
eActionFlags |= TR_ACTION_SAVED;
|
||||||
|
}
|
||||||
|
if (m_bAutoExportEnabled && bExportOK) {
|
||||||
|
eActionFlags |= TR_ACTION_EXPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Lets show a warning dialog telling the user what is about to happen.
|
// Lets show a warning dialog telling the user what is about to happen.
|
||||||
// If the user no longer wants to carry out this action then they can click
|
// If the user no longer wants to carry out this action then they can click
|
||||||
// Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
|
// Cancel and we will do POST_TIMER_RECORD_NOTHING instead.
|
||||||
int iDelayOutcome = PreActionDelay(iPostRecordAction, (m_bAutoSaveEnabled && bSaveOK),
|
int iDelayOutcome = PreActionDelay(iPostRecordAction, (TimerRecordCompletedActions)eActionFlags);
|
||||||
(m_bAutoExportEnabled && bExportOK));
|
|
||||||
if (iDelayOutcome != eProgressSuccess) {
|
if (iDelayOutcome != eProgressSuccess) {
|
||||||
// Cancel the action!
|
// Cancel the action!
|
||||||
iPostRecordAction = POST_TIMER_RECORD_NOTHING;
|
iPostRecordAction = POST_TIMER_RECORD_NOTHING;
|
||||||
@ -912,18 +957,32 @@ void TimerRecordDialog::UpdateEnd()
|
|||||||
|
|
||||||
int TimerRecordDialog::WaitForStart()
|
int TimerRecordDialog::WaitForStart()
|
||||||
{
|
{
|
||||||
|
// MY: The Waiting For Start dialog now shows what actions will occur after recording has completed
|
||||||
|
wxString sPostAction = m_pTimerAfterCompleteChoiceCtrl->GetString(m_pTimerAfterCompleteChoiceCtrl->GetSelection());
|
||||||
|
|
||||||
|
/* i18n-hint: Time specifications like "Sunday 28th October 2007 15:16:17 GMT"
|
||||||
|
* but hopefully translated by wxwidgets will be inserted into this */
|
||||||
wxString strMsg;
|
wxString strMsg;
|
||||||
/* i18n-hint: A time specification like "Sunday 28th October 2007 15:16:17 GMT"
|
strMsg.Printf(_("Waiting to start recording at:\t%s\n") +
|
||||||
* but hopefully translated by wxwidgets will be inserted into this */
|
_("Recording duration:\t\t%s\n") +
|
||||||
strMsg.Printf(_("Waiting to start recording at %s.\n"),
|
_("Scheduled to stop at:\t\t%s\n\n") +
|
||||||
GetDisplayDate(m_DateTime_Start).c_str());
|
_("Automatic Save Enabled:\t\t%s\n") +
|
||||||
|
_("Automatic Export Enabled:\t\t%s\n") +
|
||||||
|
_("Post Timer Recording Action:\t%s"),
|
||||||
|
GetDisplayDate(m_DateTime_Start).c_str(),
|
||||||
|
m_TimeSpan_Duration.Format(),
|
||||||
|
GetDisplayDate(m_DateTime_End).c_str(),
|
||||||
|
(m_bAutoSaveEnabled ? _("Yes") : _("No")),
|
||||||
|
(m_bAutoExportEnabled ? _("Yes") : _("No")),
|
||||||
|
sPostAction);
|
||||||
|
|
||||||
wxDateTime startWait_DateTime = wxDateTime::UNow();
|
wxDateTime startWait_DateTime = wxDateTime::UNow();
|
||||||
wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
|
wxTimeSpan waitDuration = m_DateTime_Start - startWait_DateTime;
|
||||||
TimerProgressDialog
|
TimerProgressDialog progress(waitDuration.GetMilliseconds().GetValue(),
|
||||||
progress(waitDuration.GetMilliseconds().GetValue(),
|
_("Audacity Timer Record - Waiting for Start"),
|
||||||
_("Audacity Timer Record - Waiting for Start"),
|
strMsg,
|
||||||
strMsg,
|
pdlgHideStopButton | pdlgConfirmStopCancel | pdlgHideElapsedTime,
|
||||||
pdlgHideStopButton);
|
_("Recording will commence in:"));
|
||||||
|
|
||||||
int updateResult = eProgressSuccess;
|
int updateResult = eProgressSuccess;
|
||||||
bool bIsRecording = false;
|
bool bIsRecording = false;
|
||||||
@ -936,28 +995,21 @@ int TimerRecordDialog::WaitForStart()
|
|||||||
return updateResult;
|
return updateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rather than two flags, an enum with the possibilities would be better.
|
int TimerRecordDialog::PreActionDelay(int iActionIndex, TimerRecordCompletedActions eCompletedActions)
|
||||||
int TimerRecordDialog::PreActionDelay(int iActionIndex, bool bSaved, bool bExported)
|
|
||||||
{
|
{
|
||||||
wxString sMessage;
|
|
||||||
wxString sAction = m_pTimerAfterCompleteChoiceCtrl->GetString(iActionIndex);
|
wxString sAction = m_pTimerAfterCompleteChoiceCtrl->GetString(iActionIndex);
|
||||||
wxString sDone = "";
|
wxString sCountdownLabel;
|
||||||
if (bSaved && bExported) {
|
sCountdownLabel.Printf("%s in:", sAction);
|
||||||
sDone = _("Saved and Exported");
|
|
||||||
}
|
// Build a clearer message...
|
||||||
else if (bSaved) {
|
wxString sMessage;
|
||||||
sDone = _("Saved");
|
sMessage.Printf(_("Timer Recording Completed.\n\n") +
|
||||||
}
|
_("Recording Saved:\t\t\t%s\n") +
|
||||||
else if (bExported) {
|
_("Recording Exported:\t\t%s\n") +
|
||||||
sDone = _("Exported");
|
_("Post Timer Recording Action:\t%s"),
|
||||||
}
|
((eCompletedActions & TR_ACTION_SAVED) ? _("Yes") : _("No")),
|
||||||
// TODO: The wording will sound better if there are complete messages for
|
((eCompletedActions & TR_ACTION_EXPORTED) ? _("Yes") : _("No")),
|
||||||
// the will-occur-shortly messages.
|
sAction);
|
||||||
/* i18n-hint: The first %s will be a translation of 'Saved', 'Exported' or
|
|
||||||
* 'Saved and Exported'. The second %s will be 'Exit Audacity'
|
|
||||||
* 'Restart System' or 'Shutdown System' */
|
|
||||||
sMessage.Printf(_("Timer Recording completed: Recording has been %s.\n\n'%s' will occur shortly...\n"),
|
|
||||||
sDone, sAction);
|
|
||||||
|
|
||||||
wxDateTime dtNow = wxDateTime::UNow();
|
wxDateTime dtNow = wxDateTime::UNow();
|
||||||
wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
|
wxTimeSpan tsWait = wxTimeSpan(0, 1, 0, 0);
|
||||||
@ -966,7 +1018,8 @@ int TimerRecordDialog::PreActionDelay(int iActionIndex, bool bSaved, bool bExpor
|
|||||||
TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
|
TimerProgressDialog dlgAction(tsWait.GetMilliseconds().GetValue(),
|
||||||
_("Audacity Timer Record - Waiting"),
|
_("Audacity Timer Record - Waiting"),
|
||||||
sMessage,
|
sMessage,
|
||||||
pdlgHideStopButton);
|
pdlgHideStopButton | pdlgHideElapsedTime,
|
||||||
|
sCountdownLabel);
|
||||||
|
|
||||||
int iUpdateResult = eProgressSuccess;
|
int iUpdateResult = eProgressSuccess;
|
||||||
bool bIsTime = false;
|
bool bIsTime = false;
|
||||||
|
@ -30,6 +30,12 @@ class NumericTextCtrl;
|
|||||||
class ShuttleGui;
|
class ShuttleGui;
|
||||||
class TimerRecordPathCtrl;
|
class TimerRecordPathCtrl;
|
||||||
|
|
||||||
|
enum TimerRecordCompletedActions {
|
||||||
|
TR_ACTION_NOTHING = 0x00000000,
|
||||||
|
TR_ACTION_SAVED = 0x00000001,
|
||||||
|
TR_ACTION_EXPORTED = 0x00000002
|
||||||
|
};
|
||||||
|
|
||||||
class TimerRecordPathCtrl final : public wxTextCtrl
|
class TimerRecordPathCtrl final : public wxTextCtrl
|
||||||
{
|
{
|
||||||
// MY: Class that inherits from the wxTextCtrl class.
|
// MY: Class that inherits from the wxTextCtrl class.
|
||||||
@ -93,7 +99,7 @@ private:
|
|||||||
|
|
||||||
int ExecutePostRecordActions(bool bWasStopped);
|
int ExecutePostRecordActions(bool bWasStopped);
|
||||||
|
|
||||||
int PreActionDelay(int iActionIndex, bool bSaved, bool bExported);
|
int PreActionDelay(int iActionIndex, TimerRecordCompletedActions eCompletedActions);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDateTime m_DateTime_Start;
|
wxDateTime m_DateTime_Start;
|
||||||
|
@ -996,13 +996,14 @@ ProgressDialog::ProgressDialog()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProgressDialog::ProgressDialog(const wxString & title,
|
ProgressDialog::ProgressDialog(const wxString & title,
|
||||||
const wxString & message,
|
const wxString & message /* = wxEmptyString*/,
|
||||||
int flags)
|
int flags /* = pdlgDefaultFlags */,
|
||||||
|
const wxString & sRemainingLabelText /* = wxEmptyString */)
|
||||||
: wxDialog()
|
: wxDialog()
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
Create(title, message, flags);
|
Create(title, message, flags, sRemainingLabelText);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1070,11 +1071,17 @@ void ProgressDialog::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ProgressDialog::Create(const wxString & title,
|
bool ProgressDialog::Create(const wxString & title,
|
||||||
const wxString & message,
|
const wxString & message /* = wxEmptyString */,
|
||||||
int flags)
|
int flags /* = pdlgDefaultFlags */,
|
||||||
|
const wxString & sRemainingLabelText /* = wxEmptyString */)
|
||||||
{
|
{
|
||||||
wxWindow *parent = GetParentForModalDialog(NULL, 0);
|
wxWindow *parent = GetParentForModalDialog(NULL, 0);
|
||||||
|
|
||||||
|
// Set this boolean to indicate if we are using the "Elapsed" labels
|
||||||
|
m_bShowElapsedTime = !(flags & pdlgHideElapsedTime);
|
||||||
|
// Set this boolean to indicate if we confirm the Cancel/Stop actions
|
||||||
|
m_bConfirmAction = (flags & pdlgConfirmStopCancel);
|
||||||
|
|
||||||
bool success = wxDialog::Create(parent,
|
bool success = wxDialog::Create(parent,
|
||||||
wxID_ANY,
|
wxID_ANY,
|
||||||
title,
|
title,
|
||||||
@ -1125,33 +1132,45 @@ bool ProgressDialog::Create(const wxString & title,
|
|||||||
//
|
//
|
||||||
{
|
{
|
||||||
auto ug = std::make_unique<wxFlexGridSizer>(2, 2, 10, 10);
|
auto ug = std::make_unique<wxFlexGridSizer>(2, 2, 10, 10);
|
||||||
|
// MY: Only one row if we are not going to show the elapsed time
|
||||||
|
if (m_bShowElapsedTime == false) {
|
||||||
|
ug = std::make_unique<wxFlexGridSizer>(1, 2, 10, 10);
|
||||||
|
}
|
||||||
g = ug.get();
|
g = ug.get();
|
||||||
|
|
||||||
w = safenew wxStaticText(this,
|
if (m_bShowElapsedTime) {
|
||||||
wxID_ANY,
|
w = safenew wxStaticText(this,
|
||||||
_("Elapsed Time:"),
|
wxID_ANY,
|
||||||
wxDefaultPosition,
|
_("Elapsed Time:"),
|
||||||
wxDefaultSize,
|
wxDefaultPosition,
|
||||||
wxALIGN_RIGHT);
|
wxDefaultSize,
|
||||||
w->SetName(w->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
wxALIGN_RIGHT);
|
||||||
g->Add(w, 0, wxALIGN_RIGHT);
|
w->SetName(w->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
||||||
|
g->Add(w, 0, wxALIGN_RIGHT);
|
||||||
|
|
||||||
mElapsed = safenew wxStaticText(this,
|
mElapsed = safenew wxStaticText(this,
|
||||||
wxID_ANY,
|
wxID_ANY,
|
||||||
wxT("00:00:00"),
|
wxT("00:00:00"),
|
||||||
wxDefaultPosition,
|
wxDefaultPosition,
|
||||||
wxDefaultSize,
|
wxDefaultSize,
|
||||||
wxALIGN_LEFT);
|
wxALIGN_LEFT);
|
||||||
mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
||||||
g->Add(mElapsed, 0, wxALIGN_LEFT);
|
g->Add(mElapsed, 0, wxALIGN_LEFT);
|
||||||
ds.y += mElapsed->GetSize().y + 10;
|
ds.y += mElapsed->GetSize().y + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customised "Remaining" label text
|
||||||
|
wxString sRemainingText = sRemainingLabelText;
|
||||||
|
if (sRemainingText == wxEmptyString) {
|
||||||
|
sRemainingText = _("Remaining Time:");
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
w = safenew wxStaticText(this,
|
w = safenew wxStaticText(this,
|
||||||
wxID_ANY,
|
wxID_ANY,
|
||||||
_("Remaining Time:"),
|
sRemainingText,
|
||||||
wxDefaultPosition,
|
wxDefaultPosition,
|
||||||
wxDefaultSize,
|
wxDefaultSize,
|
||||||
wxALIGN_RIGHT);
|
wxALIGN_RIGHT);
|
||||||
@ -1180,12 +1199,14 @@ bool ProgressDialog::Create(const wxString & title,
|
|||||||
{
|
{
|
||||||
w = safenew wxButton(this, wxID_OK, _("Stop"));
|
w = safenew wxButton(this, wxID_OK, _("Stop"));
|
||||||
h->Add(w, 0, wxRIGHT, 10);
|
h->Add(w, 0, wxRIGHT, 10);
|
||||||
|
m_btnStop = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & pdlgHideCancelButton))
|
if (!(flags & pdlgHideCancelButton))
|
||||||
{
|
{
|
||||||
w = safenew wxButton(this, wxID_CANCEL, _("Cancel"));
|
w = safenew wxButton(this, wxID_CANCEL, _("Cancel"));
|
||||||
h->Add(w, 0, wxRIGHT, 10);
|
h->Add(w, 0, wxRIGHT, 10);
|
||||||
|
m_btnCancel = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
v->Add(uh.release(), 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10);
|
v->Add(uh.release(), 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 10);
|
||||||
@ -1201,6 +1222,10 @@ bool ProgressDialog::Create(const wxString & title,
|
|||||||
wxClientDC dc(this);
|
wxClientDC dc(this);
|
||||||
dc.GetMultiLineTextExtent(message, &mLastW, &mLastH);
|
dc.GetMultiLineTextExtent(message, &mLastW, &mLastH);
|
||||||
|
|
||||||
|
// MY: Add a little bit more width when we have TABs to stop words wrapping
|
||||||
|
int iTabFreq = wxMax((message.Freq('\t') - 1), 0);
|
||||||
|
mLastW = mLastW + (iTabFreq * 8);
|
||||||
|
|
||||||
#if defined(__WXMAC__)
|
#if defined(__WXMAC__)
|
||||||
mMessage->SetMinSize(wxSize(mLastW, mLastH));
|
mMessage->SetMinSize(wxSize(mLastW, mLastH));
|
||||||
#endif
|
#endif
|
||||||
@ -1297,12 +1322,14 @@ int ProgressDialog::Update(int value, const wxString & message)
|
|||||||
// Only update if a full second has passed or track progress is complete
|
// Only update if a full second has passed or track progress is complete
|
||||||
if ((now - mLastUpdate > 1000) || (value == 1000))
|
if ((now - mLastUpdate > 1000) || (value == 1000))
|
||||||
{
|
{
|
||||||
wxTimeSpan tsElapsed(0, 0, 0, elapsed);
|
if (m_bShowElapsedTime) {
|
||||||
wxTimeSpan tsRemains(0, 0, 0, remains);
|
wxTimeSpan tsElapsed(0, 0, 0, elapsed);
|
||||||
|
mElapsed->SetLabel(tsElapsed.Format(wxT("%H:%M:%S")));
|
||||||
|
mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
||||||
|
mElapsed->Update();
|
||||||
|
}
|
||||||
|
|
||||||
mElapsed->SetLabel(tsElapsed.Format(wxT("%H:%M:%S")));
|
wxTimeSpan tsRemains(0, 0, 0, remains);
|
||||||
mElapsed->SetName(mElapsed->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
|
||||||
mElapsed->Update();
|
|
||||||
mRemaining->SetLabel(tsRemains.Format(wxT("%H:%M:%S")));
|
mRemaining->SetLabel(tsRemains.Format(wxT("%H:%M:%S")));
|
||||||
mRemaining->SetName(mRemaining->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
mRemaining->SetName(mRemaining->GetLabel()); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
|
||||||
mRemaining->Update();
|
mRemaining->Update();
|
||||||
@ -1477,12 +1504,36 @@ bool ProgressDialog::SearchForWindow(const wxWindowList & list, const wxWindow *
|
|||||||
|
|
||||||
void ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
void ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
||||||
{
|
{
|
||||||
|
if (m_bConfirmAction) {
|
||||||
|
wxString sPrompt = _("Are you sure you wish to cancel?");
|
||||||
|
wxMessageDialog dlgMessage(this,
|
||||||
|
sPrompt,
|
||||||
|
_("Confirm Cancel"),
|
||||||
|
wxYES_NO | wxICON_QUESTION | wxNO_DEFAULT | wxSTAY_ON_TOP);
|
||||||
|
int iAction = dlgMessage.ShowModal();
|
||||||
|
if (iAction != wxID_YES) {
|
||||||
|
m_btnCancel->SetFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
FindWindowById(wxID_CANCEL, this)->Disable();
|
FindWindowById(wxID_CANCEL, this)->Disable();
|
||||||
mCancel = true;
|
mCancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
|
void ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
|
||||||
{
|
{
|
||||||
|
if (m_bConfirmAction) {
|
||||||
|
wxString sPrompt = _("Are you sure you wish to stop?");
|
||||||
|
wxMessageDialog dlgMessage(this,
|
||||||
|
sPrompt,
|
||||||
|
_("Confirm Stop"),
|
||||||
|
wxYES_NO | wxICON_QUESTION | wxNO_DEFAULT | wxSTAY_ON_TOP);
|
||||||
|
int iAction = dlgMessage.ShowModal();
|
||||||
|
if (iAction != wxID_YES) {
|
||||||
|
m_btnStop->SetFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
FindWindowById(wxID_OK, this)->Disable();
|
FindWindowById(wxID_OK, this)->Disable();
|
||||||
mCancel = false;
|
mCancel = false;
|
||||||
mStop = true;
|
mStop = true;
|
||||||
@ -1490,6 +1541,17 @@ void ProgressDialog::OnStop(wxCommandEvent & WXUNUSED(event))
|
|||||||
|
|
||||||
void ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
|
void ProgressDialog::OnCloseWindow(wxCloseEvent & WXUNUSED(event))
|
||||||
{
|
{
|
||||||
|
if (m_bConfirmAction) {
|
||||||
|
wxString sPrompt = _("Are you sure you wish to close?");
|
||||||
|
wxMessageDialog dlgMessage(this,
|
||||||
|
sPrompt,
|
||||||
|
_("Confirm Close"),
|
||||||
|
wxYES_NO | wxICON_QUESTION | wxNO_DEFAULT | wxSTAY_ON_TOP);
|
||||||
|
int iAction = dlgMessage.ShowModal();
|
||||||
|
if (iAction != wxID_YES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
mCancel = true;
|
mCancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,10 +1587,11 @@ void ProgressDialog::Beep() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
TimerProgressDialog::TimerProgressDialog(const wxLongLong_t duration,
|
TimerProgressDialog::TimerProgressDialog(const wxLongLong_t duration,
|
||||||
const wxString & title,
|
const wxString & title,
|
||||||
const wxString & message /*= wxEmptyString*/,
|
const wxString & message /* = wxEmptyString */,
|
||||||
int flags /*= pdlgEmptyFlags*/)
|
int flags /* = pdlgDefaultFlags */,
|
||||||
: ProgressDialog(title, message, flags)
|
const wxString & sRemainingLabelText /* = wxEmptyString */)
|
||||||
|
: ProgressDialog(title, message, flags, sRemainingLabelText)
|
||||||
{
|
{
|
||||||
mDuration = duration;
|
mDuration = duration;
|
||||||
}
|
}
|
||||||
@ -1587,11 +1650,13 @@ int TimerProgressDialog::Update(const wxString & message /*= wxEmptyString*/)
|
|||||||
// Only update if a full second has passed.
|
// Only update if a full second has passed.
|
||||||
if (now - mLastUpdate > 1000)
|
if (now - mLastUpdate > 1000)
|
||||||
{
|
{
|
||||||
wxTimeSpan tsElapsed(0, 0, 0, elapsed);
|
if (m_bShowElapsedTime) {
|
||||||
wxTimeSpan tsRemains(0, 0, 0, remains);
|
wxTimeSpan tsElapsed(0, 0, 0, elapsed);
|
||||||
|
mElapsed->SetLabel(tsElapsed.Format(wxT("%H:%M:%S")));
|
||||||
|
mElapsed->Update();
|
||||||
|
}
|
||||||
|
|
||||||
mElapsed->SetLabel(tsElapsed.Format(wxT("%H:%M:%S")));
|
wxTimeSpan tsRemains(0, 0, 0, remains);
|
||||||
mElapsed->Update();
|
|
||||||
mRemaining->SetLabel(tsRemains.Format(wxT("%H:%M:%S")));
|
mRemaining->SetLabel(tsRemains.Format(wxT("%H:%M:%S")));
|
||||||
mRemaining->Update();
|
mRemaining->Update();
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <wx/gauge.h>
|
#include <wx/gauge.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
#include <wx/msgdlg.h>
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -40,6 +41,8 @@ enum ProgressDialogFlags
|
|||||||
pdlgEmptyFlags = 0x00000000,
|
pdlgEmptyFlags = 0x00000000,
|
||||||
pdlgHideStopButton = 0x00000001,
|
pdlgHideStopButton = 0x00000001,
|
||||||
pdlgHideCancelButton = 0x00000002,
|
pdlgHideCancelButton = 0x00000002,
|
||||||
|
pdlgHideElapsedTime = 0x00000004,
|
||||||
|
pdlgConfirmStopCancel = 0x00000008,
|
||||||
|
|
||||||
pdlgDefaultFlags = pdlgEmptyFlags
|
pdlgDefaultFlags = pdlgEmptyFlags
|
||||||
};
|
};
|
||||||
@ -52,11 +55,17 @@ class AUDACITY_DLL_API ProgressDialog /* not final */ : public wxDialog
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProgressDialog();
|
ProgressDialog();
|
||||||
ProgressDialog(const wxString & title, const wxString & message = wxEmptyString, int flags = pdlgDefaultFlags);
|
ProgressDialog(const wxString & title,
|
||||||
|
const wxString & message = wxEmptyString,
|
||||||
|
int flags = pdlgDefaultFlags,
|
||||||
|
const wxString & sRemainingLabelText = wxEmptyString);
|
||||||
virtual ~ProgressDialog();
|
virtual ~ProgressDialog();
|
||||||
|
|
||||||
// NEW virtual? It doesn't override wxDialog
|
// NEW virtual? It doesn't override wxDialog
|
||||||
virtual bool Create(const wxString & title, const wxString & message = wxEmptyString, int flags = pdlgDefaultFlags);
|
virtual bool Create(const wxString & title,
|
||||||
|
const wxString & message = wxEmptyString,
|
||||||
|
int flags = pdlgDefaultFlags,
|
||||||
|
const wxString & sRemainingLabelText = wxEmptyString);
|
||||||
|
|
||||||
int Update(int value, const wxString & message = wxEmptyString);
|
int Update(int value, const wxString & message = wxEmptyString);
|
||||||
int Update(double current, const wxString & message = wxEmptyString);
|
int Update(double current, const wxString & message = wxEmptyString);
|
||||||
@ -83,6 +92,14 @@ protected:
|
|||||||
|
|
||||||
bool mIsTransparent;
|
bool mIsTransparent;
|
||||||
|
|
||||||
|
// MY: Booleans to hold the flag values
|
||||||
|
bool m_bShowElapsedTime = true;
|
||||||
|
bool m_bConfirmAction = false;
|
||||||
|
|
||||||
|
// MY: Declare the buttons so we can se the focus on them later
|
||||||
|
wxWindow *m_btnStop;
|
||||||
|
wxWindow *m_btnCancel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
bool SearchForWindow(const wxWindowList & list, const wxWindow *searchfor) const;
|
bool SearchForWindow(const wxWindowList & list, const wxWindow *searchfor) const;
|
||||||
@ -110,7 +127,8 @@ public:
|
|||||||
TimerProgressDialog(const wxLongLong_t duration,
|
TimerProgressDialog(const wxLongLong_t duration,
|
||||||
const wxString & title,
|
const wxString & title,
|
||||||
const wxString & message = wxEmptyString,
|
const wxString & message = wxEmptyString,
|
||||||
int flags = pdlgDefaultFlags);
|
int flags = pdlgDefaultFlags,
|
||||||
|
const wxString & sRemainingLabelText = wxEmptyString);
|
||||||
int Update(const wxString & message = wxEmptyString);
|
int Update(const wxString & message = wxEmptyString);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user