Add an interactive Python console to the script manager
This commit is contained in:
parent
7c05b42dcd
commit
930a2aa2bf
|
@ -507,6 +507,7 @@ set(UI
|
||||||
|
|
||||||
scripting/installscriptdialog.ui
|
scripting/installscriptdialog.ui
|
||||||
scripting/scriptdialog.ui
|
scripting/scriptdialog.ui
|
||||||
|
scripting/python/pythonconsole.ui
|
||||||
|
|
||||||
smartplaylists/querysearchpage.ui
|
smartplaylists/querysearchpage.ui
|
||||||
smartplaylists/querysortpage.ui
|
smartplaylists/querysortpage.ui
|
||||||
|
@ -818,11 +819,13 @@ endif(APPLE)
|
||||||
|
|
||||||
if(HAVE_SCRIPTING_PYTHON)
|
if(HAVE_SCRIPTING_PYTHON)
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
|
scripting/python/pythonconsole.cpp
|
||||||
scripting/python/pythonengine.cpp
|
scripting/python/pythonengine.cpp
|
||||||
scripting/python/pythonscript.cpp
|
scripting/python/pythonscript.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND HEADERS
|
list(APPEND HEADERS
|
||||||
|
scripting/python/pythonconsole.h
|
||||||
scripting/python/pythonengine.h
|
scripting/python/pythonengine.h
|
||||||
)
|
)
|
||||||
endif(HAVE_SCRIPTING_PYTHON)
|
endif(HAVE_SCRIPTING_PYTHON)
|
||||||
|
@ -898,6 +901,13 @@ list(APPEND OTHER_SOURCES
|
||||||
remote/remoteconfig.cpp
|
remote/remoteconfig.cpp
|
||||||
remote/remoteconfig.h
|
remote/remoteconfig.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/ui_remoteconfig.h
|
${CMAKE_CURRENT_BINARY_DIR}/ui_remoteconfig.h
|
||||||
|
scripting/python/pythonconsole.cpp
|
||||||
|
scripting/python/pythonconsole.h
|
||||||
|
scripting/python/pythonengine.cpp
|
||||||
|
scripting/python/pythonengine.h
|
||||||
|
scripting/python/pythonscript.cpp
|
||||||
|
scripting/python/pythonscript.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/ui_pythonconsole.h
|
||||||
ui/macsystemtrayicon.h
|
ui/macsystemtrayicon.h
|
||||||
ui/macsystemtrayicon.mm
|
ui/macsystemtrayicon.mm
|
||||||
ui/wiimotedevshortcutsconfig.cpp
|
ui/wiimotedevshortcutsconfig.cpp
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Needs to be included first
|
||||||
|
#include "pythonengine.h"
|
||||||
|
|
||||||
|
#include "pythonconsole.h"
|
||||||
|
#include "ui_pythonconsole.h"
|
||||||
|
|
||||||
|
#include <gui/PythonQtScriptingConsole.h>
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
|
PythonConsole::PythonConsole(QWidget *parent)
|
||||||
|
: QWidget(parent),
|
||||||
|
ui_(new Ui_PythonConsole),
|
||||||
|
proxy_model_(new QSortFilterProxyModel(this)),
|
||||||
|
engine_(NULL),
|
||||||
|
widget_(NULL)
|
||||||
|
{
|
||||||
|
ui_->setupUi(this);
|
||||||
|
connect(ui_->modules, SIGNAL(currentIndexChanged(int)), SLOT(ModuleChanged(int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
PythonConsole::~PythonConsole() {
|
||||||
|
delete ui_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonConsole::showEvent(QShowEvent* e) {
|
||||||
|
engine_->EnsureInitialised();
|
||||||
|
|
||||||
|
QWidget::showEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonConsole::SetEngine(PythonEngine* engine) {
|
||||||
|
engine_ = engine;
|
||||||
|
|
||||||
|
proxy_model_->setSourceModel(engine->modules_model());
|
||||||
|
proxy_model_->setDynamicSortFilter(true);
|
||||||
|
|
||||||
|
ui_->modules->setModel(proxy_model_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonConsole::ModuleChanged(int row) {
|
||||||
|
const QModelIndex index = proxy_model_->index(row, 0);
|
||||||
|
|
||||||
|
PythonQtObjectPtr ptr;
|
||||||
|
ptr.fromVariant(index.data(Qt::UserRole + 1));
|
||||||
|
|
||||||
|
delete widget_;
|
||||||
|
widget_ = new PythonQtScriptingConsole(this, ptr);
|
||||||
|
|
||||||
|
layout()->addWidget(widget_);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PYTHONCONSOLE_H
|
||||||
|
#define PYTHONCONSOLE_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
|
||||||
|
class PythonQtScriptingConsole;
|
||||||
|
|
||||||
|
class PythonEngine;
|
||||||
|
class Ui_PythonConsole;
|
||||||
|
|
||||||
|
class PythonConsole : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PythonConsole(QWidget* parent = 0);
|
||||||
|
~PythonConsole();
|
||||||
|
|
||||||
|
void SetEngine(PythonEngine* engine);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* e);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ModuleChanged(int row);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui_PythonConsole* ui_;
|
||||||
|
QSortFilterProxyModel* proxy_model_;
|
||||||
|
|
||||||
|
PythonEngine* engine_;
|
||||||
|
|
||||||
|
PythonQtScriptingConsole* widget_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PYTHONCONSOLE_H
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PythonConsole</class>
|
||||||
|
<widget class="QWidget" name="PythonConsole">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>788</width>
|
||||||
|
<height>439</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Context:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="modules">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -44,7 +44,8 @@ PythonEngine* PythonEngine::sInstance = NULL;
|
||||||
|
|
||||||
PythonEngine::PythonEngine(ScriptManager* manager)
|
PythonEngine::PythonEngine(ScriptManager* manager)
|
||||||
: LanguageEngine(manager),
|
: LanguageEngine(manager),
|
||||||
initialised_(false)
|
initialised_(false),
|
||||||
|
modules_model_(new QStandardItemModel(this))
|
||||||
{
|
{
|
||||||
Q_ASSERT(sInstance == NULL);
|
Q_ASSERT(sInstance == NULL);
|
||||||
sInstance = this;
|
sInstance = this;
|
||||||
|
@ -57,6 +58,8 @@ PythonEngine::PythonEngine(ScriptManager* manager)
|
||||||
PythonEngine::~PythonEngine() {
|
PythonEngine::~PythonEngine() {
|
||||||
sInstance = NULL;
|
sInstance = NULL;
|
||||||
|
|
||||||
|
modules_model_->clear();
|
||||||
|
|
||||||
scripts_module_ = PythonQtObjectPtr();
|
scripts_module_ = PythonQtObjectPtr();
|
||||||
clementine_module_ = PythonQtObjectPtr();
|
clementine_module_ = PythonQtObjectPtr();
|
||||||
PythonQt::cleanup();
|
PythonQt::cleanup();
|
||||||
|
@ -105,6 +108,10 @@ bool PythonEngine::EnsureInitialised() {
|
||||||
qLog(Debug) << "Creating scripts module";
|
qLog(Debug) << "Creating scripts module";
|
||||||
scripts_module_ = python_qt->createModuleFromScript(kScriptModulePrefix);
|
scripts_module_ = python_qt->createModuleFromScript(kScriptModulePrefix);
|
||||||
|
|
||||||
|
// The modules model contains all the modules
|
||||||
|
modules_model_->clear();
|
||||||
|
AddModuleToModel("__main__", python_qt->getMainModule());
|
||||||
|
|
||||||
qLog(Debug) << "Python initialisation complete";
|
qLog(Debug) << "Python initialisation complete";
|
||||||
initialised_ = true;
|
initialised_ = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -116,9 +123,10 @@ Script* PythonEngine::CreateScript(const ScriptInfo& info) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Script* ret = new PythonScript(this, info);
|
PythonScript* ret = new PythonScript(this, info);
|
||||||
loaded_scripts_[ret->info().id()] = ret; // Used by RegisterNativeObject during startup
|
loaded_scripts_[ret->info().id()] = ret; // Used by RegisterNativeObject during startup
|
||||||
if (ret->Init()) {
|
if (ret->Init()) {
|
||||||
|
AddModuleToModel(ret->module_name(), ret->module());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +135,9 @@ Script* PythonEngine::CreateScript(const ScriptInfo& info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonEngine::DestroyScript(Script* script) {
|
void PythonEngine::DestroyScript(Script* script) {
|
||||||
|
PythonScript* python_script = static_cast<PythonScript*>(script);
|
||||||
|
RemoveModuleFromModel(python_script->module_name());
|
||||||
|
|
||||||
script->Unload();
|
script->Unload();
|
||||||
loaded_scripts_.remove(script->info().id());
|
loaded_scripts_.remove(script->info().id());
|
||||||
delete script;
|
delete script;
|
||||||
|
@ -139,3 +150,15 @@ void PythonEngine::PythonStdOut(const QString& str) {
|
||||||
void PythonEngine::PythonStdErr(const QString& str) {
|
void PythonEngine::PythonStdErr(const QString& str) {
|
||||||
manager()->AddLogLine("Python", str, true);
|
manager()->AddLogLine("Python", str, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PythonEngine::AddModuleToModel(const QString& name, PythonQtObjectPtr ptr) {
|
||||||
|
QStandardItem* item = new QStandardItem(name);
|
||||||
|
item->setData(QVariant::fromValue(ptr));
|
||||||
|
modules_model_->appendRow(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonEngine::RemoveModuleFromModel(const QString& name) {
|
||||||
|
foreach (QStandardItem* item, modules_model_->findItems(name)) {
|
||||||
|
modules_model_->removeRow(item->row());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include "gtest/gtest_prod.h"
|
#include "gtest/gtest_prod.h"
|
||||||
|
|
||||||
|
class QStandardItemModel;
|
||||||
|
|
||||||
|
|
||||||
class PythonEngine : public LanguageEngine {
|
class PythonEngine : public LanguageEngine {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ public:
|
||||||
|
|
||||||
ScriptInfo::Language language() const { return ScriptInfo::Language_Python; }
|
ScriptInfo::Language language() const { return ScriptInfo::Language_Python; }
|
||||||
QString name() const { return "python"; }
|
QString name() const { return "python"; }
|
||||||
|
QStandardItemModel* modules_model() const { return modules_model_; }
|
||||||
|
|
||||||
bool EnsureInitialised();
|
bool EnsureInitialised();
|
||||||
|
|
||||||
|
@ -50,6 +54,10 @@ private slots:
|
||||||
void PythonStdOut(const QString& str);
|
void PythonStdOut(const QString& str);
|
||||||
void PythonStdErr(const QString& str);
|
void PythonStdErr(const QString& str);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddModuleToModel(const QString& name, PythonQtObjectPtr ptr);
|
||||||
|
void RemoveModuleFromModel(const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PythonEngine* sInstance;
|
static PythonEngine* sInstance;
|
||||||
bool initialised_;
|
bool initialised_;
|
||||||
|
@ -58,6 +66,7 @@ private:
|
||||||
PythonQtObjectPtr scripts_module_;
|
PythonQtObjectPtr scripts_module_;
|
||||||
|
|
||||||
QMap<QString, Script*> loaded_scripts_;
|
QMap<QString, Script*> loaded_scripts_;
|
||||||
|
QStandardItemModel* modules_model_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PYTHONENGINE_H
|
#endif // PYTHONENGINE_H
|
||||||
|
|
|
@ -27,6 +27,9 @@ class PythonScript : public Script {
|
||||||
public:
|
public:
|
||||||
PythonScript(PythonEngine* engine, const ScriptInfo& info);
|
PythonScript(PythonEngine* engine, const ScriptInfo& info);
|
||||||
|
|
||||||
|
const QString& module_name() const { return module_name_; }
|
||||||
|
PythonQtObjectPtr module() const { return module_; }
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
bool Unload();
|
bool Unload();
|
||||||
|
|
||||||
|
@ -34,7 +37,6 @@ private:
|
||||||
PythonEngine* engine_;
|
PythonEngine* engine_;
|
||||||
|
|
||||||
QString module_name_;
|
QString module_name_;
|
||||||
|
|
||||||
PythonQtObjectPtr module_;
|
PythonQtObjectPtr module_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SCRIPTING_PYTHON
|
||||||
|
# include "scripting/python/pythonengine.h"
|
||||||
|
# include "scripting/python/pythonconsole.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "installscriptdialog.h"
|
#include "installscriptdialog.h"
|
||||||
#include "scriptarchive.h"
|
#include "scriptarchive.h"
|
||||||
#include "scriptdialog.h"
|
#include "scriptdialog.h"
|
||||||
|
@ -155,6 +161,14 @@ void ScriptDialog::SetManager(ScriptManager* manager) {
|
||||||
foreach (const QString& html, manager->log_lines()) {
|
foreach (const QString& html, manager->log_lines()) {
|
||||||
LogLineAdded(html);
|
LogLineAdded(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SCRIPTING_PYTHON
|
||||||
|
// Add the python console
|
||||||
|
PythonConsole* console = new PythonConsole(this);
|
||||||
|
console->SetEngine(qobject_cast<PythonEngine*>(
|
||||||
|
manager_->EngineForLanguage(ScriptInfo::Language_Python)));
|
||||||
|
ui_->tab_widget->addTab(console, tr("Python console"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptDialog::CurrentChanged(const QModelIndex& index) {
|
void ScriptDialog::CurrentChanged(const QModelIndex& index) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|
|
@ -681,6 +681,9 @@ msgstr ""
|
||||||
msgid "Constant bitrate"
|
msgid "Constant bitrate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Context:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Convert all music"
|
msgid "Convert all music"
|
||||||
msgstr "Converteer alle muziek"
|
msgstr "Converteer alle muziek"
|
||||||
|
|
||||||
|
@ -2116,6 +2119,9 @@ msgstr "druk op Wiiremote knop"
|
||||||
msgid "Put songs in a random order"
|
msgid "Put songs in a random order"
|
||||||
msgstr "Zet liedjes in willekeurige volgorde"
|
msgstr "Zet liedjes in willekeurige volgorde"
|
||||||
|
|
||||||
|
msgid "Python console"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Quality"
|
msgid "Quality"
|
||||||
msgstr "Kwaliteit"
|
msgstr "Kwaliteit"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue