2010-01-23 19:44:49 +00:00
|
|
|
/**********************************************************************
|
|
|
|
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
|
|
|
|
BatchProcessDialog.cpp
|
|
|
|
|
|
|
|
Dominic Mazzoni
|
|
|
|
James Crook
|
|
|
|
|
|
|
|
*******************************************************************//*!
|
|
|
|
|
|
|
|
\class BatchProcessDialog
|
|
|
|
\brief Shows progress in executing commands in BatchCommands.
|
|
|
|
|
|
|
|
*//*******************************************************************/
|
|
|
|
|
|
|
|
#include "Audacity.h"
|
2015-06-18 14:24:36 +00:00
|
|
|
#include "BatchProcessDialog.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
#include <wx/defs.h>
|
|
|
|
#include <wx/checkbox.h>
|
|
|
|
#include <wx/choice.h>
|
|
|
|
#include <wx/filedlg.h>
|
|
|
|
#include <wx/intl.h>
|
|
|
|
#include <wx/sizer.h>
|
|
|
|
#include <wx/statbox.h>
|
|
|
|
#include <wx/stattext.h>
|
|
|
|
#include <wx/textctrl.h>
|
|
|
|
#include <wx/listctrl.h>
|
|
|
|
#include <wx/radiobut.h>
|
|
|
|
#include <wx/button.h>
|
|
|
|
#include <wx/imaglist.h>
|
|
|
|
#include <wx/settings.h>
|
|
|
|
|
2016-12-03 19:33:37 +00:00
|
|
|
#include "AudacityException.h"
|
2015-06-18 14:24:36 +00:00
|
|
|
#include "ShuttleGui.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "Prefs.h"
|
|
|
|
#include "Project.h"
|
|
|
|
#include "Internat.h"
|
|
|
|
#include "commands/CommandManager.h"
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
#include "commands/CommandContext.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "effects/Effect.h"
|
|
|
|
#include "../images/Arrow.xpm"
|
The fabled realtime effects...
I've made it where you can enable and disable via experimentals:
EXPERIMENTAL_REALTIME_EFFECTS
EXPERIMENTAL_EFFECTS_RACK
You will notice that, as of now, the only effects currently set up for
realtime are VSTs. Now that this is in, I will start converting the
rest.
As I start to convert the effects, the astute of you may notice that
they no longer directly access tracks or any "internal" Audacity
objects. This isolates the effects from changes in Audacity and makes
it much easier to add new ones.
Anyway, all 3 platforms can now display VST effects in graphical mode.
Yes, that means Linux too. There are quite a few VSTs for Linux if
you search for them.
The so-called "rack" definitely needs some discussion, work, and attention
from someone much better at graphics than me. I'm not really sure it should
stay in as-is. I'd originally planned for it to be simply a utility window
where you can store your (preconfigured) favorite effects. It should probably
revert back to that idea.
You may notice that this DOES include the API work I did. The realtime effects
were too tied to it and I didn't want to redo the whole thing. As I mentioned
elsewhere, the API stuff may or may not be very future proof.
So, let the critter complaints commence. I absolute KNOW there will be some.
(I know I'll be hearing from the Linux peeps pretty darn quickly. ;-))
2014-10-26 03:24:10 +00:00
|
|
|
#include "../images/Empty9x16.xpm"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "BatchCommands.h"
|
2016-02-24 16:41:26 +00:00
|
|
|
#include "Track.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "UndoManager.h"
|
|
|
|
|
|
|
|
#include "Theme.h"
|
|
|
|
#include "AllThemeResources.h"
|
|
|
|
|
|
|
|
#include "FileDialog.h"
|
2017-08-03 10:41:38 +00:00
|
|
|
#include "FileNames.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
#include "import/Import.h"
|
2017-09-06 21:39:33 +00:00
|
|
|
#include "widgets/ErrorDialog.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
#define ChainsListID 7001
|
2013-03-10 09:05:41 +00:00
|
|
|
#define CommandsListID 7002
|
|
|
|
#define ApplyToProjectID 7003
|
|
|
|
#define ApplyToFilesID 7004
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-07-10 21:10:50 +00:00
|
|
|
BEGIN_EVENT_TABLE(BatchProcessDialog, wxDialogWrapper)
|
2010-01-23 19:44:49 +00:00
|
|
|
EVT_BUTTON(ApplyToProjectID, BatchProcessDialog::OnApplyToProject)
|
|
|
|
EVT_BUTTON(ApplyToFilesID, BatchProcessDialog::OnApplyToFiles)
|
|
|
|
EVT_BUTTON(wxID_CANCEL, BatchProcessDialog::OnCancel)
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
BatchProcessDialog::BatchProcessDialog(wxWindow * parent, bool bInherited):
|
2016-07-10 21:10:50 +00:00
|
|
|
wxDialogWrapper(parent, wxID_ANY, _("Apply Chain"),
|
2010-01-23 19:44:49 +00:00
|
|
|
wxDefaultPosition, wxDefaultSize,
|
|
|
|
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
|
|
|
{
|
2013-08-25 21:51:26 +00:00
|
|
|
//AudacityProject * p = GetActiveProject();
|
2018-03-01 17:54:08 +00:00
|
|
|
mAbort = false;
|
|
|
|
if( bInherited )
|
|
|
|
return;
|
2010-01-23 19:44:49 +00:00
|
|
|
SetLabel(_("Apply Chain")); // Provide visual label
|
|
|
|
SetName(_("Apply Chain")); // Provide audible label
|
|
|
|
Populate();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BatchProcessDialog::~BatchProcessDialog()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void BatchProcessDialog::Populate()
|
|
|
|
{
|
|
|
|
//------------------------- Main section --------------------
|
|
|
|
ShuttleGui S(this, eIsCreating);
|
|
|
|
PopulateOrExchange(S);
|
|
|
|
// ----------------------- End of main section --------------
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Defines the dialog and does data exchange with it.
|
|
|
|
void BatchProcessDialog::PopulateOrExchange(ShuttleGui &S)
|
|
|
|
{
|
|
|
|
S.StartVerticalLay(true);
|
|
|
|
{
|
2014-06-03 20:30:19 +00:00
|
|
|
/*i18n-hint: A chain is a sequence of commands that can be applied
|
2012-03-20 15:36:02 +00:00
|
|
|
* to one or more audio files.*/
|
2013-02-14 05:51:32 +00:00
|
|
|
S.StartStatic(_("&Select Chain"), true);
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
|
|
|
|
wxLC_SINGLE_SEL);
|
|
|
|
mChains = S.Id(ChainsListID).AddListControlReportMode();
|
|
|
|
mChains->InsertColumn(0, _("Chain"), wxLIST_FORMAT_LEFT);
|
|
|
|
}
|
|
|
|
S.EndStatic();
|
|
|
|
|
|
|
|
S.StartHorizontalLay(wxALIGN_RIGHT, false);
|
|
|
|
{
|
|
|
|
S.SetBorder(10);
|
|
|
|
S.Id(ApplyToProjectID).AddButton(_("Apply to Current &Project"));
|
|
|
|
S.Id(ApplyToFilesID).AddButton(_("Apply to &Files..."));
|
|
|
|
S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndVerticalLay();
|
|
|
|
|
|
|
|
wxArrayString names = mBatchCommands.GetNames();
|
|
|
|
for (int i = 0; i < (int)names.GetCount(); i++) {
|
|
|
|
mChains->InsertItem(i, names[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get and validate the currently active chain
|
2012-04-26 22:57:04 +00:00
|
|
|
wxString name = gPrefs->Read(wxT("/Batch/ActiveChain"), wxT(""));
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
int item = mChains->FindItem(-1, name);
|
|
|
|
if (item == -1) {
|
|
|
|
item = 0;
|
|
|
|
name = mChains->GetItemText(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the name in the list...this will fire an event.
|
|
|
|
mChains->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
|
|
|
|
|
|
|
Layout();
|
|
|
|
Fit();
|
|
|
|
SetSizeHints(GetSize());
|
|
|
|
Center();
|
|
|
|
|
|
|
|
// Set the column size for the chains list.
|
|
|
|
wxSize sz = mChains->GetClientSize();
|
|
|
|
mChains->SetColumnWidth(0, sz.x);
|
|
|
|
}
|
|
|
|
|
2013-08-25 21:51:26 +00:00
|
|
|
void BatchProcessDialog::OnApplyToProject(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mChains->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1) {
|
2017-09-06 21:39:33 +00:00
|
|
|
AudacityMessageBox(_("No chain selected"));
|
2010-01-23 19:44:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
wxString name = mChains->GetItemText(item);
|
|
|
|
|
2016-07-10 21:10:50 +00:00
|
|
|
wxDialog * pD = safenew wxDialogWrapper(this, wxID_ANY, GetTitle());
|
2015-10-09 22:28:53 +00:00
|
|
|
pD->SetName(pD->GetTitle());
|
|
|
|
ShuttleGui S(pD, eIsCreating);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
2017-09-28 01:20:14 +00:00
|
|
|
S.StartStatic( {}, false); // deliberately not translated (!)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
S.SetBorder(20);
|
|
|
|
S.AddFixedText(wxString::Format(_("Applying '%s' to current project"),
|
2017-10-09 05:03:14 +00:00
|
|
|
name));
|
Automation: AudacityCommand
This is a squash of 50 commits.
This merges the capabilities of BatchCommands and Effects using a new
AudacityCommand class. AudacityCommand provides one function to specify the
parameters, and then we leverage that one function in automation, whether by chains,
mod-script-pipe or (future) Nyquist.
- Now have AudacityCommand which is using the same mechanism as Effect
- Has configurable parameters
- Has data-entry GUI (built using shuttle GUI)
- Registers with PluginManager.
- Menu commands now provided in chains, and to python batch.
- Tested with Zoom Toggle.
- ShuttleParams now can set, get, set defaults, validate and specify
the parameters.
- Bugfix: Don't overwrite values with defaults first time out.
- Add DefineParams function for all built-in effects.
- Extend CommandContext to carry output channels for results.
We abuse EffectsManager. It handles both Effects and
AudacityCommands now. In time an Effect should become a special case of
AudacityCommand and we'll split and rename the EffectManager class.
- Don't use 'default' as a parameter name.
- Massive renaming for CommandDefinitionInterface
- EffectIdentInterface becomes EffectDefinitionInterface
- EffectAutomationParameters becomes CommandAutomationParameters
- PluginType is now a bit field.
This way we can search for related types at the same time.
- Most old batch commands made into AudacityCommands.
The ones that weren't are for a reason. They are used by mod-script-pipe
to carry commands and responses across from a non-GUI thread to the GUI
thread.
- Major tidy up of ScreenshotCommand
- Reworking of SelectCommand
- GetPreferenceCommand and SetPreferenceCommand
- GetTrackInfo and SetTrackInfo
- GetInfoCommand
- Help, Open, Save, Import and Export commands.
- Removed obsolete commands ExecMenu, GetProjectInfo and SetProjectInfo
which are now better handled by other commands.
- JSONify "GetInfo: Commands" output, i.e. commas in the right places.
- General work on better Doxygen.
- Lyrics -> LyricsPanel
- Meter -> MeterPanel
- Updated Linux makefile.
- Scripting commands added into Extra menu.
- Distinct names for previously duplicated find-clipping parameters.
- Fixed longstanding error with erroneous status field number which
previously caused an ASSERT in debug.
- Sensible formatting of numbers in Chains, 0.1 not 0.1000000000137
2018-01-14 18:51:41 +00:00
|
|
|
mResults = S.AddTextWindow( wxT("") );
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
S.EndStatic();
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
2015-10-09 22:28:53 +00:00
|
|
|
pD->Layout();
|
|
|
|
pD->Fit();
|
|
|
|
pD->CenterOnScreen();
|
|
|
|
pD->Move(-1, 0);
|
|
|
|
pD->Show();
|
|
|
|
|
2015-10-10 14:41:59 +00:00
|
|
|
// The Hide() on the next line seems to tickle a bug in wx3,
|
|
|
|
// giving rise to our Bug #1221. The problem is that on Linux
|
|
|
|
// the 'Hide' converts us from a Modal into a regular dialog,
|
|
|
|
// as far as closing is concerned. On Linux we can't close with
|
|
|
|
// EndModal() anymore after this.
|
|
|
|
Hide();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
gPrefs->Write(wxT("/Batch/ActiveChain"), name);
|
2012-08-02 06:03:19 +00:00
|
|
|
gPrefs->Flush();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
mBatchCommands.ReadChain(name);
|
2015-07-24 05:02:19 +00:00
|
|
|
|
|
|
|
// The disabler must get deleted before the EndModal() call. Otherwise,
|
|
|
|
// the menus on OSX will remain disabled.
|
2016-02-01 01:39:24 +00:00
|
|
|
bool success;
|
|
|
|
{
|
|
|
|
wxWindowDisabler wd(pD);
|
2016-12-03 19:33:37 +00:00
|
|
|
success = GuardedCall< bool >(
|
|
|
|
[this]{ return mBatchCommands.ApplyChain(); } );
|
2016-02-01 01:39:24 +00:00
|
|
|
}
|
2015-07-24 05:02:19 +00:00
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
Show();
|
2010-01-23 19:44:49 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-10-09 22:53:49 +00:00
|
|
|
|
2015-10-10 14:41:59 +00:00
|
|
|
#if !defined(__WXMAC__)
|
|
|
|
// Under Linux an EndModal() here crashes (Bug #1221).
|
2015-10-09 22:53:49 +00:00
|
|
|
// But sending a close message instead is OK.
|
2015-10-09 22:28:53 +00:00
|
|
|
wxCloseEvent Evt;
|
2015-10-10 14:27:35 +00:00
|
|
|
Evt.SetId( wxID_OK );
|
2015-10-09 22:28:53 +00:00
|
|
|
Evt.SetEventObject( this);
|
|
|
|
ProcessWindowEvent( Evt );
|
2015-10-10 14:41:59 +00:00
|
|
|
#else
|
|
|
|
EndModal(wxID_OK);
|
|
|
|
#endif
|
2016-01-27 19:58:51 +00:00
|
|
|
|
|
|
|
// Raise myself again, and the parent window with me
|
|
|
|
Show();
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2013-08-25 21:51:26 +00:00
|
|
|
void BatchProcessDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mChains->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1) {
|
2017-09-06 21:39:33 +00:00
|
|
|
AudacityMessageBox(_("No chain selected"));
|
2010-01-23 19:44:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString name = mChains->GetItemText(item);
|
|
|
|
gPrefs->Write(wxT("/Batch/ActiveChain"), name);
|
2012-08-02 06:03:19 +00:00
|
|
|
gPrefs->Flush();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
AudacityProject *project = GetActiveProject();
|
|
|
|
if (!project->GetIsEmpty()) {
|
2017-09-06 21:39:33 +00:00
|
|
|
AudacityMessageBox(_("Please save and close the current project first."));
|
2010-01-23 19:44:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-26 22:57:04 +00:00
|
|
|
wxString prompt = _("Select file(s) for batch processing...");
|
2014-06-03 20:30:19 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
FormatList l;
|
|
|
|
wxString filter;
|
|
|
|
wxString all;
|
|
|
|
|
The fabled realtime effects...
I've made it where you can enable and disable via experimentals:
EXPERIMENTAL_REALTIME_EFFECTS
EXPERIMENTAL_EFFECTS_RACK
You will notice that, as of now, the only effects currently set up for
realtime are VSTs. Now that this is in, I will start converting the
rest.
As I start to convert the effects, the astute of you may notice that
they no longer directly access tracks or any "internal" Audacity
objects. This isolates the effects from changes in Audacity and makes
it much easier to add new ones.
Anyway, all 3 platforms can now display VST effects in graphical mode.
Yes, that means Linux too. There are quite a few VSTs for Linux if
you search for them.
The so-called "rack" definitely needs some discussion, work, and attention
from someone much better at graphics than me. I'm not really sure it should
stay in as-is. I'd originally planned for it to be simply a utility window
where you can store your (preconfigured) favorite effects. It should probably
revert back to that idea.
You may notice that this DOES include the API work I did. The realtime effects
were too tied to it and I didn't want to redo the whole thing. As I mentioned
elsewhere, the API stuff may or may not be very future proof.
So, let the critter complaints commence. I absolute KNOW there will be some.
(I know I'll be hearing from the Linux peeps pretty darn quickly. ;-))
2014-10-26 03:24:10 +00:00
|
|
|
Importer::Get().GetSupportedImportFormats(&l);
|
2016-02-19 15:59:51 +00:00
|
|
|
for (const auto &format : l) {
|
|
|
|
const Format *f = &format;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
wxString newfilter = f->formatName + wxT("|");
|
The fabled realtime effects...
I've made it where you can enable and disable via experimentals:
EXPERIMENTAL_REALTIME_EFFECTS
EXPERIMENTAL_EFFECTS_RACK
You will notice that, as of now, the only effects currently set up for
realtime are VSTs. Now that this is in, I will start converting the
rest.
As I start to convert the effects, the astute of you may notice that
they no longer directly access tracks or any "internal" Audacity
objects. This isolates the effects from changes in Audacity and makes
it much easier to add new ones.
Anyway, all 3 platforms can now display VST effects in graphical mode.
Yes, that means Linux too. There are quite a few VSTs for Linux if
you search for them.
The so-called "rack" definitely needs some discussion, work, and attention
from someone much better at graphics than me. I'm not really sure it should
stay in as-is. I'd originally planned for it to be simply a utility window
where you can store your (preconfigured) favorite effects. It should probably
revert back to that idea.
You may notice that this DOES include the API work I did. The realtime effects
were too tied to it and I didn't want to redo the whole thing. As I mentioned
elsewhere, the API stuff may or may not be very future proof.
So, let the critter complaints commence. I absolute KNOW there will be some.
(I know I'll be hearing from the Linux peeps pretty darn quickly. ;-))
2014-10-26 03:24:10 +00:00
|
|
|
for (size_t i = 0; i < f->formatExtensions.size(); i++) {
|
2010-01-23 19:44:49 +00:00
|
|
|
if (!newfilter.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
|
|
|
|
newfilter += wxT("*.") + f->formatExtensions[i] + wxT(";");
|
|
|
|
if (!all.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
|
|
|
|
all += wxT("*.") + f->formatExtensions[i] + wxT(";");
|
|
|
|
}
|
|
|
|
newfilter.RemoveLast(1);
|
|
|
|
filter += newfilter;
|
|
|
|
filter += wxT("|");
|
|
|
|
}
|
|
|
|
all.RemoveLast(1);
|
|
|
|
filter.RemoveLast(1);
|
|
|
|
|
|
|
|
wxString mask = _("All files|*|All supported files|") +
|
|
|
|
all + wxT("|") +
|
|
|
|
filter;
|
|
|
|
|
|
|
|
wxString type = gPrefs->Read(wxT("/DefaultOpenType"),mask.BeforeFirst(wxT('|')));
|
|
|
|
// Convert the type to the filter index
|
|
|
|
int index = mask.First(type + wxT("|"));
|
|
|
|
if (index == wxNOT_FOUND) {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
index = mask.Left(index).Freq(wxT('|')) / 2;
|
|
|
|
if (index < 0) {
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 10:41:38 +00:00
|
|
|
auto path = FileNames::FindDefaultPath(FileNames::Operation::Open);
|
2017-10-12 19:41:52 +00:00
|
|
|
FileDialogWrapper dlog(this,
|
2013-02-20 23:42:58 +00:00
|
|
|
prompt,
|
|
|
|
path,
|
|
|
|
wxT(""),
|
|
|
|
mask,
|
2010-01-23 19:44:49 +00:00
|
|
|
wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);
|
|
|
|
|
|
|
|
dlog.SetFilterIndex(index);
|
|
|
|
if (dlog.ShowModal() != wxID_OK) {
|
|
|
|
return;
|
|
|
|
}
|
2017-08-03 10:41:38 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
wxArrayString files;
|
|
|
|
dlog.GetPaths(files);
|
|
|
|
|
|
|
|
files.Sort();
|
|
|
|
|
2016-07-10 21:10:50 +00:00
|
|
|
wxDialog * pD = safenew wxDialogWrapper(this, wxID_ANY, GetTitle());
|
2015-10-09 22:53:49 +00:00
|
|
|
pD->SetName(pD->GetTitle());
|
|
|
|
ShuttleGui S(pD, eIsCreating);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
S.StartVerticalLay(false);
|
|
|
|
{
|
|
|
|
S.StartStatic(_("Applying..."), 1);
|
|
|
|
{
|
2016-08-10 05:34:44 +00:00
|
|
|
auto imageList = std::make_unique<wxImageList>(9, 16);
|
The fabled realtime effects...
I've made it where you can enable and disable via experimentals:
EXPERIMENTAL_REALTIME_EFFECTS
EXPERIMENTAL_EFFECTS_RACK
You will notice that, as of now, the only effects currently set up for
realtime are VSTs. Now that this is in, I will start converting the
rest.
As I start to convert the effects, the astute of you may notice that
they no longer directly access tracks or any "internal" Audacity
objects. This isolates the effects from changes in Audacity and makes
it much easier to add new ones.
Anyway, all 3 platforms can now display VST effects in graphical mode.
Yes, that means Linux too. There are quite a few VSTs for Linux if
you search for them.
The so-called "rack" definitely needs some discussion, work, and attention
from someone much better at graphics than me. I'm not really sure it should
stay in as-is. I'd originally planned for it to be simply a utility window
where you can store your (preconfigured) favorite effects. It should probably
revert back to that idea.
You may notice that this DOES include the API work I did. The realtime effects
were too tied to it and I didn't want to redo the whole thing. As I mentioned
elsewhere, the API stuff may or may not be very future proof.
So, let the critter complaints commence. I absolute KNOW there will be some.
(I know I'll be hearing from the Linux peeps pretty darn quickly. ;-))
2014-10-26 03:24:10 +00:00
|
|
|
imageList->Add(wxIcon(empty9x16_xpm));
|
2010-01-23 19:44:49 +00:00
|
|
|
imageList->Add(wxIcon(arrow_xpm));
|
|
|
|
|
|
|
|
S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
|
|
|
|
wxLC_SINGLE_SEL);
|
2013-03-10 09:05:41 +00:00
|
|
|
mList = S.Id(CommandsListID).AddListControlReportMode();
|
2016-08-10 05:34:44 +00:00
|
|
|
// AssignImageList takes ownership
|
|
|
|
mList->AssignImageList(imageList.release(), wxIMAGE_LIST_SMALL);
|
2010-01-23 19:44:49 +00:00
|
|
|
mList->InsertColumn(0, _("File"), wxLIST_FORMAT_LEFT);
|
|
|
|
}
|
|
|
|
S.EndStatic();
|
|
|
|
|
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
|
|
|
S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndVerticalLay();
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < (int)files.GetCount(); i++ ) {
|
|
|
|
mList->InsertItem(i, files[i], i == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the column size for the files list.
|
|
|
|
mList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
|
|
|
|
|
|
|
int width = mList->GetColumnWidth(0);
|
|
|
|
wxSize sz = mList->GetClientSize();
|
|
|
|
if (width > sz.GetWidth() && width < 500) {
|
|
|
|
sz.SetWidth(width);
|
|
|
|
mList->SetInitialSize(sz);
|
|
|
|
}
|
|
|
|
|
2015-10-09 22:53:49 +00:00
|
|
|
pD->Layout();
|
|
|
|
pD->Fit();
|
|
|
|
pD->SetSizeHints(pD->GetSize());
|
|
|
|
pD->CenterOnScreen();
|
|
|
|
pD->Move(-1, 0);
|
|
|
|
pD->Show();
|
2010-01-23 19:44:49 +00:00
|
|
|
Hide();
|
|
|
|
|
|
|
|
mBatchCommands.ReadChain(name);
|
|
|
|
for (i = 0; i < (int)files.GetCount(); i++) {
|
2015-10-09 22:53:49 +00:00
|
|
|
wxWindowDisabler wd(pD);
|
2010-01-23 19:44:49 +00:00
|
|
|
if (i > 0) {
|
|
|
|
//Clear the arrow in previous item.
|
|
|
|
mList->SetItemImage(i - 1, 0, 0);
|
|
|
|
}
|
|
|
|
mList->SetItemImage(i, 1, 1);
|
|
|
|
mList->EnsureVisible(i);
|
|
|
|
|
2016-12-03 19:33:37 +00:00
|
|
|
auto success = GuardedCall< bool >( [&] {
|
|
|
|
project->Import(files[i]);
|
2017-12-30 19:13:31 +00:00
|
|
|
project->ZoomAfterImport(nullptr);
|
2017-08-19 14:15:32 +00:00
|
|
|
project->OnSelectAll(*project);
|
2016-12-03 19:33:37 +00:00
|
|
|
if (!mBatchCommands.ApplyChain())
|
|
|
|
return false;
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2016-12-03 19:33:37 +00:00
|
|
|
if (!pD->IsShown() || mAbort)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} );
|
|
|
|
|
|
|
|
if (!success)
|
2010-01-23 19:44:49 +00:00
|
|
|
break;
|
2016-12-03 19:33:37 +00:00
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
UndoManager *um = project->GetUndoManager();
|
|
|
|
um->ClearStates();
|
2017-08-19 14:15:32 +00:00
|
|
|
project->OnSelectAll(*project);
|
|
|
|
project->OnRemoveTracks(*project);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
2017-08-19 14:15:32 +00:00
|
|
|
project->OnRemoveTracks(*project);
|
2015-07-24 05:02:19 +00:00
|
|
|
|
2015-10-10 14:41:59 +00:00
|
|
|
// Under Linux an EndModal() here crashes (Bug #1221).
|
2015-10-09 22:53:49 +00:00
|
|
|
// But sending a close message instead is OK.
|
2015-10-10 14:41:59 +00:00
|
|
|
#if !defined(__WXMAC__)
|
2015-10-09 22:53:49 +00:00
|
|
|
wxCloseEvent Evt;
|
2015-10-10 14:27:35 +00:00
|
|
|
Evt.SetId( wxID_OK );
|
2015-10-09 22:53:49 +00:00
|
|
|
Evt.SetEventObject( this);
|
|
|
|
ProcessWindowEvent( Evt );
|
2015-10-10 14:41:59 +00:00
|
|
|
#else
|
|
|
|
EndModal(wxID_OK);
|
|
|
|
#endif
|
2016-01-27 19:58:51 +00:00
|
|
|
|
|
|
|
// Raise myself again, and the parent window with me
|
|
|
|
Show();
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2013-08-25 21:51:26 +00:00
|
|
|
void BatchProcessDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
2015-10-10 14:41:59 +00:00
|
|
|
#if !defined(__WXMAC__)
|
|
|
|
// It is possible that we could just do EndModal()
|
|
|
|
// here even on Linux. However, we know the alternative way of
|
|
|
|
// closing works, if we are hidden, so we hide and then do that.
|
2015-10-10 14:27:35 +00:00
|
|
|
Hide();
|
2015-10-10 14:41:59 +00:00
|
|
|
// Under Linux an EndModal() here potentially crashes (Bug #1221).
|
2015-10-09 22:53:49 +00:00
|
|
|
// But sending a close message instead is OK.
|
|
|
|
wxCloseEvent Evt;
|
2015-10-10 14:27:35 +00:00
|
|
|
Evt.SetId( wxID_CANCEL );
|
2015-10-09 22:53:49 +00:00
|
|
|
Evt.SetEventObject( this);
|
|
|
|
ProcessWindowEvent( Evt );
|
2015-10-10 14:27:35 +00:00
|
|
|
#else
|
|
|
|
EndModal(wxID_CANCEL);
|
|
|
|
#endif
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
#include <wx/textdlg.h>
|
2013-11-01 12:15:01 +00:00
|
|
|
#include "BatchCommandDialog.h"
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
AddButtonID = 10000,
|
|
|
|
RemoveButtonID,
|
|
|
|
ImportButtonID,
|
|
|
|
ExportButtonID,
|
|
|
|
DefaultsButtonID,
|
|
|
|
InsertButtonID,
|
2018-03-01 17:54:08 +00:00
|
|
|
EditButtonID,
|
2010-01-23 19:44:49 +00:00
|
|
|
DeleteButtonID,
|
|
|
|
UpButtonID,
|
|
|
|
DownButtonID,
|
2018-03-01 17:54:08 +00:00
|
|
|
RenameButtonID,
|
|
|
|
// ChainsListID 7005
|
|
|
|
// CommandsListID, 7002
|
|
|
|
// Re-Use IDs from BatchProcessDialog.
|
|
|
|
ApplyToProjectButtonID = ApplyToProjectID,
|
|
|
|
ApplyToFilesButtonID = ApplyToFilesID,
|
2010-01-23 19:44:49 +00:00
|
|
|
};
|
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
BEGIN_EVENT_TABLE(EditChainsDialog, BatchProcessDialog)
|
2010-01-23 19:44:49 +00:00
|
|
|
EVT_LIST_ITEM_SELECTED(ChainsListID, EditChainsDialog::OnChainSelected)
|
2013-03-10 09:05:41 +00:00
|
|
|
EVT_LIST_ITEM_SELECTED(CommandsListID, EditChainsDialog::OnListSelected)
|
2010-01-23 19:44:49 +00:00
|
|
|
EVT_LIST_BEGIN_LABEL_EDIT(ChainsListID, EditChainsDialog::OnChainsBeginEdit)
|
|
|
|
EVT_LIST_END_LABEL_EDIT(ChainsListID, EditChainsDialog::OnChainsEndEdit)
|
|
|
|
EVT_BUTTON(AddButtonID, EditChainsDialog::OnAdd)
|
|
|
|
EVT_BUTTON(RemoveButtonID, EditChainsDialog::OnRemove)
|
|
|
|
EVT_BUTTON(RenameButtonID, EditChainsDialog::OnRename)
|
2013-03-10 09:05:41 +00:00
|
|
|
EVT_SIZE(EditChainsDialog::OnSize)
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
EVT_LIST_ITEM_ACTIVATED(CommandsListID, EditChainsDialog::OnCommandActivated)
|
|
|
|
EVT_BUTTON(InsertButtonID, EditChainsDialog::OnInsert)
|
2018-03-01 17:54:08 +00:00
|
|
|
EVT_BUTTON(EditButtonID, EditChainsDialog::OnEditCommandParams)
|
2010-01-23 19:44:49 +00:00
|
|
|
EVT_BUTTON(DeleteButtonID, EditChainsDialog::OnDelete)
|
|
|
|
EVT_BUTTON(UpButtonID, EditChainsDialog::OnUp)
|
|
|
|
EVT_BUTTON(DownButtonID, EditChainsDialog::OnDown)
|
|
|
|
EVT_BUTTON(DefaultsButtonID, EditChainsDialog::OnDefaults)
|
|
|
|
|
|
|
|
EVT_BUTTON(wxID_OK, EditChainsDialog::OnOK)
|
|
|
|
EVT_BUTTON(wxID_CANCEL, EditChainsDialog::OnCancel)
|
|
|
|
|
|
|
|
EVT_KEY_DOWN(EditChainsDialog::OnKeyDown)
|
|
|
|
END_EVENT_TABLE()
|
|
|
|
|
|
|
|
enum {
|
2014-06-03 20:30:19 +00:00
|
|
|
BlankColumn,
|
|
|
|
ItemNumberColumn,
|
|
|
|
ActionColumn,
|
2010-01-23 19:44:49 +00:00
|
|
|
ParamsColumn,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Constructor
|
|
|
|
EditChainsDialog::EditChainsDialog(wxWindow * parent):
|
2018-03-01 17:54:08 +00:00
|
|
|
BatchProcessDialog(parent, true)
|
|
|
|
// , wxID_ANY, _("Edit Chains"),
|
|
|
|
// wxDefaultPosition, wxDefaultSize,
|
|
|
|
// wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
SetLabel(_("Edit Chains")); // Provide visual label
|
|
|
|
SetName(_("Edit Chains")); // Provide audible label
|
2018-03-01 17:54:08 +00:00
|
|
|
SetTitle(_("Edit Chains"));
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
mChanged = false;
|
|
|
|
mSelectedCommand = 0;
|
|
|
|
|
|
|
|
Populate();
|
|
|
|
}
|
|
|
|
|
|
|
|
EditChainsDialog::~EditChainsDialog()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates the dialog and its contents.
|
|
|
|
void EditChainsDialog::Populate()
|
|
|
|
{
|
2018-01-10 02:49:49 +00:00
|
|
|
mCommandNames = BatchCommands::GetAllCommands();
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
//------------------------- Main section --------------------
|
|
|
|
ShuttleGui S(this, eIsCreating);
|
|
|
|
PopulateOrExchange(S);
|
|
|
|
// ----------------------- End of main section --------------
|
|
|
|
|
|
|
|
// Get and validate the currently active chain
|
2012-04-26 22:57:04 +00:00
|
|
|
mActiveChain = gPrefs->Read(wxT("/Batch/ActiveChain"), wxT(""));
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
// Go populate the chains list.
|
|
|
|
PopulateChains();
|
|
|
|
|
|
|
|
// We have a bare list. We need to add columns and content.
|
|
|
|
PopulateList();
|
|
|
|
|
|
|
|
// Layout and set minimum size of window
|
|
|
|
Layout();
|
|
|
|
Fit();
|
|
|
|
SetSizeHints(GetSize());
|
|
|
|
|
|
|
|
// Size and place window
|
|
|
|
SetSize(wxSystemSettings::GetMetric(wxSYS_SCREEN_X) * 3 / 4,
|
|
|
|
wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) * 4 / 5);
|
|
|
|
Center();
|
|
|
|
|
|
|
|
// Set the column size for the chains list.
|
|
|
|
wxSize sz = mChains->GetClientSize();
|
|
|
|
mChains->SetColumnWidth(0, sz.x);
|
|
|
|
|
|
|
|
// Size columns properly
|
2013-03-10 09:05:41 +00:00
|
|
|
FitColumns();
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Defines the dialog and does data exchange with it.
|
|
|
|
void EditChainsDialog::PopulateOrExchange(ShuttleGui & S)
|
|
|
|
{
|
|
|
|
S.StartHorizontalLay(wxEXPAND, 1);
|
|
|
|
{
|
|
|
|
S.StartStatic(_("&Chains"));
|
|
|
|
{
|
|
|
|
// JKC: Experimenting with an alternative way to get multiline
|
|
|
|
// translated strings to work correctly without very long lines.
|
|
|
|
// My appologies Alexandre if this way didn't work either.
|
2014-06-03 20:30:19 +00:00
|
|
|
//
|
2010-01-23 19:44:49 +00:00
|
|
|
// With this method:
|
|
|
|
// 1) it compiles fine under windows unicode and normal mode.
|
|
|
|
// 2) xgettext source code has handling for the trailing '\'
|
|
|
|
//
|
2014-06-03 20:30:19 +00:00
|
|
|
// It remains to see if linux and mac can cope and if xgettext
|
2010-01-23 19:44:49 +00:00
|
|
|
// actually does do fine with strings presented like this.
|
|
|
|
// If it doesn't work out, revert to all-on-one-line.
|
|
|
|
S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_SINGLE_SEL |
|
|
|
|
wxLC_EDIT_LABELS);
|
|
|
|
mChains = S.Id(ChainsListID).AddListControlReportMode();
|
2017-07-22 10:33:09 +00:00
|
|
|
// i18n-hint: This is the heading for a column in the edit chains dialog
|
|
|
|
mChains->InsertColumn(0, _("Chain"), wxLIST_FORMAT_LEFT);
|
2010-01-23 19:44:49 +00:00
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
|
|
|
S.Id(AddButtonID).AddButton(_("&Add"));
|
|
|
|
mRemove = S.Id(RemoveButtonID).AddButton(_("&Remove"));
|
|
|
|
mRename = S.Id(RenameButtonID).AddButton(_("Re&name"));
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndStatic();
|
|
|
|
|
|
|
|
S.StartStatic(_("C&hain (Double-Click or press SPACE to edit)"), true);
|
|
|
|
{
|
|
|
|
S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
|
|
|
|
wxLC_SINGLE_SEL);
|
|
|
|
mList = S.Id(CommandsListID).AddListControlReportMode();
|
|
|
|
|
2014-06-03 20:30:19 +00:00
|
|
|
//An empty first column is a workaround - under Win98 the first column
|
2010-01-23 19:44:49 +00:00
|
|
|
//can't be right aligned.
|
|
|
|
mList->InsertColumn(BlankColumn, wxT(""), wxLIST_FORMAT_LEFT);
|
|
|
|
/* i18n-hint: This is the number of the command in the list */
|
|
|
|
mList->InsertColumn(ItemNumberColumn, _("Num"), wxLIST_FORMAT_RIGHT);
|
2013-03-10 09:05:41 +00:00
|
|
|
mList->InsertColumn(ActionColumn, _("Command "), wxLIST_FORMAT_RIGHT);
|
2010-01-23 19:44:49 +00:00
|
|
|
mList->InsertColumn(ParamsColumn, _("Parameters"), wxLIST_FORMAT_LEFT);
|
|
|
|
|
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
2018-03-01 17:54:08 +00:00
|
|
|
S.AddPrompt( _("Command:") );
|
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
|
|
|
S.Id(InsertButtonID).AddButton(_("&Insert"), wxALIGN_LEFT);
|
|
|
|
S.Id(EditButtonID).AddButton(_("&Edit"), wxALIGN_LEFT);
|
|
|
|
S.Id(DeleteButtonID).AddButton(_("De&lete"), wxALIGN_LEFT);
|
|
|
|
S.Id(UpButtonID).AddButton(_("Move &Up"), wxALIGN_LEFT);
|
|
|
|
S.Id(DownButtonID).AddButton(_("Move &Down"), wxALIGN_LEFT);
|
|
|
|
mDefaults = S.Id(DefaultsButtonID).AddButton(_("De&faults"));
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
S.AddSpace( 40 );
|
|
|
|
S.AddPrompt( _("Apply Chain to:") );
|
|
|
|
S.StartHorizontalLay(wxCENTER, false);
|
|
|
|
{
|
|
|
|
S.Id(ApplyToProjectButtonID).AddButton(_("&Project"), wxALIGN_LEFT);
|
|
|
|
S.Id(ApplyToFilesButtonID).AddButton(_("&Files"), wxALIGN_LEFT);
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
}
|
|
|
|
S.EndStatic();
|
|
|
|
}
|
|
|
|
S.EndHorizontalLay();
|
|
|
|
|
|
|
|
S.AddStandardButtons();
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This clears and updates the contents of mChains
|
|
|
|
void EditChainsDialog::PopulateChains()
|
|
|
|
{
|
|
|
|
wxArrayString names = mBatchCommands.GetNames();
|
|
|
|
int i;
|
|
|
|
|
|
|
|
mChains->DeleteAllItems();
|
|
|
|
for (i = 0; i < (int)names.GetCount(); i++) {
|
|
|
|
mChains->InsertItem(i, names[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
int item = mChains->FindItem(-1, mActiveChain);
|
|
|
|
if (item == -1) {
|
|
|
|
item = 0;
|
|
|
|
mActiveChain = mChains->GetItemText(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the name in the list...this will fire an event.
|
|
|
|
mChains->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This clears and updates the contents of mList
|
|
|
|
void EditChainsDialog::PopulateList()
|
|
|
|
{
|
|
|
|
mList->DeleteAllItems();
|
|
|
|
|
|
|
|
for (int i = 0; i < mBatchCommands.GetCount(); i++) {
|
|
|
|
AddItem(mBatchCommands.GetCommand(i),
|
|
|
|
mBatchCommands.GetParams(i));
|
|
|
|
}
|
2012-03-20 15:36:02 +00:00
|
|
|
/*i18n-hint: This is the last item in a list.*/
|
2010-01-23 19:44:49 +00:00
|
|
|
AddItem(_("- END -"), wxT(""));
|
|
|
|
|
|
|
|
// Select the name in the list...this will fire an event.
|
|
|
|
if (mSelectedCommand >= (int)mList->GetItemCount()) {
|
|
|
|
mSelectedCommand = 0;
|
|
|
|
}
|
|
|
|
mList->SetItemState(mSelectedCommand, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add one item into mList
|
|
|
|
void EditChainsDialog::AddItem(const wxString &Action, const wxString &Params)
|
|
|
|
{
|
2018-01-10 02:49:49 +00:00
|
|
|
// Translate internal command name to a friendly form
|
|
|
|
auto item = make_iterator_range(mCommandNames).index_if(
|
2018-03-01 19:23:46 +00:00
|
|
|
[&](const CommandName &name){ return Action == std::get<1>(name); }
|
2018-01-10 02:49:49 +00:00
|
|
|
);
|
|
|
|
auto friendlyName = item >= 0
|
|
|
|
? // wxGetTranslation
|
2018-03-01 19:23:46 +00:00
|
|
|
std::get<0>( mCommandNames[item] )
|
2018-01-10 02:49:49 +00:00
|
|
|
: Action;
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
int i = mList->GetItemCount();
|
|
|
|
|
|
|
|
mList->InsertItem(i, wxT(""));
|
|
|
|
mList->SetItem(i, ItemNumberColumn, wxString::Format(wxT(" %02i"), i + 1));
|
2018-01-10 02:49:49 +00:00
|
|
|
mList->SetItem(i, ActionColumn, friendlyName );
|
2010-01-23 19:44:49 +00:00
|
|
|
mList->SetItem(i, ParamsColumn, Params );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EditChainsDialog::ChangeOK()
|
|
|
|
{
|
|
|
|
if (mChanged) {
|
|
|
|
wxString title;
|
|
|
|
wxString msg;
|
|
|
|
int id;
|
|
|
|
|
2017-10-09 05:03:14 +00:00
|
|
|
title.Printf(_("%s changed"), mActiveChain);
|
2010-01-23 19:44:49 +00:00
|
|
|
msg = _("Do you want to save the changes?");
|
|
|
|
|
2017-09-06 21:39:33 +00:00
|
|
|
id = AudacityMessageBox(msg, title, wxYES_NO | wxCANCEL);
|
2010-01-23 19:44:49 +00:00
|
|
|
if (id == wxCANCEL) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == wxYES) {
|
|
|
|
if (!mBatchCommands.WriteChain(mActiveChain)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mChanged = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/// An item in the chains list has been selected.
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnChainSelected(wxListEvent & event)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
if (!ChangeOK()) {
|
|
|
|
event.Veto();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int item = event.GetIndex();
|
|
|
|
|
|
|
|
mActiveChain = mChains->GetItemText(item);
|
|
|
|
mBatchCommands.ReadChain(mActiveChain);
|
|
|
|
|
|
|
|
if (mBatchCommands.IsFixed(mActiveChain)) {
|
|
|
|
mRemove->Disable();
|
|
|
|
mRename->Disable();
|
|
|
|
mDefaults->Enable();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mRemove->Enable();
|
|
|
|
mRename->Enable();
|
|
|
|
mDefaults->Disable();
|
|
|
|
}
|
|
|
|
|
|
|
|
PopulateList();
|
2013-03-10 09:05:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// An item in the chains list has been selected.
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnListSelected(wxListEvent & WXUNUSED(event))
|
2013-03-10 09:05:41 +00:00
|
|
|
{
|
|
|
|
FitColumns();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The window has been resized.
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnSize(wxSizeEvent & WXUNUSED(event))
|
2013-03-10 09:05:41 +00:00
|
|
|
{
|
|
|
|
// Refrsh the layout and re-fit the columns.
|
|
|
|
Layout();
|
|
|
|
FitColumns();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditChainsDialog::FitColumns()
|
|
|
|
{
|
|
|
|
mList->SetColumnWidth(0, 0); // First column width is zero, to hide it.
|
|
|
|
|
|
|
|
#if defined(__WXMAC__)
|
|
|
|
// wxMac uses a hard coded width of 150 when wxLIST_AUTOSIZE_USEHEADER
|
|
|
|
// is specified, so we calculate the width ourselves. This method may
|
|
|
|
// work equally well on other platforms.
|
|
|
|
for (size_t c = 1; c < mList->GetColumnCount(); c++) {
|
|
|
|
wxListItem info;
|
|
|
|
int width;
|
|
|
|
|
|
|
|
mList->SetColumnWidth(c, wxLIST_AUTOSIZE);
|
|
|
|
info.Clear();
|
|
|
|
info.SetId(c);
|
|
|
|
info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH);
|
|
|
|
mList->GetColumn(c, info);
|
|
|
|
|
|
|
|
mList->GetTextExtent(info.GetText(), &width, NULL);
|
|
|
|
width += 2 * 4; // 2 * kItemPadding - see listctrl_mac.cpp
|
|
|
|
width += 16; // kIconWidth - see listctrl_mac.cpp
|
|
|
|
|
|
|
|
mList->SetColumnWidth(c, wxMax(width, mList->GetColumnWidth(c)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Looks strange, but it forces the horizontal scrollbar to get
|
|
|
|
// drawn. If not done, strange column sizing can occur if the
|
|
|
|
// user attempts to resize the columns.
|
|
|
|
mList->SetClientSize(mList->GetClientSize());
|
|
|
|
#else
|
|
|
|
mList->SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER);
|
|
|
|
mList->SetColumnWidth(2, wxLIST_AUTOSIZE_USEHEADER);
|
|
|
|
mList->SetColumnWidth(3, wxLIST_AUTOSIZE);
|
2014-06-03 20:30:19 +00:00
|
|
|
#endif
|
2013-03-10 09:05:41 +00:00
|
|
|
|
|
|
|
int bestfit = mList->GetColumnWidth(3);
|
|
|
|
int clientsize = mList->GetClientSize().GetWidth();
|
|
|
|
int col1 = mList->GetColumnWidth(1);
|
|
|
|
int col2 = mList->GetColumnWidth(2);
|
|
|
|
bestfit = (bestfit > clientsize-col1-col2)? bestfit : clientsize-col1-col2;
|
|
|
|
mList->SetColumnWidth(3, bestfit);
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
void EditChainsDialog::OnChainsBeginEdit(wxListEvent &event)
|
|
|
|
{
|
|
|
|
int itemNo = event.GetIndex();
|
|
|
|
|
|
|
|
wxString chain = mChains->GetItemText(itemNo);
|
|
|
|
|
|
|
|
if (mBatchCommands.IsFixed(mActiveChain)) {
|
|
|
|
wxBell();
|
|
|
|
event.Veto();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
void EditChainsDialog::OnChainsEndEdit(wxListEvent &event)
|
|
|
|
{
|
|
|
|
if (event.IsEditCancelled()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString newname = event.GetLabel();
|
|
|
|
|
|
|
|
mBatchCommands.RenameChain(mActiveChain, newname);
|
|
|
|
|
|
|
|
mActiveChain = newname;
|
|
|
|
|
|
|
|
PopulateChains();
|
|
|
|
}
|
|
|
|
|
2014-06-03 20:30:19 +00:00
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnAdd(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
while (true) {
|
2017-10-12 15:49:57 +00:00
|
|
|
AudacityTextEntryDialog d(this,
|
2010-01-23 19:44:49 +00:00
|
|
|
_("Enter name of new chain"),
|
2015-05-12 08:29:55 +00:00
|
|
|
_("Name of new chain"));
|
|
|
|
d.SetName(d.GetTitle());
|
2010-01-23 19:44:49 +00:00
|
|
|
wxString name;
|
|
|
|
|
|
|
|
if (d.ShowModal() == wxID_CANCEL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = d.GetValue().Strip(wxString::both);
|
|
|
|
|
|
|
|
if (name.Length() == 0) {
|
2017-09-06 21:39:33 +00:00
|
|
|
AudacityMessageBox(_("Name must not be blank"),
|
2010-01-23 19:44:49 +00:00
|
|
|
GetTitle(),
|
|
|
|
wxOK | wxICON_ERROR,
|
|
|
|
this);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.Contains(wxFILE_SEP_PATH) ||
|
|
|
|
name.Contains(wxFILE_SEP_PATH_UNIX)) {
|
2012-03-20 21:59:30 +00:00
|
|
|
/*i18n-hint: The %c will be replaced with 'forbidden characters', like '/' and '\'.*/
|
2017-09-06 21:39:33 +00:00
|
|
|
AudacityMessageBox(wxString::Format(_("Names may not contain '%c' and '%c'"),
|
2010-01-23 19:44:49 +00:00
|
|
|
wxFILE_SEP_PATH, wxFILE_SEP_PATH_UNIX),
|
|
|
|
GetTitle(),
|
|
|
|
wxOK | wxICON_ERROR,
|
|
|
|
this);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.AddChain(name);
|
|
|
|
|
|
|
|
mActiveChain = name;
|
|
|
|
|
|
|
|
PopulateChains();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnRemove(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mChains->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString name = mChains->GetItemText(item);
|
2017-10-12 16:21:52 +00:00
|
|
|
AudacityMessageDialog m(this,
|
2012-03-20 15:36:02 +00:00
|
|
|
/*i18n-hint: %s will be replaced by the name of a file.*/
|
2017-10-09 05:03:14 +00:00
|
|
|
wxString::Format(_("Are you sure you want to delete %s?"), name),
|
2010-01-23 19:44:49 +00:00
|
|
|
GetTitle(),
|
|
|
|
wxYES_NO | wxICON_QUESTION);
|
2012-05-23 18:52:52 +00:00
|
|
|
if (m.ShowModal() == wxID_NO) {
|
2010-01-23 19:44:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.DeleteChain(name);
|
|
|
|
|
|
|
|
if (item >= (mChains->GetItemCount() - 1) && item >= 0) {
|
|
|
|
item--;
|
|
|
|
}
|
|
|
|
|
|
|
|
mActiveChain = mChains->GetItemText(item);
|
|
|
|
|
|
|
|
PopulateChains();
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnRename(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mChains->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mChains->EditLabel(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An item in the list has been selected.
|
|
|
|
/// Bring up a dialog to allow its parameters to be edited.
|
|
|
|
void EditChainsDialog::OnCommandActivated(wxListEvent &event)
|
|
|
|
{
|
2018-03-01 17:54:08 +00:00
|
|
|
wxCommandEvent dummy;
|
|
|
|
OnEditCommandParams( dummy );
|
|
|
|
|
|
|
|
#if 0
|
2010-01-23 19:44:49 +00:00
|
|
|
int item = event.GetIndex();
|
|
|
|
|
|
|
|
BatchCommandDialog d(this, wxID_ANY);
|
|
|
|
d.SetCommandAndParams(mBatchCommands.GetCommand(item),
|
|
|
|
mBatchCommands.GetParams(item));
|
|
|
|
|
|
|
|
if (!d.ShowModal()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.DeleteFromChain(item);
|
|
|
|
mBatchCommands.AddToChain(d.mSelectedCommand,
|
|
|
|
d.mSelectedParameters,
|
|
|
|
item);
|
|
|
|
|
|
|
|
mChanged = true;
|
|
|
|
|
|
|
|
mSelectedCommand = item;
|
|
|
|
|
|
|
|
PopulateList();
|
2018-03-01 17:54:08 +00:00
|
|
|
#endif
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnInsert(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mList->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
2018-03-01 17:54:08 +00:00
|
|
|
if (item == -1) {
|
|
|
|
item = mList->GetItemCount()-1;
|
|
|
|
}
|
|
|
|
InsertCommandAt( item );
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditChainsDialog::InsertCommandAt(int item)
|
|
|
|
{
|
2010-01-23 19:44:49 +00:00
|
|
|
if (item == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BatchCommandDialog d(this, wxID_ANY);
|
|
|
|
|
|
|
|
if (!d.ShowModal()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-08-18 22:53:13 +00:00
|
|
|
if(d.mSelectedCommand != wxT(""))
|
|
|
|
{
|
|
|
|
mBatchCommands.AddToChain(d.mSelectedCommand,
|
|
|
|
d.mSelectedParameters,
|
|
|
|
item);
|
|
|
|
mChanged = true;
|
|
|
|
mSelectedCommand = item + 1;
|
|
|
|
PopulateList();
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
void EditChainsDialog::OnEditCommandParams(wxCommandEvent & WXUNUSED(event))
|
|
|
|
{
|
|
|
|
int item = mList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
|
|
|
|
|
|
|
|
// LAST command in list is END.
|
|
|
|
// If nothing selected, add at END.
|
|
|
|
// If END selected, add at END.
|
|
|
|
// When adding at end we use InsertCommandAt, so that a new command
|
|
|
|
// can be chosen.
|
|
|
|
int lastItem = mList->GetItemCount()-1;
|
|
|
|
if( (item<0) || (item+1) == mList->GetItemCount() )
|
|
|
|
{
|
|
|
|
InsertCommandAt( lastItem );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just edit the parameters, and not the command.
|
|
|
|
wxString command = mBatchCommands.GetCommand(item);
|
|
|
|
wxString params = mBatchCommands.GetParams(item);
|
|
|
|
|
|
|
|
params = BatchCommands::PromptForParamsFor(command, params, this).Trim();
|
|
|
|
|
|
|
|
mBatchCommands.DeleteFromChain(item);
|
|
|
|
mBatchCommands.AddToChain(command,
|
|
|
|
params,
|
|
|
|
item);
|
|
|
|
mChanged = true;
|
|
|
|
mSelectedCommand = item;
|
|
|
|
PopulateList();
|
|
|
|
}
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnDelete(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mList->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1 || item + 1 == mList->GetItemCount()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.DeleteFromChain(item);
|
|
|
|
mChanged = true;
|
|
|
|
|
|
|
|
if (item >= (mList->GetItemCount() - 2) && item >= 0) {
|
|
|
|
item--;
|
|
|
|
}
|
|
|
|
mSelectedCommand = item;
|
|
|
|
PopulateList();
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnUp(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mList->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1 || item == 0 || item + 1 == mList->GetItemCount()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.AddToChain(mBatchCommands.GetCommand(item),
|
|
|
|
mBatchCommands.GetParams(item),
|
|
|
|
item - 1);
|
|
|
|
mBatchCommands.DeleteFromChain(item + 1);
|
|
|
|
mChanged = true;
|
|
|
|
mSelectedCommand = item - 1;
|
|
|
|
PopulateList();
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnDown(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
long item = mList->GetNextItem(-1,
|
|
|
|
wxLIST_NEXT_ALL,
|
|
|
|
wxLIST_STATE_SELECTED);
|
|
|
|
if (item == -1 || item + 2 >= mList->GetItemCount()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mBatchCommands.AddToChain(mBatchCommands.GetCommand(item),
|
|
|
|
mBatchCommands.GetParams(item),
|
|
|
|
item + 2);
|
|
|
|
mBatchCommands.DeleteFromChain(item);
|
|
|
|
mChanged = true;
|
|
|
|
mSelectedCommand = item + 1;
|
|
|
|
PopulateList();
|
|
|
|
}
|
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
void EditChainsDialog::OnApplyToProject(wxCommandEvent & event)
|
|
|
|
{
|
|
|
|
if( !SaveChanges() )
|
|
|
|
return;
|
|
|
|
BatchProcessDialog::OnApplyToProject( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
void EditChainsDialog::OnApplyToFiles(wxCommandEvent & event)
|
|
|
|
{
|
|
|
|
if( !SaveChanges() )
|
|
|
|
return;
|
|
|
|
BatchProcessDialog::OnApplyToFiles( event );
|
|
|
|
}
|
|
|
|
|
2010-01-23 19:44:49 +00:00
|
|
|
/// Select the empty Command chain.
|
2013-08-25 21:51:26 +00:00
|
|
|
void EditChainsDialog::OnDefaults(wxCommandEvent & WXUNUSED(event))
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
mBatchCommands.RestoreChain(mActiveChain);
|
|
|
|
|
|
|
|
mChanged = true;
|
|
|
|
|
|
|
|
PopulateList();
|
|
|
|
}
|
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
bool EditChainsDialog::SaveChanges(){
|
2010-01-23 19:44:49 +00:00
|
|
|
gPrefs->Write(wxT("/Batch/ActiveChain"), mActiveChain);
|
2012-08-02 06:03:19 +00:00
|
|
|
gPrefs->Flush();
|
2010-01-23 19:44:49 +00:00
|
|
|
|
|
|
|
if (mChanged) {
|
|
|
|
if (!mBatchCommands.WriteChain(mActiveChain)) {
|
2018-03-01 17:54:08 +00:00
|
|
|
return false;
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-01 17:54:08 +00:00
|
|
|
mChanged = false;
|
|
|
|
return true;
|
|
|
|
}
|
2010-01-23 19:44:49 +00:00
|
|
|
|
2018-03-01 17:54:08 +00:00
|
|
|
/// Send changed values back to Prefs, and update Audacity.
|
|
|
|
void EditChainsDialog::OnOK(wxCommandEvent & WXUNUSED(event))
|
|
|
|
{
|
|
|
|
if( !SaveChanges() )
|
|
|
|
return;
|
2010-01-23 19:44:49 +00:00
|
|
|
EndModal(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2018-03-01 17:54:08 +00:00
|
|
|
void EditChainsDialog::OnCancel(wxCommandEvent & event)
|
2010-01-23 19:44:49 +00:00
|
|
|
{
|
|
|
|
if (!ChangeOK()) {
|
|
|
|
return;
|
|
|
|
}
|
2018-03-01 17:54:08 +00:00
|
|
|
BatchProcessDialog::OnCancel( event );
|
|
|
|
//EndModal(false);
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
void EditChainsDialog::OnKeyDown(wxKeyEvent &event)
|
|
|
|
{
|
|
|
|
if (event.GetKeyCode() == WXK_DELETE) {
|
2013-03-10 09:05:41 +00:00
|
|
|
wxLogDebug(wxT("wxKeyEvent"));
|
2010-01-23 19:44:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
event.Skip();
|
|
|
|
}
|