Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/ui/ieventmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ class IEventManager :
/* greebo: Retrieves the string representation of the given event
*/
virtual std::string getEventStr(wxKeyEvent& ev) = 0;

virtual void connectDeferredAccelerators() = 0;
};

// Global accessor for the event manager
Expand Down
2 changes: 1 addition & 1 deletion plugins/script/PythonModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ ScriptCommand::Ptr PythonModule::createScriptCommand(const std::string& scriptBa
}

// Successfully retrieved the command
return std::make_shared<ScriptCommand>(cmdName, cmdDisplayName, relativeScriptPath);
return std::make_shared<ScriptCommand>(cmdName, cmdDisplayName, relativeScriptPath, scriptBasePath);
}

rError() << "Script file " << relativeScriptPath << " does not export a __commandName__ value" << std::endl;
Expand Down
6 changes: 4 additions & 2 deletions plugins/script/ScriptCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ namespace script

ScriptCommand::ScriptCommand(const std::string& name,
const std::string& displayName,
const std::string& scriptFilename) :
const std::string& scriptFilename,
const std::string& basePath) :
_name(name),
_displayName(displayName),
_scriptFilename(scriptFilename)
_scriptFilename(scriptFilename),
_basePath(basePath)
{
// Register this with the command system
GlobalCommandSystem().addStatement(_name, "RunScriptCommand '" + _name + "'", false);
Expand Down
10 changes: 9 additions & 1 deletion plugins/script/ScriptCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ class ScriptCommand :
// The script file name to execute (relative to scripts/ folder)
std::string _scriptFilename;

std::string _basePath;

public:
using Ptr = std::shared_ptr<ScriptCommand>;

ScriptCommand(const std::string& name,
const std::string& displayName,
const std::string& scriptFilename);
const std::string& scriptFilename,
const std::string& basePath);

~ScriptCommand() override;

Expand All @@ -46,6 +49,11 @@ class ScriptCommand :
{
return _displayName;
}

const std::string& getBasePath() const
{
return _basePath;
}
};

} // namespace script
56 changes: 36 additions & 20 deletions plugins/script/ScriptingSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@

#include "PythonModule.h"
#include "SceneNodeBuffer.h"
#include "ui/ieventmanager.h"

#include "os/path.h"
#include <functional>
#include "string/case_conv.h"
#include "settings/SettingsManager.h"

namespace script
{
Expand Down Expand Up @@ -95,6 +97,8 @@ void ScriptingSystem::initialise()

// Search script folder for commands
reloadScripts();

GlobalEventManager().connectDeferredAccelerators();
}

void ScriptingSystem::runScriptFile(const cmd::ArgumentList& args)
Expand Down Expand Up @@ -138,12 +142,12 @@ void ScriptingSystem::executeCommand(const std::string& name)
UndoableCommand cmd("runScriptCommand " + name);

// Execute the script file behind this command
executeScriptFile(found->second->getFilename(), true);
_pythonModule->executeScriptFile(found->second->getBasePath(), found->second->getFilename(), true);
}

