1
mirror of https://invent.kde.org/network/falkon.git synced 2024-09-21 09:42:10 +02:00

Don't use subfolders for QML/Python extensions

This commit is contained in:
David Rosca 2019-04-19 11:38:15 +02:00
parent 6dd33dd803
commit d2d3d45932
No known key found for this signature in database
GPG Key ID: EBC3FC294452C6D8
13 changed files with 61 additions and 96 deletions

View File

@ -19,6 +19,7 @@
#include "pluginproxy.h" #include "pluginproxy.h"
#include "datapaths.h" #include "datapaths.h"
#include "networkmanager.h" #include "networkmanager.h"
#include "desktopfile.h"
#include "desktopnotificationsfactory.h" #include "desktopnotificationsfactory.h"
#include "mainapplication.h" #include "mainapplication.h"
@ -31,6 +32,18 @@
Q_GLOBAL_STATIC(OcsSupport, qz_ocs_support) Q_GLOBAL_STATIC(OcsSupport, qz_ocs_support)
static DesktopFile readMetaData(const KArchiveDirectory *directory)
{
const KArchiveEntry *entry = directory->entry(QSL("metadata.desktop"));
if (!entry || !entry->isFile()) {
qWarning() << "No metadata.desktop found";
return DesktopFile();
}
const QString tempDir = DataPaths::path(DataPaths::Temp);
static_cast<const KArchiveFile*>(entry)->copyTo(tempDir);
return DesktopFile(tempDir + QL1S("/metadata.desktop"));
}
OcsSupport::OcsSupport(QObject *parent) OcsSupport::OcsSupport(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
@ -124,6 +137,8 @@ void OcsSupport::installTheme(const KArchiveDirectory *directory)
return; return;
} }
const DesktopFile metaData = readMetaData(static_cast<const KArchiveDirectory*>(entry));
const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/themes"); const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/themes");
QDir().mkpath(targetDir); QDir().mkpath(targetDir);
@ -141,7 +156,7 @@ void OcsSupport::installTheme(const KArchiveDirectory *directory)
qInfo() << "Theme installed to" << targetDir; qInfo() << "Theme installed to" << targetDir;
mApp->desktopNotifications()->showNotification(tr("Theme installed"), tr("Theme was successfully installed")); mApp->desktopNotifications()->showNotification(tr("Theme installed"), tr("'%1' was successfully installed").arg(metaData.name()));
} }
void OcsSupport::installExtension(const KArchiveDirectory *directory) void OcsSupport::installExtension(const KArchiveDirectory *directory)
@ -164,21 +179,23 @@ void OcsSupport::installExtension(const KArchiveDirectory *directory)
return; return;
} }
const DesktopFile metaData = readMetaData(static_cast<const KArchiveDirectory*>(entry));
const QString extensionType = metaData.value(QSL("X-Falkon-Type")).toString();
QString type; QString type;
const QStringList files = static_cast<const KArchiveDirectory*>(entry)->entries(); if (extensionType == QL1S("Extension/Python")) {
if (files.contains(QL1S("__init__.py"))) {
type = QSL("python"); type = QSL("python");
} else if (files.contains(QL1S("main.qml"))) { } else if (extensionType == QL1S("Extension/Qml")) {
type = QSL("qml"); type = QSL("qml");
} }
if (type.isEmpty()) { if (type.isEmpty()) {
qWarning() << "Unsupported extension type"; qWarning() << "Unsupported extension type" << extensionType;
showError(); showError();
return; return;
} }
const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/plugins/") + type; const QString targetDir = DataPaths::path(DataPaths::Config) + QL1S("/plugins/");
QDir().mkpath(targetDir); QDir().mkpath(targetDir);
if (QFileInfo::exists(targetDir + QL1S("/") + name)) { if (QFileInfo::exists(targetDir + QL1S("/") + name)) {
@ -202,5 +219,5 @@ void OcsSupport::installExtension(const KArchiveDirectory *directory)
return; return;
} }
mApp->desktopNotifications()->showNotification(tr("Extension installed"), tr("Extension was successfully installed")); mApp->desktopNotifications()->showNotification(tr("Extension installed"), tr("'%1' was successfully installed").arg(metaData.name()));
} }

View File

@ -236,50 +236,34 @@ void Plugins::loadAvailablePlugins()
// InternalPlugin // InternalPlugin
registerAvailablePlugin(loadInternalPlugin(QSL("adblock"))); registerAvailablePlugin(loadInternalPlugin(QSL("adblock")));
// SharedLibraryPlugin
for (const QString &dir : dirs) { for (const QString &dir : dirs) {
const auto files = QDir(dir).entryInfoList(QDir::Files); const auto files = QDir(dir).entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &info : files) { for (const QFileInfo &info : files) {
if (info.baseName() == QL1S("PyFalkon")) { Plugin plugin;
continue; const QString pluginPath = info.absoluteFilePath();
if (info.isFile()) {
// SharedLibraryPlugin
if (info.baseName() != QL1S("PyFalkon")) {
plugin = loadSharedLibraryPlugin(pluginPath);
}
} else if (info.isDir()) {
const DesktopFile metaData(QDir(pluginPath).filePath(QSL("metadata.desktop")));
const QString type = metaData.value(QSL("X-Falkon-Type")).toString();
if (type == QL1S("Extension/Python")) {
// PythonPlugin
plugin = loadPythonPlugin(pluginPath);
} else if (type == QL1S("Extension/Qml")) {
// QmlPlugin
plugin = QmlPlugin::loadPlugin(pluginPath);
} else {
qWarning() << "Invalid type" << type << "of" << pluginPath << "plugin";
}
} }
Plugin plugin = loadSharedLibraryPlugin(info.absoluteFilePath());
if (plugin.type == Plugin::Invalid) { if (plugin.type == Plugin::Invalid) {
continue; continue;
} }
if (plugin.pluginSpec.name.isEmpty()) { if (plugin.pluginSpec.name.isEmpty()) {
qWarning() << "Invalid plugin spec of" << info.absoluteFilePath() << "plugin"; qWarning() << "Invalid plugin spec of" << pluginPath << "plugin";
continue;
}
registerAvailablePlugin(plugin);
}
}
// PythonPlugin
if (m_pythonPlugin) {
auto f = (QVector<Plugin>(*)()) m_pythonPlugin->resolve("pyfalkon_load_available_plugins");
if (!f) {
qWarning() << "Failed to resolve" << "pyfalkon_load_available_plugins";
} else {
const auto plugins = f();
for (const auto &plugin : plugins) {
registerAvailablePlugin(plugin);
}
}
}
// QmlPlugin
for (QString dir : dirs) {
// Qml plugins will be loaded from subdirectory qml
dir.append(QSL("/qml"));
const auto qmlDirs = QDir(dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &info : qmlDirs) {
Plugin plugin = QmlPlugin::loadPlugin(info.absoluteFilePath());
if (plugin.type == Plugin::Invalid) {
continue;
}
if (plugin.pluginSpec.name.isEmpty()) {
qWarning() << "Invalid plugin spec of" << info.absoluteFilePath() << "plugin";
continue; continue;
} }
registerAvailablePlugin(plugin); registerAvailablePlugin(plugin);

View File

@ -40,15 +40,6 @@ State state = PythonUninitialized;
PluginInterface *pluginInterface = nullptr; PluginInterface *pluginInterface = nullptr;
QHash<PyObject*, PluginInterface*> pluginInstances; QHash<PyObject*, PluginInterface*> pluginInstances;
static QStringList script_paths()
{
QStringList dirs = DataPaths::allPaths(DataPaths::Plugins);
for (int i = 0; i < dirs.count(); ++i) {
dirs[i].append(QSL("/python"));
}
return dirs;
}
static void cleanup() static void cleanup()
{ {
if (state > PythonUninitialized) { if (state > PythonUninitialized) {
@ -73,7 +64,7 @@ static State init()
return state; return state;
} }
set_path(script_paths()); set_path(DataPaths::allPaths(DataPaths::Plugins));
if (PyImport_AppendInittab("Falkon", PyInit_PyFalkon) != 0) { if (PyImport_AppendInittab("Falkon", PyInit_PyFalkon) != 0) {
PyErr_Print(); PyErr_Print();
@ -143,37 +134,3 @@ void pyfalkon_init_plugin(Plugins::Plugin *plugin)
plugin->instance = pluginInterface; plugin->instance = pluginInterface;
plugin->data = QVariant::fromValue(static_cast<void*>(module)); plugin->data = QVariant::fromValue(static_cast<void*>(module));
} }
QVector<Plugins::Plugin> pyfalkon_load_available_plugins()
{
QVector<Plugins::Plugin> plugins;
const QStringList dirs = script_paths();
for (const QString &dir : dirs) {
const auto modules = QDir(dir).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &info : modules) {
Plugins::Plugin plugin = pyfalkon_load_plugin(info.absoluteFilePath());
if (plugin.pluginSpec.name.isEmpty()) {
qWarning() << "Invalid plugin spec of" << info.absoluteFilePath() << "plugin";
continue;
}
plugins.append(plugin);
}
}
return plugins;
}
bool pyfalkon_run_script(const QByteArray &script)
{
if (init() != PythonInitialized) {
return false;
}
if (PyRun_SimpleString(script.constData()) != 0) {
PyErr_Print();
return false;
}
return true;
}

View File

@ -23,6 +23,3 @@ void pyfalkon_register_plugin(PluginInterface *plugin);
extern "C" Q_DECL_EXPORT Plugins::Plugin pyfalkon_load_plugin(const QString &name); extern "C" Q_DECL_EXPORT Plugins::Plugin pyfalkon_load_plugin(const QString &name);
extern "C" Q_DECL_EXPORT void pyfalkon_init_plugin(Plugins::Plugin *plugin); extern "C" Q_DECL_EXPORT void pyfalkon_init_plugin(Plugins::Plugin *plugin);
extern "C" Q_DECL_EXPORT QVector<Plugins::Plugin> pyfalkon_load_available_plugins();
extern "C" Q_DECL_EXPORT bool pyfalkon_run_script(const QByteArray &script);

View File

@ -2,23 +2,23 @@ function(install_python_script name)
if (ENABLE_PYTHON_PLUGINS) if (ENABLE_PYTHON_PLUGINS)
install( install(
DIRECTORY ${name} DIRECTORY ${name}
DESTINATION "${FALKON_INSTALL_PLUGINDIR}/python" DESTINATION ${FALKON_INSTALL_PLUGINDIR}
FILES_MATCHING PATTERN "*" PATTERN "Messages.sh" EXCLUDE FILES_MATCHING PATTERN "*" PATTERN "Messages.sh" EXCLUDE
) )
install(FILES i18n.py DESTINATION "${FALKON_INSTALL_PLUGINDIR}/python/${name}") install(FILES i18n.py DESTINATION "${FALKON_INSTALL_PLUGINDIR}/${name}")
endif() endif()
endfunction() endfunction()
function(install_qml_script name) function(install_qml_script name)
install( install(
DIRECTORY ${name} DIRECTORY ${name}
DESTINATION "${FALKON_INSTALL_PLUGINDIR}/qml" DESTINATION ${FALKON_INSTALL_PLUGINDIR}
FILES_MATCHING PATTERN "*" PATTERN "Messages.sh" EXCLUDE FILES_MATCHING PATTERN "*" PATTERN "Messages.sh" EXCLUDE
) )
endfunction() endfunction()
install_python_script(hellopython) # install_python_script(hellopython)
install_python_script(runaction) install_python_script(runaction)
install_python_script(middleclickloader) install_python_script(middleclickloader)
install_qml_script(helloqml) # install_qml_script(helloqml)

View File

@ -50,6 +50,7 @@ Comment[zh_TW]=Python 擴充程式範例
Icon= Icon=
Type=Service Type=Service
X-Falkon-Type=Extension/Python
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com

View File

@ -43,8 +43,11 @@ Comment[uk]=Зразок додатка Qml
Comment[x-test]=xxSample Qml Pluginxx Comment[x-test]=xxSample Qml Pluginxx
Comment[zh_CN]= Qml Comment[zh_CN]= Qml
Comment[zh_TW]= QML Comment[zh_TW]= QML
Icon= Icon=
Type=Service Type=Service
X-Falkon-Type=Extension/Qml
X-Falkon-Author=Anmol Gautam X-Falkon-Author=Anmol Gautam
X-Falkon-Email=tarptaeya@gmail.com X-Falkon-Email=tarptaeya@gmail.com
X-Falkon-Version=0.1.0 X-Falkon-Version=0.1.0

View File

@ -46,6 +46,7 @@ Comment[zh_CN]=将选择剪贴板中的文本加载为 URL
Icon= Icon=
Type=Service Type=Service
X-Falkon-Type=Extension/Python
X-Falkon-Author=Juraj Oravec X-Falkon-Author=Juraj Oravec
X-Falkon-Email=sgd.orava@gmail.com X-Falkon-Email=sgd.orava@gmail.com

View File

@ -48,6 +48,7 @@ Comment[zh_TW]=在網站上執行各種動作
Icon=icon.svg Icon=icon.svg
Type=Service Type=Service
X-Falkon-Type=Extension/Python
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com

View File

@ -49,6 +49,7 @@ Comment[zh_CN]=基于火狐 Chromifox 主题的类似于 Chrome 的 Falkon 主
Icon=theme.png Icon=theme.png
Type=Service Type=Service
X-Falkon-Type=Theme
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com

View File

@ -49,6 +49,7 @@ Comment[zh_CN]=给 Linux 设计的使用原生控件的默认简易主题,图
Icon=theme.png Icon=theme.png
Type=Service Type=Service
X-Falkon-Type=Theme
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com

View File

@ -50,6 +50,7 @@ Comment[zh_TW]=適用於 Falkon基於 Firefox Mac OS X 主題的類 Mac 主
Icon=theme.png Icon=theme.png
Type=Service Type=Service
X-Falkon-Type=Theme
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com

View File

@ -50,6 +50,7 @@ Comment[zh_TW]=基於質感設計的類 Windows 主題
Icon=theme.png Icon=theme.png
Type=Service Type=Service
X-Falkon-Type=Theme
X-Falkon-Author=David Rosca X-Falkon-Author=David Rosca
X-Falkon-Email=nowrep@gmail.com X-Falkon-Email=nowrep@gmail.com