2006-12-28 23:31:33 +01:00
|
|
|
// Copyright (c) 2006, Niels Martin Hansen
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
|
|
// may be used to endorse or promote products derived from this software
|
|
|
|
// without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "auto4_base.h"
|
2010-05-21 03:13:36 +02:00
|
|
|
#include "compat.h"
|
2011-09-28 21:46:14 +02:00
|
|
|
#include "command/command.h"
|
2014-05-22 21:07:15 +02:00
|
|
|
#include "dialog_manager.h"
|
2014-05-29 17:28:37 +02:00
|
|
|
#include "format.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "help_button.h"
|
2011-09-28 21:46:14 +02:00
|
|
|
#include "include/aegisub/context.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "libresrc/libresrc.h"
|
2013-01-07 02:50:09 +01:00
|
|
|
#include "options.h"
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2014-05-22 21:07:15 +02:00
|
|
|
#include <libaegisub/signal.h>
|
|
|
|
|
2013-01-07 02:50:09 +01:00
|
|
|
#include <algorithm>
|
2014-05-23 00:40:16 +02:00
|
|
|
#include <boost/range/algorithm/transform.hpp>
|
2014-05-22 21:07:15 +02:00
|
|
|
#include <vector>
|
2013-01-07 02:50:09 +01:00
|
|
|
|
|
|
|
#include <wx/button.h>
|
2014-05-22 21:07:15 +02:00
|
|
|
#include <wx/dialog.h>
|
2013-01-07 02:50:09 +01:00
|
|
|
#include <wx/filedlg.h>
|
|
|
|
#include <wx/listctrl.h>
|
|
|
|
#include <wx/log.h>
|
|
|
|
#include <wx/msgdlg.h>
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <wx/sizer.h>
|
2013-01-07 02:50:09 +01:00
|
|
|
|
2014-05-22 21:07:15 +02:00
|
|
|
namespace {
|
|
|
|
/// Struct to attach a flag for global/local to scripts
|
|
|
|
struct ExtraScriptInfo {
|
|
|
|
Automation4::Script *script;
|
|
|
|
bool is_global;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DialogAutomation final : public wxDialog {
|
|
|
|
agi::Context *context;
|
|
|
|
|
|
|
|
/// Currently loaded scripts
|
|
|
|
std::vector<ExtraScriptInfo> script_info;
|
|
|
|
|
|
|
|
/// File-local script manager
|
|
|
|
Automation4::ScriptManager *local_manager;
|
|
|
|
|
|
|
|
/// Listener for external changes to the local scripts
|
|
|
|
agi::signal::Connection local_scripts_changed;
|
|
|
|
|
|
|
|
/// Global script manager
|
|
|
|
Automation4::ScriptManager *global_manager;
|
|
|
|
|
|
|
|
/// Listener for external changes to the global scripts
|
|
|
|
agi::signal::Connection global_scripts_changed;
|
|
|
|
|
|
|
|
|
|
|
|
/// List of loaded scripts
|
|
|
|
wxListView *list;
|
|
|
|
|
|
|
|
/// Unload a local script
|
|
|
|
wxButton *remove_button;
|
|
|
|
|
|
|
|
/// Reload a script
|
|
|
|
wxButton *reload_button;
|
|
|
|
|
|
|
|
void RebuildList();
|
|
|
|
void AddScript(Automation4::Script *script, bool is_global);
|
|
|
|
void SetScriptInfo(int i, Automation4::Script *script);
|
|
|
|
void UpdateDisplay();
|
|
|
|
|
|
|
|
void OnAdd(wxCommandEvent &);
|
|
|
|
void OnRemove(wxCommandEvent &);
|
|
|
|
void OnReload(wxCommandEvent &);
|
|
|
|
|
|
|
|
void OnInfo(wxCommandEvent &);
|
|
|
|
void OnReloadAutoload(wxCommandEvent &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
DialogAutomation(agi::Context *context);
|
|
|
|
};
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
DialogAutomation::DialogAutomation(agi::Context *c)
|
2011-09-28 23:38:18 +02:00
|
|
|
: wxDialog(c->parent, -1, _("Automation Manager"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
2011-09-28 21:46:14 +02:00
|
|
|
, context(c)
|
2014-03-25 22:49:26 +01:00
|
|
|
, local_manager(c->local_scripts.get())
|
2012-03-09 01:23:30 +01:00
|
|
|
, local_scripts_changed(local_manager->AddScriptChangeListener(&DialogAutomation::RebuildList, this))
|
2014-06-06 17:24:33 +02:00
|
|
|
, global_manager(config::global_scripts)
|
2012-03-09 01:23:30 +01:00
|
|
|
, global_scripts_changed(global_manager->AddScriptChangeListener(&DialogAutomation::RebuildList, this))
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
2012-04-03 22:40:24 +02:00
|
|
|
SetIcon(GETICON(automation_toolbutton_16));
|
2007-07-05 01:09:40 +02:00
|
|
|
|
2006-12-28 23:31:33 +01:00
|
|
|
// create main controls
|
2011-09-28 21:46:14 +02:00
|
|
|
list = new wxListView(this, -1, wxDefaultPosition, wxSize(600, 175), wxLC_REPORT|wxLC_SINGLE_SEL);
|
2012-02-01 19:47:47 +01:00
|
|
|
wxButton *add_button = new wxButton(this, -1, _("&Add"));
|
2011-09-28 21:46:14 +02:00
|
|
|
remove_button = new wxButton(this, -1, _("&Remove"));
|
|
|
|
reload_button = new wxButton(this, -1, _("Re&load"));
|
2012-02-01 19:47:47 +01:00
|
|
|
wxButton *info_button = new wxButton(this, -1, _("Show &Info"));
|
|
|
|
wxButton *reload_autoload_button = new wxButton(this, -1, _("Re&scan Autoload Dir"));
|
|
|
|
wxButton *close_button = new wxButton(this, wxID_CANCEL, _("&Close"));
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2013-12-12 03:25:13 +01:00
|
|
|
list->Bind(wxEVT_LIST_ITEM_SELECTED, std::bind(&DialogAutomation::UpdateDisplay, this));
|
|
|
|
list->Bind(wxEVT_LIST_ITEM_DESELECTED, std::bind(&DialogAutomation::UpdateDisplay, this));
|
|
|
|
add_button->Bind(wxEVT_BUTTON, &DialogAutomation::OnAdd, this);
|
|
|
|
remove_button->Bind(wxEVT_BUTTON, &DialogAutomation::OnRemove, this);
|
|
|
|
reload_button->Bind(wxEVT_BUTTON, &DialogAutomation::OnReload, this);
|
|
|
|
info_button->Bind(wxEVT_BUTTON, &DialogAutomation::OnInfo, this);
|
|
|
|
reload_autoload_button->Bind(wxEVT_BUTTON, &DialogAutomation::OnReloadAutoload, this);
|
2011-09-28 21:46:14 +02:00
|
|
|
|
2006-12-28 23:31:33 +01:00
|
|
|
// add headers to list view
|
2011-09-28 21:43:11 +02:00
|
|
|
list->InsertColumn(0, "", wxLIST_FORMAT_CENTER, 20);
|
2006-12-28 23:31:33 +01:00
|
|
|
list->InsertColumn(1, _("Name"), wxLIST_FORMAT_LEFT, 140);
|
|
|
|
list->InsertColumn(2, _("Filename"), wxLIST_FORMAT_LEFT, 90);
|
|
|
|
list->InsertColumn(3, _("Description"), wxLIST_FORMAT_LEFT, 330);
|
|
|
|
|
|
|
|
// button layout
|
|
|
|
wxSizer *button_box = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
button_box->AddStretchSpacer(2);
|
|
|
|
button_box->Add(add_button, 0);
|
|
|
|
button_box->Add(remove_button, 0);
|
|
|
|
button_box->AddSpacer(10);
|
|
|
|
button_box->Add(reload_button, 0);
|
|
|
|
button_box->Add(info_button, 0);
|
|
|
|
button_box->AddSpacer(10);
|
|
|
|
button_box->Add(reload_autoload_button, 0);
|
|
|
|
button_box->AddSpacer(10);
|
2011-09-28 21:43:11 +02:00
|
|
|
button_box->Add(new HelpButton(this,"Automation Manager"), 0);
|
2006-12-28 23:31:33 +01:00
|
|
|
button_box->Add(close_button, 0);
|
|
|
|
button_box->AddStretchSpacer(2);
|
|
|
|
|
|
|
|
// main layout
|
|
|
|
wxSizer *main_box = new wxBoxSizer(wxVERTICAL);
|
2011-09-28 21:46:14 +02:00
|
|
|
main_box->Add(list, wxSizerFlags(1).Expand().Border());
|
|
|
|
main_box->Add(button_box, wxSizerFlags().Expand().Border(wxALL & ~wxTOP));
|
|
|
|
SetSizerAndFit(main_box);
|
2006-12-28 23:31:33 +01:00
|
|
|
Center();
|
|
|
|
|
2007-07-05 17:23:31 +02:00
|
|
|
// why doesn't this work... the button gets the "default" decoration but doesn't answer to Enter
|
|
|
|
// ("esc" does work)
|
|
|
|
SetDefaultItem(close_button);
|
|
|
|
SetAffirmativeId(wxID_CANCEL);
|
|
|
|
close_button->SetDefault();
|
|
|
|
|
2006-12-28 23:31:33 +01:00
|
|
|
RebuildList();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DialogAutomation::RebuildList()
|
|
|
|
{
|
|
|
|
script_info.clear();
|
|
|
|
list->DeleteAllItems();
|
|
|
|
|
2013-06-08 06:19:40 +02:00
|
|
|
for (auto& script : local_manager->GetScripts()) AddScript(script.get(), false);
|
|
|
|
for (auto& script : global_manager->GetScripts()) AddScript(script.get(), true);
|
2012-03-09 01:23:30 +01:00
|
|
|
|
|
|
|
UpdateDisplay();
|
2006-12-28 23:31:33 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::SetScriptInfo(int i, Automation4::Script *script)
|
|
|
|
{
|
2013-01-04 16:01:50 +01:00
|
|
|
list->SetItem(i, 1, to_wx(script->GetName()));
|
|
|
|
list->SetItem(i, 2, script->GetPrettyFilename().wstring());
|
|
|
|
list->SetItem(i, 3, to_wx(script->GetDescription()));
|
2011-09-28 21:46:14 +02:00
|
|
|
if (!script->GetLoadedState())
|
|
|
|
list->SetItemBackgroundColour(i, wxColour(255,128,128));
|
2012-02-01 19:47:47 +01:00
|
|
|
else
|
|
|
|
list->SetItemBackgroundColour(i, list->GetBackgroundColour());
|
2011-09-28 21:46:14 +02:00
|
|
|
}
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::AddScript(Automation4::Script *script, bool is_global)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
2011-09-28 21:46:14 +02:00
|
|
|
ExtraScriptInfo ei = { script, is_global };
|
2006-12-28 23:31:33 +01:00
|
|
|
script_info.push_back(ei);
|
|
|
|
|
|
|
|
wxListItem itm;
|
2011-09-28 21:46:14 +02:00
|
|
|
itm.SetText(is_global ? "G" : "L");
|
2006-12-28 23:31:33 +01:00
|
|
|
itm.SetData((int)script_info.size()-1);
|
|
|
|
itm.SetId(list->GetItemCount());
|
2011-09-28 21:46:14 +02:00
|
|
|
SetScriptInfo(list->InsertItem(itm), script);
|
2006-12-28 23:31:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DialogAutomation::UpdateDisplay()
|
|
|
|
{
|
|
|
|
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
|
|
|
bool selected = i >= 0;
|
2011-09-28 21:46:14 +02:00
|
|
|
bool local = selected && !script_info[list->GetItemData(i)].is_global;
|
|
|
|
remove_button->Enable(local);
|
2006-12-28 23:31:33 +01:00
|
|
|
reload_button->Enable(selected);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
template<class Container>
|
2013-01-04 16:01:50 +01:00
|
|
|
static bool has_file(Container const& c, agi::fs::path const& fn)
|
2011-09-28 21:46:14 +02:00
|
|
|
{
|
2012-11-13 04:36:25 +01:00
|
|
|
return any_of(c.begin(), c.end(),
|
2013-06-08 06:19:40 +02:00
|
|
|
[&](std::unique_ptr<Automation4::Script> const& s) { return fn == s->GetFilename(); });
|
2011-09-28 21:46:14 +02:00
|
|
|
}
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::OnAdd(wxCommandEvent &)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
2011-10-24 22:17:48 +02:00
|
|
|
wxFileDialog diag(this,
|
2011-09-28 21:46:14 +02:00
|
|
|
_("Add Automation script"),
|
2012-12-23 00:18:38 +01:00
|
|
|
to_wx(OPT_GET("Path/Last/Automation")->GetString()),
|
2011-10-24 22:17:48 +02:00
|
|
|
"",
|
2013-01-04 16:01:50 +01:00
|
|
|
to_wx(Automation4::ScriptFactory::GetWildcardStr()),
|
2011-10-24 22:17:48 +02:00
|
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
|
2011-09-28 21:46:14 +02:00
|
|
|
|
2011-10-24 22:17:48 +02:00
|
|
|
if (diag.ShowModal() == wxID_CANCEL) return;
|
2011-09-28 21:46:14 +02:00
|
|
|
|
2011-10-24 22:17:48 +02:00
|
|
|
wxArrayString fnames;
|
|
|
|
diag.GetPaths(fnames);
|
2011-09-28 21:46:14 +02:00
|
|
|
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& fname : fnames) {
|
2015-01-01 04:41:56 +01:00
|
|
|
agi::fs::path fnpath(fname.wx_str());
|
2013-01-04 16:01:50 +01:00
|
|
|
OPT_SET("Path/Last/Automation")->SetString(fnpath.parent_path().string());
|
2011-10-24 22:17:48 +02:00
|
|
|
|
|
|
|
if (has_file(local_manager->GetScripts(), fnpath) || has_file(global_manager->GetScripts(), fnpath)) {
|
2012-11-04 04:53:03 +01:00
|
|
|
wxLogError("Script '%s' is already loaded", fname);
|
2011-10-24 22:17:48 +02:00
|
|
|
continue;
|
|
|
|
}
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
local_manager->Add(Automation4::ScriptFactory::CreateFromFile(fnpath, true));
|
2011-10-24 22:17:48 +02:00
|
|
|
}
|
2006-12-28 23:31:33 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::OnRemove(wxCommandEvent &)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
|
|
|
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
|
|
|
if (i < 0) return;
|
|
|
|
const ExtraScriptInfo &ei = script_info[list->GetItemData(i)];
|
|
|
|
if (ei.is_global) return;
|
2012-03-09 01:23:30 +01:00
|
|
|
|
2006-12-28 23:31:33 +01:00
|
|
|
local_manager->Remove(ei.script);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::OnReload(wxCommandEvent &)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
|
|
|
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
|
|
|
if (i < 0) return;
|
|
|
|
|
2011-10-25 21:02:01 +02:00
|
|
|
ExtraScriptInfo const& ei = script_info[list->GetItemData(i)];
|
|
|
|
if (ei.is_global)
|
|
|
|
global_manager->Reload(ei.script);
|
|
|
|
else
|
|
|
|
local_manager->Reload(ei.script);
|
2011-10-24 22:18:07 +02:00
|
|
|
}
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::OnInfo(wxCommandEvent &)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
|
|
|
int i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
2013-11-21 18:13:36 +01:00
|
|
|
ExtraScriptInfo *ei = i >= 0 ? &script_info[list->GetItemData(i)] : nullptr;
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2011-10-24 22:18:07 +02:00
|
|
|
wxArrayString info;
|
|
|
|
std::back_insert_iterator<wxArrayString> append_info(info);
|
|
|
|
|
2014-05-29 17:28:37 +02:00
|
|
|
info.push_back(fmt_tl(
|
|
|
|
"Total scripts loaded: %d\nGlobal scripts loaded: %d\nLocal scripts loaded: %d\n",
|
|
|
|
local_manager->GetScripts().size() + global_manager->GetScripts().size(),
|
|
|
|
global_manager->GetScripts().size(),
|
|
|
|
local_manager->GetScripts().size()));
|
2006-12-28 23:31:33 +01:00
|
|
|
|
2011-10-24 22:18:07 +02:00
|
|
|
info.push_back(_("Scripting engines installed:"));
|
2014-03-26 18:36:34 +01:00
|
|
|
boost::transform(Automation4::ScriptFactory::GetFactories(), append_info,
|
|
|
|
[](std::unique_ptr<Automation4::ScriptFactory> const& f) {
|
2014-05-29 17:28:37 +02:00
|
|
|
return fmt_wx("- %s (%s)", f->GetEngineName(), f->GetFilenamePattern());
|
2014-03-26 18:36:34 +01:00
|
|
|
});
|
2006-12-28 23:31:33 +01:00
|
|
|
|
|
|
|
if (ei) {
|
2014-05-29 17:28:37 +02:00
|
|
|
info.push_back(fmt_tl("\nScript info:\nName: %s\nDescription: %s\nAuthor: %s\nVersion: %s\nFull path: %s\nState: %s\n\nFeatures provided by script:",
|
2011-09-28 21:43:48 +02:00
|
|
|
ei->script->GetName(),
|
|
|
|
ei->script->GetDescription(),
|
|
|
|
ei->script->GetAuthor(),
|
|
|
|
ei->script->GetVersion(),
|
2013-01-04 16:01:50 +01:00
|
|
|
ei->script->GetFilename().wstring(),
|
2011-10-24 22:18:07 +02:00
|
|
|
ei->script->GetLoadedState() ? _("Correctly loaded") : _("Failed to load")));
|
2011-09-28 21:48:47 +02:00
|
|
|
|
2014-03-26 18:36:34 +01:00
|
|
|
boost::transform(ei->script->GetMacros(), append_info, [=](const cmd::Command *f) {
|
2014-05-29 17:28:37 +02:00
|
|
|
return fmt_tl(" Macro: %s (%s)", f->StrDisplay(context), f->name());
|
2014-03-26 18:36:34 +01:00
|
|
|
});
|
|
|
|
boost::transform(ei->script->GetFilters(), append_info, [](const Automation4::ExportFilter* f) {
|
2014-05-29 17:28:37 +02:00
|
|
|
return fmt_tl(" Export filter: %s", f->GetName());
|
2014-03-26 18:36:34 +01:00
|
|
|
});
|
2006-12-28 23:31:33 +01:00
|
|
|
}
|
|
|
|
|
2011-10-24 22:18:07 +02:00
|
|
|
wxMessageBox(wxJoin(info, '\n', 0), _("Automation Script Info"));
|
2006-12-28 23:31:33 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:14 +02:00
|
|
|
void DialogAutomation::OnReloadAutoload(wxCommandEvent &)
|
2006-12-28 23:31:33 +01:00
|
|
|
{
|
|
|
|
global_manager->Reload();
|
|
|
|
}
|
2014-05-22 21:07:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShowAutomationDialog(agi::Context *c) {
|
|
|
|
c->dialog->Show<DialogAutomation>(c);
|
|
|
|
}
|