void ScriptingSystem::loadCommandScript(const std::string& scriptFilename)
void ScriptingSystem::loadCommandScript(const std::string& basePath, const std::string& scriptFilename)
{
auto command = _pythonModule->createScriptCommand(_scriptPath, scriptFilename);
auto command = _pythonModule->createScriptCommand(basePath, scriptFilename);

if (!command)
{
Expand Down Expand Up @@ -173,29 +177,37 @@ void ScriptingSystem::reloadScripts()
_commands.clear();

// Initialise the search's starting point
fs::path start = fs::path(_scriptPath) / COMMAND_PATH;

if (!fs::exists(start))
auto scanDirectory = [&](const std::string& basePath)
{
rWarning() << "Couldn't find scripts folder: " << start.string() << std::endl;
return;
}
fs::path start = fs::path(basePath) / COMMAND_PATH;

for (fs::recursive_directory_iterator it(start);
it != fs::recursive_directory_iterator(); ++it)
{
// Get the candidate
const fs::path& candidate = *it;
if (!fs::exists(start))
{
return;
}

if (fs::is_directory(candidate)) continue;
for (fs::recursive_directory_iterator it(start);
it != fs::recursive_directory_iterator(); ++it)
{
const fs::path& candidate = *it;

std::string extension = os::getExtension(candidate.string());
string::to_lower(extension);
if (fs::is_directory(candidate)) continue;

if (extension != PYTHON_FILE_EXTENSION) continue;
std::string extension = os::getExtension(candidate.string());
string::to_lower(extension);

// Script file found, construct a new command
loadCommandScript(os::getRelativePath(candidate.generic_string(), _scriptPath));
if (extension != PYTHON_FILE_EXTENSION) continue;

// Script file found, construct a new command
loadCommandScript(basePath, os::getRelativePath(candidate.generic_string(), basePath));
}
};

scanDirectory(_scriptPath);

if (!_userScriptPath.empty())
{
scanDirectory(_userScriptPath);
}

rMessage() << "ScriptModule: Found " << _commands.size() << " commands." << std::endl;
Expand All @@ -208,6 +220,9 @@ void ScriptingSystem::initialiseModule(const IApplicationContext& ctx)
// Construct the script path
_scriptPath = ctx.getRuntimeDataPath() + SCRIPT_PATH;

settings::SettingsManager manager(ctx);
_userScriptPath = manager.getCurrentVersionSettingsFolder() + SCRIPT_PATH;

// Set up the python interpreter
_pythonModule.reset(new PythonModule);

Expand Down Expand Up @@ -274,6 +289,7 @@ void ScriptingSystem::shutdownModule()

_commands.clear();
_scriptPath.clear();
_userScriptPath.clear();
_pythonModule.reset();
}

Expand Down
3 changes: 2 additions & 1 deletion plugins/script/ScriptingSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ScriptingSystem: public IScriptingSystem

// The path where the script files are hosted
std::string _scriptPath;
std::string _userScriptPath;

// All named script commands (pointing to .py files)
std::map<std::string, ScriptCommand::Ptr> _commands;
Expand Down Expand Up @@ -74,7 +75,7 @@ class ScriptingSystem: public IScriptingSystem
private:
void executeScriptFile(const std::string& filename, bool setExecuteCommandAttr);
void reloadScripts();
void loadCommandScript(const std::string& scriptFilename);
void loadCommandScript(const std::string& basePath, const std::string& scriptFilename);
};
typedef std::shared_ptr<ScriptingSystem> ScriptingSystemPtr;

Expand Down
50 changes: 49 additions & 1 deletion radiant/eventmanager/EventManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void EventManager::shutdownModule()
saveEventListToRegistry();

_accelerators.clear();
_deferredAccelerators.clear();
_events.clear();
}

Expand All @@ -107,6 +108,7 @@ void EventManager::resetAcceleratorBindings()
}

_accelerators.clear();
_deferredAccelerators.clear();

for (const auto& pair : _menuItems)
{
Expand Down Expand Up @@ -406,7 +408,9 @@ Accelerator& EventManager::connectAccelerator(int keyCode, unsigned int modifier
}
else
{
return _emptyAccelerator;
rMessage() << "EventManager: Deferring shortcut for not-yet-registered command: " << command << std::endl;
_deferredAccelerators.emplace(command, accelerator);
return *accelerator;
}

auto result = _accelerators.emplace(command, accelerator);
Expand Down Expand Up @@ -635,6 +639,50 @@ void EventManager::saveEventListToRegistry()

shortcutSaver.visit(pair.first, *pair.second);
}

for (const auto& pair : _deferredAccelerators)
{
if (pair.second->isEmpty()) continue;

shortcutSaver.visit(pair.first, *pair.second);
}
}

void EventManager::connectDeferredAccelerators()
{
auto it = _deferredAccelerators.begin();

while (it != _deferredAccelerators.end())
{
const auto& command = it->first;
auto& accelerator = it->second;

auto event = findEvent(command);

if (!event->empty())
{
accelerator->setEvent(event);
}
else if (GlobalCommandSystem().commandExists(command))
{
accelerator->setStatement(command);
}
else
{
++it;
continue;
}

rMessage() << "EventManager: Resolved deferred shortcut for " << command << std::endl;

_accelerators.emplace(command, accelerator);

std::string acceleratorStr = accelerator->getString(true);
setMenuItemAccelerator(command, acceleratorStr);
setToolItemAccelerator(command, acceleratorStr);

it = _deferredAccelerators.erase(it);
}
}

Accelerator& EventManager::findAccelerator(const std::string& key, const std::string& modifierStr)
Expand Down
3 changes: 3 additions & 0 deletions radiant/eventmanager/EventManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class EventManager :
// The command-to-accelerator map containing all registered shortcuts
typedef std::map<std::string, Accelerator::Ptr> AcceleratorMap;
AcceleratorMap _accelerators;
AcceleratorMap _deferredAccelerators;

// The map of all registered events
EventMap _events;
Expand Down Expand Up @@ -92,6 +93,8 @@ class EventManager :

void foreachEvent(IEventVisitor& eventVisitor) override;

void connectDeferredAccelerators() override;

// Tries to locate an accelerator, that is connected to the given command
Accelerator& findAccelerator(wxKeyEvent& ev);
bool handleKeyEvent(wxKeyEvent& keyEvent);
Expand Down