mirror of
https://invent.kde.org/network/falkon.git
synced 2024-12-20 18:56:34 +01:00
Add RunAction extension
Allows to run actions on sites. Actions are specified in desktop files and allow to either load url or run command depending on defined conditions. This extension is a generic replacement for ImageFinder and Videoner plugins.
This commit is contained in:
parent
63cf3dbade
commit
0495b46d16
@ -6,3 +6,4 @@ function(install_python_script name)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
install_python_script(hellopython)
|
install_python_script(hellopython)
|
||||||
|
install_python_script(runaction)
|
||||||
|
@ -8,4 +8,11 @@ XGETTEXT_FLAGS_PYTHON="\
|
|||||||
-ki18n:1 -ki18np:1,2 \
|
-ki18n:1 -ki18np:1,2 \
|
||||||
"
|
"
|
||||||
|
|
||||||
$XGETTEXT_PROGRAM $XGETTEXT_FLAGS_PYTHON `find hellopython -name '*.py'` -o $podir/falkon_hellopython.pot
|
python_scripts="
|
||||||
|
hellopython
|
||||||
|
runaction
|
||||||
|
"
|
||||||
|
|
||||||
|
for script in $python_scripts; do
|
||||||
|
$XGETTEXT_PROGRAM $XGETTEXT_FLAGS_PYTHON `find $script -name '*.py'` -o $podir/falkon_$script.pot
|
||||||
|
done
|
||||||
|
18
src/scripts/runaction/__init__.py
Normal file
18
src/scripts/runaction/__init__.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
from .runaction import *
|
73
src/scripts/runaction/action.py
Normal file
73
src/scripts/runaction/action.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
import Falkon
|
||||||
|
import os, re, enum, shlex
|
||||||
|
from PySide2 import QtCore, QtGui
|
||||||
|
|
||||||
|
class Action():
|
||||||
|
class Type(enum.Enum):
|
||||||
|
Invalid, Url, Command = range(3)
|
||||||
|
|
||||||
|
class TypeCondition(enum.Enum):
|
||||||
|
Page, Link, Image, Media, Text = range(5)
|
||||||
|
|
||||||
|
id = ""
|
||||||
|
title = ""
|
||||||
|
menuTitle = ""
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
actionType = Type.Invalid
|
||||||
|
typeCondition = [ TypeCondition.Page, TypeCondition.Link, TypeCondition.Image, TypeCondition.Media ]
|
||||||
|
urlCondition = ".*"
|
||||||
|
submenu = ""
|
||||||
|
normalExec = ""
|
||||||
|
textExec = ""
|
||||||
|
supported = False
|
||||||
|
|
||||||
|
def __init__(self, fileName):
|
||||||
|
data = Falkon.DesktopFile(fileName)
|
||||||
|
self.id = os.path.splitext(os.path.basename(fileName))[0]
|
||||||
|
self.title = data.name()
|
||||||
|
self.menuTitle = data.comment()
|
||||||
|
self.icon = QtGui.QIcon.fromTheme(data.icon(), QtGui.QIcon(os.path.join(os.path.dirname(fileName), data.icon())))
|
||||||
|
self.actionType = Action.Type[data.value("X-RunAction-Type")]
|
||||||
|
self.typeCondition = list(map(lambda s: Action.TypeCondition[s], data.value("X-RunAction-TypeCondition").split(";")))
|
||||||
|
self.urlCondition = data.value("X-RunAction-UrlCondition") or self.urlCondition
|
||||||
|
self.submenu = data.value("X-RunAction-Submenu") or self.submenu
|
||||||
|
self.normalExec = data.value("X-RunAction-Exec") or self.normalExec
|
||||||
|
self.textExec = data.value("X-RunAction-TextExec") or self.normalExec
|
||||||
|
self.supported = data.tryExec()
|
||||||
|
|
||||||
|
def testAction(self, condition, url):
|
||||||
|
if not self.supported: return False
|
||||||
|
if not condition in self.typeCondition: return False
|
||||||
|
if not re.match(self.urlCondition, url.toString()): return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def execAction(self, url, text=""):
|
||||||
|
url = str(url.toEncoded())
|
||||||
|
if self.actionType == Action.Type.Command:
|
||||||
|
url = shlex.quote(url)
|
||||||
|
text = shlex.quote(text)
|
||||||
|
elif self.actionType == Action.Type.Url:
|
||||||
|
url = str(QtCore.QUrl.toPercentEncoding(url))
|
||||||
|
text = str(QtCore.QUrl.toPercentEncoding(text))
|
||||||
|
command = self.normalExec if text == "" else self.textExec
|
||||||
|
command = command.replace("{url}", url)
|
||||||
|
command = command.replace("{text}", text)
|
||||||
|
command = command.replace("{lang}", QtCore.QLocale.system().name()[:2])
|
||||||
|
return command
|
113
src/scripts/runaction/actionmanager.py
Normal file
113
src/scripts/runaction/actionmanager.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
import Falkon
|
||||||
|
import os, subprocess
|
||||||
|
from PySide2 import QtCore, QtGui, QtWidgets, QtUiTools
|
||||||
|
from runaction.action import Action
|
||||||
|
from runaction.settingsdialog import SettingsDialog
|
||||||
|
|
||||||
|
class ActionManager(QtCore.QObject):
|
||||||
|
actions = []
|
||||||
|
|
||||||
|
def __init__(self, settingsPath, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.settingsPath = settingsPath
|
||||||
|
settings = QtCore.QSettings(self.settingsPath + "/extensions.ini", QtCore.QSettings.IniFormat)
|
||||||
|
self._disabledActions = settings.value("RunAction/disabledActions") or []
|
||||||
|
self.loadActions()
|
||||||
|
|
||||||
|
def getActions(self, webView, r=None):
|
||||||
|
out = []
|
||||||
|
menus = {}
|
||||||
|
|
||||||
|
for action in list(filter(lambda a: a.id not in self.disabledActions, self.actions)):
|
||||||
|
url = webView.url()
|
||||||
|
text = ""
|
||||||
|
if r and webView.selectedText():
|
||||||
|
cond = Action.TypeCondition.Text
|
||||||
|
text = webView.selectedText()
|
||||||
|
elif r and not r.linkUrl().isEmpty():
|
||||||
|
cond = Action.TypeCondition.Link
|
||||||
|
url = r.linkUrl()
|
||||||
|
elif r and not r.imageUrl().isEmpty():
|
||||||
|
cond = Action.TypeCondition.Image
|
||||||
|
url = r.imageUrl()
|
||||||
|
elif r and not r.mediaUrl().isEmpty():
|
||||||
|
cond = Action.TypeCondition.Media
|
||||||
|
url = r.mediaUrl()
|
||||||
|
else:
|
||||||
|
cond = Action.TypeCondition.Page
|
||||||
|
|
||||||
|
if action.testAction(cond, url):
|
||||||
|
act = Falkon.Action(action.icon, action.title, self)
|
||||||
|
act.triggered.connect(lambda a=action, w=webView, u=url, t=text: self.execAction(a, w, u, t))
|
||||||
|
if action.submenu:
|
||||||
|
if not action.submenu in menus:
|
||||||
|
menu = Falkon.Menu(action.menuTitle, webView)
|
||||||
|
menus[action.submenu] = menu
|
||||||
|
out.append(menu)
|
||||||
|
menus[action.submenu].addAction(act)
|
||||||
|
else:
|
||||||
|
out.append(act)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
@property
|
||||||
|
def disabledActions(self):
|
||||||
|
return self._disabledActions
|
||||||
|
|
||||||
|
@disabledActions.setter
|
||||||
|
def disabledActions(self, value):
|
||||||
|
settings = QtCore.QSettings(self.settingsPath + "/extensions.ini", QtCore.QSettings.IniFormat)
|
||||||
|
settings.setValue("RunAction/disabledActions", value)
|
||||||
|
self._disabledActions = value
|
||||||
|
|
||||||
|
def showSettings(self, parent=None):
|
||||||
|
dialog = SettingsDialog(self, parent)
|
||||||
|
dialog.exec_()
|
||||||
|
|
||||||
|
def execAction(self, action, webView, url, text=""):
|
||||||
|
command = action.execAction(url, text)
|
||||||
|
if action.actionType == Action.Type.Command:
|
||||||
|
subprocess.Popen(command, shell=True)
|
||||||
|
elif action.actionType == Action.Type.Url:
|
||||||
|
webView.openUrlInNewTab(QtCore.QUrl(command), Falkon.Qz.NT_SelectedTab)
|
||||||
|
|
||||||
|
def loadActions(self):
|
||||||
|
self.actions = []
|
||||||
|
|
||||||
|
paths = [
|
||||||
|
os.path.join(os.path.dirname(__file__), "actions"),
|
||||||
|
os.path.join(self.settingsPath, "runaction")
|
||||||
|
]
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
continue
|
||||||
|
for file in os.listdir(path):
|
||||||
|
if not file.endswith(".desktop"):
|
||||||
|
continue
|
||||||
|
fileName = os.path.join(path, file)
|
||||||
|
try:
|
||||||
|
action = Action(fileName)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to parse {}: {}".format(fileName, e))
|
||||||
|
finally:
|
||||||
|
if action.supported:
|
||||||
|
self.actions.append(action)
|
8
src/scripts/runaction/actions/dictionary.desktop
Normal file
8
src/scripts/runaction/actions/dictionary.desktop
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Dictionary
|
||||||
|
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Text"
|
||||||
|
X-RunAction-Exec="http://{lang}.wiktionary.org/wiki/Special:Search?search={text}"
|
BIN
src/scripts/runaction/actions/google.png
Normal file
BIN
src/scripts/runaction/actions/google.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
11
src/scripts/runaction/actions/googleimagesearch.desktop
Normal file
11
src/scripts/runaction/actions/googleimagesearch.desktop
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Google
|
||||||
|
Comment=Search with...
|
||||||
|
|
||||||
|
Icon=google.png
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Image"
|
||||||
|
X-RunAction-Submenu="search_with"
|
||||||
|
X-RunAction-Exec="https://www.google.com/searchbyimage?site=search&image_url={url}"
|
10
src/scripts/runaction/actions/mpv.desktop
Normal file
10
src/scripts/runaction/actions/mpv.desktop
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=mpv
|
||||||
|
|
||||||
|
Icon=mpv
|
||||||
|
TryExec=mpv
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Command"
|
||||||
|
X-RunAction-TypeCondition="Page;Link;Media"
|
||||||
|
X-RunAction-Exec="mpv {url}"
|
BIN
src/scripts/runaction/actions/tineye.png
Normal file
BIN
src/scripts/runaction/actions/tineye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
11
src/scripts/runaction/actions/tineyeimagesearch.desktop
Normal file
11
src/scripts/runaction/actions/tineyeimagesearch.desktop
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=TinEye
|
||||||
|
Comment=Search with...
|
||||||
|
|
||||||
|
Icon=tineye.png
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Image"
|
||||||
|
X-RunAction-Submenu="search_with"
|
||||||
|
X-RunAction-Exec="http://www.tineye.com/search?url={url}"
|
9
src/scripts/runaction/actions/translate.desktop
Normal file
9
src/scripts/runaction/actions/translate.desktop
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Translate page
|
||||||
|
|
||||||
|
Icon=translate.png
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Page"
|
||||||
|
X-RunAction-Exec="http://translate.google.com/translate?sl=auto&tl={lang}&u={url}"
|
BIN
src/scripts/runaction/actions/translate.png
Normal file
BIN
src/scripts/runaction/actions/translate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
9
src/scripts/runaction/actions/w3.desktop
Normal file
9
src/scripts/runaction/actions/w3.desktop
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Validate page
|
||||||
|
|
||||||
|
Icon=w3.png
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Page"
|
||||||
|
X-RunAction-Exec="http://validator.w3.org/check?uri={url}"
|
BIN
src/scripts/runaction/actions/w3.png
Normal file
BIN
src/scripts/runaction/actions/w3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
src/scripts/runaction/actions/yandex.png
Normal file
BIN
src/scripts/runaction/actions/yandex.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 669 B |
11
src/scripts/runaction/actions/yandeximagesearch.desktop
Normal file
11
src/scripts/runaction/actions/yandeximagesearch.desktop
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Yandex
|
||||||
|
Comment=Search with...
|
||||||
|
|
||||||
|
Icon=yandex.png
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-RunAction-Type="Url"
|
||||||
|
X-RunAction-TypeCondition="Image"
|
||||||
|
X-RunAction-Submenu="search_with"
|
||||||
|
X-RunAction-Exec="https://yandex.com/images/search?&img_url={url}&rpt=imageview"
|
50
src/scripts/runaction/button.py
Normal file
50
src/scripts/runaction/button.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
import Falkon
|
||||||
|
import os
|
||||||
|
from PySide2 import QtGui, QtWidgets
|
||||||
|
from runaction.i18n import i18n
|
||||||
|
|
||||||
|
class RunActionButton(Falkon.AbstractButtonInterface):
|
||||||
|
def __init__(self, manager):
|
||||||
|
super().__init__()
|
||||||
|
self.manager = manager
|
||||||
|
|
||||||
|
self.setIcon(QtGui.QIcon(os.path.join(os.path.dirname(__file__), "icon.svg")))
|
||||||
|
self.setTitle(i18n("Run Action"))
|
||||||
|
self.setToolTip(i18n("Run action on current page"))
|
||||||
|
|
||||||
|
self.clicked.connect(self.onClicked)
|
||||||
|
|
||||||
|
def id(self):
|
||||||
|
return "runaction-button"
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return i18n("RunAction button")
|
||||||
|
|
||||||
|
def onClicked(self, controller):
|
||||||
|
self.menu = QtWidgets.QMenu()
|
||||||
|
|
||||||
|
for action in self.manager.getActions(self.webView()):
|
||||||
|
self.menu.addAction(action)
|
||||||
|
|
||||||
|
self.menu.addSeparator()
|
||||||
|
self.menu.addAction(QtGui.QIcon.fromTheme("configure"), i18n("Configure..."), self.manager.showSettings)
|
||||||
|
|
||||||
|
self.menu.popup(controller.callPopupPosition(self.menu.sizeHint()))
|
||||||
|
self.menu.aboutToHide.connect(controller.callPopupClosed)
|
13
src/scripts/runaction/icon.svg
Normal file
13
src/scripts/runaction/icon.svg
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<defs id="defs3051">
|
||||||
|
<style type="text/css" id="current-color-scheme">
|
||||||
|
.ColorScheme-Text {
|
||||||
|
color:#4d4d4d;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</defs>
|
||||||
|
<path style="fill:currentColor;fill-opacity:1;stroke:none"
|
||||||
|
d="M 12 4 C 11.32479 4.004 10.65279 4.092995 10 4.265625 L 10 5.2988281 L 10 5.3105469 A 7 7 0 0 0 8.6835938 5.8554688 L 8.6757812 5.8476562 L 7.9433594 5.1152344 C 6.7764094 5.8032844 5.8032844 6.7764094 5.1152344 7.9433594 L 5.6367188 8.4648438 L 5.8554688 8.6835938 A 7 7 0 0 0 5.3085938 10 L 5.2949219 10 L 4.2597656 10 C 4.0891457 10.65304 4.00187 11.32505 4 12 C 4.004 12.67521 4.093005 13.34721 4.265625 14 L 5.2988281 14 L 5.3105469 14 A 7 7 0 0 0 5.8554688 15.316406 L 5.6367188 15.535156 L 5.1152344 16.056641 C 5.8032844 17.223601 6.7763994 18.196716 7.9433594 18.884766 L 8.4648438 18.363281 L 8.6835938 18.144531 A 7 7 0 0 0 10 18.691406 L 10 19 L 10 19.740234 C 10.65304 19.910854 11.32504 19.99813 12 20 C 12.67496 19.9981 13.34696 19.91085 14 19.740234 L 14 19 L 14 18.691406 A 7 7 0 0 0 15.316406 18.144531 L 15.535156 18.363281 L 16.056641 18.884766 C 17.223601 18.196716 18.196716 17.223601 18.884766 16.056641 L 18.363281 15.535156 L 18.144531 15.316406 A 7 7 0 0 0 18.689453 14 L 18.701172 14 L 19.734375 14 C 19.907004 13.34721 19.996 12.67521 20 12 C 19.9981 11.32505 19.91085 10.65304 19.740234 10 L 18.705078 10 L 18.691406 10 A 7 7 0 0 0 18.144531 8.6835938 L 18.363281 8.4648438 L 18.884766 7.9433594 C 18.196716 6.7764094 17.223591 5.8032844 16.056641 5.1152344 L 15.324219 5.8476562 L 15.316406 5.8554688 A 7 7 0 0 0 14 5.3105469 L 14 5.2988281 L 14 4.265625 C 13.34721 4.092995 12.67521 4.004 12 4 z M 12 5 C 12.33491 5.0012 12.66956 5.0273719 13 5.0761719 L 13 5.0800781 L 13 6 L 13 6.0859375 A 6 6 0 0 1 15.470703 7.1152344 L 15.535156 7.0507812 L 16.185547 6.4003906 L 16.1875 6.3984375 C 16.72484 6.7991075 17.201446 7.2742469 17.603516 7.8105469 L 17.599609 7.8144531 L 16.949219 8.4648438 L 16.886719 8.5273438 A 6 6 0 0 1 17.910156 11 L 18 11 L 18.921875 11 L 18.925781 11 C 18.974081 11.33106 18.9995 11.66455 19 12 C 18.9988 12.33491 18.972628 12.66955 18.923828 13 L 18.919922 13 L 18 13 L 17.914062 13 A 6 6 0 0 1 16.884766 15.470703 L 16.949219 15.535156 L 17.599609 16.185547 L 17.601562 16.1875 C 17.200893 16.72484 16.725753 17.201456 16.189453 17.603516 L 16.185547 17.599609 L 15.535156 16.949219 L 15.472656 16.886719 A 6 6 0 0 1 13 17.910156 L 13 18 L 13 18.921875 L 13 18.925781 C 12.66894 18.974081 12.33545 18.9995 12 19 C 11.66455 18.9995 11.33106 18.974081 11 18.925781 L 11 18.921875 L 11 18 L 11 17.910156 A 6 6 0 0 1 8.5273438 16.886719 L 8.4648438 16.949219 L 7.8144531 17.599609 L 7.8105469 17.603516 C 7.2742507 17.201463 6.7991075 16.72484 6.3984375 16.1875 L 6.4003906 16.185547 L 7.0507812 15.535156 L 7.1152344 15.470703 A 6 6 0 0 1 6.0859375 13 L 6 13 L 5.0800781 13 L 5.0761719 13 C 5.0273719 12.66955 5.0012 12.33491 5 12 C 5.0005 11.66455 5.0259187 11.33106 5.0742188 11 L 5.078125 11 L 6 11 L 6.0898438 11 A 6 6 0 0 1 7.1132812 8.5273438 L 7.0507812 8.4648438 L 6.4003906 7.8144531 L 6.3964844 7.8105469 C 6.7985582 7.2742507 7.27516 6.7991075 7.8125 6.3984375 L 7.8144531 6.4003906 L 8.4648438 7.0507812 L 8.5292969 7.1152344 A 6 6 0 0 1 11 6.0859375 L 11 6 L 11 5.0800781 L 11 5.0761719 C 11.33044 5.0273719 11.66509 5.0012 12 5 z M 10 9 L 10 15 L 15 12 L 10 9 z "
|
||||||
|
class="ColorScheme-Text"
|
||||||
|
/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
11
src/scripts/runaction/metadata.desktop
Normal file
11
src/scripts/runaction/metadata.desktop
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Run Action
|
||||||
|
Comment=Run various actions on sites
|
||||||
|
|
||||||
|
Icon=icon.svg
|
||||||
|
Type=Service
|
||||||
|
|
||||||
|
X-Falkon-Author=David Rosca
|
||||||
|
X-Falkon-Email=nowrep@gmail.com
|
||||||
|
X-Falkon-Version=0.1.0
|
||||||
|
X-Falkon-Settings=true
|
70
src/scripts/runaction/runaction.py
Normal file
70
src/scripts/runaction/runaction.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
import Falkon
|
||||||
|
from PySide2 import QtCore
|
||||||
|
from runaction import actionmanager, button
|
||||||
|
|
||||||
|
class RunActionPlugin(Falkon.PluginInterface, QtCore.QObject):
|
||||||
|
buttons = {}
|
||||||
|
manager = None
|
||||||
|
|
||||||
|
def init(self, state, settingsPath):
|
||||||
|
plugins = Falkon.MainApplication.instance().plugins()
|
||||||
|
plugins.mainWindowCreated.connect(self.mainWindowCreated)
|
||||||
|
plugins.mainWindowDeleted.connect(self.mainWindowDeleted)
|
||||||
|
|
||||||
|
self.manager = actionmanager.ActionManager(settingsPath)
|
||||||
|
|
||||||
|
if state == Falkon.PluginInterface.LateInitState:
|
||||||
|
for window in Falkon.MainApplication.instance().windows():
|
||||||
|
self.mainWindowCreated(window)
|
||||||
|
|
||||||
|
def unload(self):
|
||||||
|
for window in Falkon.MainApplication.instance().windows():
|
||||||
|
self.mainWindowDeleted(window)
|
||||||
|
|
||||||
|
self.manager = None
|
||||||
|
|
||||||
|
def testPlugin(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def populateWebViewMenu(self, menu, view, r):
|
||||||
|
for action in self.manager.getActions(view, r):
|
||||||
|
if action.inherits("QMenu"):
|
||||||
|
menu.addMenu(action).setParent(menu)
|
||||||
|
else:
|
||||||
|
action.setParent(menu)
|
||||||
|
menu.addAction(action)
|
||||||
|
|
||||||
|
def showSettings(self, parent):
|
||||||
|
self.manager.showSettings(parent)
|
||||||
|
|
||||||
|
def mainWindowCreated(self, window):
|
||||||
|
b = button.RunActionButton(self.manager)
|
||||||
|
window.statusBar().addButton(b)
|
||||||
|
window.navigationBar().addToolButton(b)
|
||||||
|
self.buttons[window] = b
|
||||||
|
|
||||||
|
def mainWindowDeleted(self, window):
|
||||||
|
if not window in self.buttons: return
|
||||||
|
b = self.buttons[window]
|
||||||
|
window.statusBar().removeButton(b)
|
||||||
|
window.navigationBar().removeToolButton(b)
|
||||||
|
del self.buttons[window]
|
||||||
|
|
||||||
|
Falkon.registerPlugin(RunActionPlugin())
|
47
src/scripts/runaction/settings.ui
Normal file
47
src/scripts/runaction/settings.ui
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>RunActionSettings</class>
|
||||||
|
<widget class="QWidget" name="RunActionSettings">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>544</width>
|
||||||
|
<height>492</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listWidget">
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="uniformItemSizes">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
58
src/scripts/runaction/settingsdialog.py
Normal file
58
src/scripts/runaction/settingsdialog.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# ============================================================
|
||||||
|
# RunAction plugin for Falkon
|
||||||
|
# Copyright (C) 2018 David Rosca <nowrep@gmail.com>
|
||||||
|
#
|
||||||
|
# This program 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.
|
||||||
|
#
|
||||||
|
# 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
# ============================================================
|
||||||
|
import Falkon
|
||||||
|
import os
|
||||||
|
from PySide2 import QtCore, QtGui, QtWidgets, QtUiTools
|
||||||
|
from runaction.i18n import i18n
|
||||||
|
|
||||||
|
class SettingsDialog(QtWidgets.QDialog):
|
||||||
|
def __init__(self, manager, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.manager = manager
|
||||||
|
|
||||||
|
file = QtCore.QFile(os.path.join(os.path.dirname(__file__), "settings.ui"))
|
||||||
|
file.open(QtCore.QFile.ReadOnly)
|
||||||
|
self.ui = QtUiTools.QUiLoader().load(file, self)
|
||||||
|
layout = QtWidgets.QVBoxLayout(self)
|
||||||
|
layout.addWidget(self.ui)
|
||||||
|
|
||||||
|
self.setMinimumSize(400, 250)
|
||||||
|
self.setWindowTitle(i18n("Run Action Settings"))
|
||||||
|
self.ui.label.setText("<b>{}</b>".format(i18n("Available actions")))
|
||||||
|
|
||||||
|
for action in self.manager.actions:
|
||||||
|
item = QtWidgets.QListWidgetItem(self.ui.listWidget)
|
||||||
|
item.setText(action.title)
|
||||||
|
item.setIcon(action.icon)
|
||||||
|
item.setData(QtCore.Qt.UserRole, action.id)
|
||||||
|
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
|
||||||
|
item.setCheckState(QtCore.Qt.Unchecked if action.id in self.manager.disabledActions else QtCore.Qt.Checked)
|
||||||
|
self.ui.listWidget.addItem(item)
|
||||||
|
|
||||||
|
self.ui.buttonBox.accepted.connect(self.accept)
|
||||||
|
self.ui.buttonBox.rejected.connect(self.reject)
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
disabled = []
|
||||||
|
for i in range(self.ui.listWidget.count()):
|
||||||
|
item = self.ui.listWidget.item(i)
|
||||||
|
if item.checkState() == QtCore.Qt.Unchecked:
|
||||||
|
disabled.append(item.data(QtCore.Qt.UserRole))
|
||||||
|
self.manager.disabledActions = disabled
|
||||||
|
super().accept()
|
Loading…
Reference in New Issue
Block a user