MuseScore/mscore/mscorePlugins.cpp

383 lines
13 KiB
C++
Raw Normal View History

2012-05-26 14:49:10 +02:00
//=============================================================================
// MuseScore
// Linux Music Score Editor
//
2012-12-06 14:21:53 +01:00
// Copyright (C) 2009-2012 Werner Schweer and others
2012-05-26 14:49:10 +02:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "musescore.h"
#include "libmscore/score.h"
#include "libmscore/undo.h"
2014-04-25 18:43:25 +02:00
// #include "globals.h"
2012-05-26 14:49:10 +02:00
#include "config.h"
#include "preferences.h"
#include "libmscore/chord.h"
#include "libmscore/note.h"
#include "libmscore/utils.h"
#include "libmscore/mscore.h"
#include "libmscore/measurebase.h"
#include "libmscore/measure.h"
#include "libmscore/segment.h"
2012-05-29 22:55:30 +02:00
#include "libmscore/rest.h"
#include "libmscore/stafftext.h"
2014-04-25 18:43:25 +02:00
// #include "plugins.h"
#include "libmscore/cursor.h"
#include "libmscore/page.h"
#include "libmscore/system.h"
2012-07-06 14:21:05 +02:00
#include "libmscore/staff.h"
#include "libmscore/part.h"
#include "libmscore/timesig.h"
#include "libmscore/keysig.h"
2012-07-06 14:21:05 +02:00
#include "libmscore/harmony.h"
2012-07-13 19:44:03 +02:00
#include "libmscore/slur.h"
2013-08-22 12:18:14 +02:00
#include "libmscore/tie.h"
2012-07-13 19:44:03 +02:00
#include "libmscore/notedot.h"
2012-08-10 20:50:27 +02:00
#include "libmscore/figuredbass.h"
#include "libmscore/accidental.h"
2012-11-26 15:54:08 +01:00
#include "libmscore/lyrics.h"
2013-10-05 23:13:33 +02:00
#include "libmscore/layoutbreak.h"
2012-12-10 09:15:50 +01:00
#include "qmlplugin.h"
2012-05-26 14:49:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-12-04 15:51:06 +01:00
extern QString localeName;
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// registerPlugin
//---------------------------------------------------------
2012-06-06 14:16:06 +02:00
void MuseScore::registerPlugin(PluginDescription* plugin)
2012-05-26 14:49:10 +02:00
{
2012-06-06 14:16:06 +02:00
QString pluginPath = plugin->path;
2012-05-26 14:49:10 +02:00
QFileInfo np(pluginPath);
if (np.suffix() != "qml")
return;
2012-05-26 14:49:10 +02:00
QString baseName = np.baseName();
foreach(QString s, plugins) {
QFileInfo fi(s);
if (fi.baseName() == baseName) {
if (MScore::debugMode)
qDebug(" Plugin <%s> already registered", qPrintable(pluginPath));
2012-05-26 14:49:10 +02:00
return;
}
}
QFile f(pluginPath);
if (!f.open(QIODevice::ReadOnly)) {
if (MScore::debugMode)
qDebug("Loading Plugin <%s> failed", qPrintable(pluginPath));
2012-05-26 14:49:10 +02:00
return;
}
if (MScore::debugMode)
qDebug("Register Plugin <%s>", qPrintable(pluginPath));
2012-05-26 14:49:10 +02:00
f.close();
QObject* obj = 0;
2014-04-25 18:43:25 +02:00
QQmlComponent component(Ms::MScore::qml(), QUrl::fromLocalFile(pluginPath));
2012-06-05 17:34:19 +02:00
obj = component.create();
if (obj == 0) {
qDebug("creating component <%s> failed", qPrintable(pluginPath));
2013-05-16 17:06:31 +02:00
foreach(QQmlError e, component.errors()) {
2012-06-05 17:34:19 +02:00
qDebug(" line %d: %s", e.line(), qPrintable(e.description()));
}
2012-06-05 17:34:19 +02:00
return;
2012-05-26 14:49:10 +02:00
}
2012-12-04 15:51:06 +01:00
//
// load translation
//
QLocale locale;
2012-12-06 17:00:04 +01:00
QString t = np.absolutePath() + "/translations/locale_" + MuseScore::getLocaleISOCode().left(2) + ".qm";
2012-12-04 15:51:06 +01:00
QTranslator* translator = new QTranslator;
if (!translator->load(t)) {
// qDebug("cannot load qml translations <%s>", qPrintable(t));
2012-12-04 15:51:06 +01:00
delete translator;
}
else {
// qDebug("load qml translations <%s>", qPrintable(t));
2012-12-04 15:51:06 +01:00
qApp->installTranslator(translator);
}
2012-06-05 17:34:19 +02:00
QmlPlugin* item = qobject_cast<QmlPlugin*>(obj);
QString menuPath = item->menuPath();
2012-06-06 14:16:06 +02:00
plugin->menuPath = menuPath;
2012-06-05 17:34:19 +02:00
plugins.append(pluginPath);
2012-06-06 14:16:06 +02:00
createMenuEntry(plugin);
QAction* a = plugin->shortcut.action();
pluginActions.append(a);
int pluginIdx = plugins.size() - 1; // plugin is already appended
connect(a, SIGNAL(triggered()), pluginMapper, SLOT(map()));
pluginMapper->setMapping(a, pluginIdx);
delete obj;
}
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// createMenuEntry
2012-06-06 14:16:06 +02:00
// syntax: "entry.entry.entry"
//---------------------------------------------------------
2012-06-06 14:16:06 +02:00
void MuseScore::createMenuEntry(PluginDescription* plugin)
{
2012-05-26 14:49:10 +02:00
if (!pluginMapper)
return;
2012-06-06 14:16:06 +02:00
QString menu = plugin->menuPath;
2012-05-26 14:49:10 +02:00
QStringList ml;
QString s;
bool escape = false;
foreach (QChar c, menu) {
if (escape) {
escape = false;
s += c;
}
else {
if (c == '\\')
escape = true;
else {
if (c == '.') {
ml += s;
s = "";
}
else {
s += c;
}
}
}
}
if (!s.isEmpty())
ml += s;
int n = ml.size();
QWidget* curMenu = menuBar();
for(int i = 0; i < n; ++i) {
QString m = ml[i];
bool found = false;
QList<QObject*> ol = curMenu->children();
foreach(QObject* o, ol) {
QMenu* menu = qobject_cast<QMenu*>(o);
if (!menu)
continue;
if (menu->objectName() == m || menu->title() == m) {
curMenu = menu;
found = true;
break;
}
}
if (!found) {
if (i == 0) {
curMenu = new QMenu(m, menuBar());
curMenu->setObjectName(m);
menuBar()->insertMenu(menuBar()->actions().back(), (QMenu*)curMenu);
if (MScore::debugMode)
qDebug("add Menu <%s>", qPrintable(m));
2012-05-26 14:49:10 +02:00
}
else if (i + 1 == n) {
QStringList sl = m.split(":");
2012-06-06 14:16:06 +02:00
QAction* a = plugin->shortcut.action();
2012-05-26 14:49:10 +02:00
QMenu* cm = static_cast<QMenu*>(curMenu);
if (sl.size() == 2) {
QList<QAction*> al = cm->actions();
QAction* ba = 0;
foreach(QAction* ia, al) {
if (ia->text() == sl[0]) {
ba = ia;
break;
}
}
2012-06-06 14:16:06 +02:00
a->setText(sl[1]);
2012-05-26 14:49:10 +02:00
cm->insertAction(ba, a);
}
else {
2012-06-06 14:16:06 +02:00
a->setText(m);
cm->addAction(a);
2012-05-26 14:49:10 +02:00
}
2012-06-06 14:16:06 +02:00
2012-05-26 14:49:10 +02:00
if (MScore::debugMode)
qDebug("plugins: add action <%s>", qPrintable(m));
2012-05-26 14:49:10 +02:00
}
else {
curMenu = ((QMenu*)curMenu)->addMenu(m);
if (MScore::debugMode)
qDebug("add menu <%s>", qPrintable(m));
2012-05-26 14:49:10 +02:00
}
}
}
}
//---------------------------------------------------------
// pluginIdxFromPath
//---------------------------------------------------------
int MuseScore::pluginIdxFromPath(QString pluginPath) {
QFileInfo np(pluginPath);
QString baseName = np.baseName();
int idx = 0;
foreach(QString s, plugins) {
QFileInfo fi(s);
if (fi.baseName() == baseName)
2012-05-26 14:49:10 +02:00
return idx;
idx++;
}
return -1;
}
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// loadPlugins
//---------------------------------------------------------
void MuseScore::loadPlugins()
{
pluginMapper = new QSignalMapper(this);
connect(pluginMapper, SIGNAL(mapped(int)), SLOT(pluginTriggered(int)));
for (int i = 0; i < preferences.pluginList.size(); ++i) {
PluginDescription* d = &preferences.pluginList[i];
2012-06-06 14:16:06 +02:00
if (d->load)
registerPlugin(d);
2012-05-26 14:49:10 +02:00
}
}
//---------------------------------------------------------
// unloadPlugins
//---------------------------------------------------------
void MuseScore::unloadPlugins()
{
for (int idx = 0; idx < plugins.size() ; idx++) {
2012-05-29 23:17:49 +02:00
; // TODO
}
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
// loadPlugin
//---------------------------------------------------------
bool MuseScore::loadPlugin(const QString& filename)
{
bool result = false;
2012-09-13 16:10:13 +02:00
if (!pluginMapper) {
pluginMapper = new QSignalMapper(this);
connect(pluginMapper, SIGNAL(mapped(int)), SLOT(pluginTriggered(int)));
}
2012-05-26 14:49:10 +02:00
QDir pluginDir(mscoreGlobalShare + "plugins");
if (MScore::debugMode)
qDebug("Plugin Path <%s>", qPrintable(mscoreGlobalShare + "plugins"));
2012-05-26 14:49:10 +02:00
if (filename.endsWith(".qml")){
2012-05-26 14:49:10 +02:00
QFileInfo fi(pluginDir, filename);
if (fi.exists()) {
QString path(fi.filePath());
2012-09-13 16:10:13 +02:00
PluginDescription* p = new PluginDescription;
p->path = path;
p->load = false;
collectPluginMetaInformation(p);
registerPlugin(p);
2012-05-26 14:49:10 +02:00
result = true;
}
}
return result;
}
//---------------------------------------------------------
// pluginTriggered
//---------------------------------------------------------
void MuseScore::pluginTriggered(int idx)
{
QString pp = plugins[idx];
2013-07-10 15:29:58 +02:00
2014-04-25 18:43:25 +02:00
QQmlEngine* engine = Ms::MScore::qml();
QQmlComponent component(engine);
component.loadUrl(QUrl::fromLocalFile(pp));
QObject* obj = component.create();
if (obj == 0) {
foreach(QQmlError e, component.errors())
qDebug(" line %d: %s", e.line(), qPrintable(e.description()));
return;
2012-06-05 17:34:19 +02:00
}
QmlPlugin* p = qobject_cast<QmlPlugin*>(obj);
if (p->pluginType() == "dock" || p->pluginType() == "dialog") {
QQuickView* view = new QQuickView(engine, 0);
view->setSource(QUrl::fromLocalFile(pp));
2013-07-23 22:13:49 +02:00
view->setTitle(p->menuPath().mid(p->menuPath().lastIndexOf(".") + 1));
view->setColor(QApplication::palette().color(QPalette::Window));
//p->setParentItem(view->contentItem());
//view->setWidth(p->width());
//view->setHeight(p->height());
view->setResizeMode(QQuickView::SizeRootObjectToView);
if (p->pluginType() == "dock") {
QDockWidget* dock = new QDockWidget("Plugin", 0);
dock->setAttribute(Qt::WA_DeleteOnClose);
Qt::DockWidgetArea area = Qt::RightDockWidgetArea;
if (p->dockArea() == "left")
area = Qt::LeftDockWidgetArea;
else if (p->dockArea() == "top")
area = Qt::TopDockWidgetArea;
else if (p->dockArea() == "bottom")
area = Qt::BottomDockWidgetArea;
QWidget* w = QWidget::createWindowContainer(view);
dock->setWidget(w);
addDockWidget(area, dock);
connect(engine, SIGNAL(quit()), dock, SLOT(close()));
view->show();
}
else {
connect(engine, SIGNAL(quit()), view, SLOT(close()));
view->show();
}
2012-06-05 17:34:19 +02:00
}
2013-07-10 21:59:00 +02:00
// dont call startCmd for non modal dialog
if (cs && p->pluginType() != "dock")
2012-06-08 19:06:52 +02:00
cs->startCmd();
2013-07-10 21:59:00 +02:00
p->runPlugin();
if (cs && p->pluginType() != "dock")
2012-06-08 19:06:52 +02:00
cs->endCmd();
endCmd();
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
// collectPluginMetaInformation
//---------------------------------------------------------
void collectPluginMetaInformation(PluginDescription* d)
{
2014-03-04 16:48:06 +01:00
qDebug("Collect meta for <%s>", qPrintable(d->path));
2014-04-25 18:43:25 +02:00
QQmlComponent component(Ms::MScore::qml(), QUrl::fromLocalFile(d->path));
QObject* obj = component.create();
if (obj == 0) {
qDebug("creating component <%s> failed", qPrintable(d->path));
2013-05-16 17:06:31 +02:00
foreach(QQmlError e, component.errors()) {
qDebug(" line %d: %s", e.line(), qPrintable(e.description()));
}
return;
}
QmlPlugin* item = qobject_cast<QmlPlugin*>(obj);
if (item) {
d->version = item->version();
d->description = item->description();
}
delete obj;
}
2013-05-13 18:49:17 +02:00
}