diff --git a/.gitignore b/.gitignore index 8adad6f..c4c4ffc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ *.zip -package diff --git a/Messages.sh b/Messages.sh deleted file mode 100644 index cc2bcff..0000000 --- a/Messages.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/sh - -XGETTEXT_FLAGS_PYTHON="\ ---copyright-holder=This_file_is_part_of_KDE \ ---msgid-bugs-address=http://bugs.kde.org \ ---from-code=UTF-8 \ --L Python \ --ki18n:1 -ki18np:1,2 \ -" - -$XGETTEXT_PROGRAM $XGETTEXT_FLAGS_PYTHON `find ./readability -name '*.py'` -o $podir/readability.pot diff --git a/readability/JsObject.py b/readability/JsObject.py deleted file mode 100644 index 29d5c99..0000000 --- a/readability/JsObject.py +++ /dev/null @@ -1,59 +0,0 @@ -# Readability - plugin for Falkon -# Copyright (C) 2019 Juraj Oravec -# -# 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 . - -import Falkon -from PySide2 import QtCore, QtGui - - -class JsObject(QtCore.QObject): - config = None - - configChanged = QtCore.Signal() - - def __init__(self, config, parent=None): - super().__init__(parent) - - self.config = config - - @QtCore.Slot(str) - def setColorTheme(self, colorTheme): - if colorTheme not in ("light", "sepia", "dark"): - return - - if self.config["colorTheme"] != colorTheme: - self.config["colorTheme"] = colorTheme - - self.configChanged.emit() - - @QtCore.Slot(str) - def setFont(self, font): - if font not in ("sans-serif", "serif"): - return - - if self.config["font"] != font: - self.config["font"] = font - - self.configChanged.emit() - - @QtCore.Slot(int) - def setFontSize(self, fontSize): - if fontSize < 1 and fontSize > 9: - return - - if self.config["fontSize"] != fontSize: - self.config["fontSize"] = fontSize - - self.configChanged.emit() diff --git a/readability/__init__.py b/readability/__init__.py deleted file mode 100644 index 7fb8d5b..0000000 --- a/readability/__init__.py +++ /dev/null @@ -1,216 +0,0 @@ -# Readability - plugin for Falkon -# Copyright (C) 2019 Juraj Oravec -# -# 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 . - -import Falkon -import os -from PySide2 import QtCore, QtGui -from readability.settingsDialog import SettingsDialog -from readability.button import Button -from readability.str2bool import str2bool -from readability.JsObject import JsObject - - -class Readability(Falkon.PluginInterface, QtCore.QObject): - config = None - view = None - buttons = None - jsObject = None - - style = "" - scriptReadability = "" - scriptToolbar = "" - scriptCall = "" - - def init(self, state, settingsPath): - self.config = { - "settingsFile": os.path.join(settingsPath, "readability", "settings.ini"), - "icon": "dark", - "contextMenu": False, - "colorTheme": "sepia", - "font": "sans-serif", - "fontSize": 5 - } - self.buttons = {} - self.loadSettings() - self.onConfigUpdate() - - self.jsObject = JsObject(self.config, self) - self.jsObject.configChanged.connect(self.saveSettings) - - Falkon.ExternalJsObject.registerExtraObject("readability", self.jsObject) - - plugins = Falkon.MainApplication.instance().plugins() - - plugins.mainWindowCreated.connect(self.onMainWindowCreated) - plugins.mainWindowDeleted.connect(self.onMainWindowDeleted) - - if state == Falkon.PluginInterface.LateInitState: - for window in Falkon.MainApplication.instance().windows(): - self.onMainWindowCreated(window) - - def unload(self): - for window in Falkon.MainApplication.instance().windows(): - self.onMainWindowDeleted(window) - - Falkon.ExternalJsObject.unregisterExtraObject(self.jsObject) - - def testPlugin(self): - return True - - def onMainWindowCreated(self, window): - button = Button(self.config["icon"]) - button.clicked.connect(lambda: self.makeReadability(button.webView())) - - window.navigationBar().addToolButton(button) - self.buttons[window] = button - - def onMainWindowDeleted(self, window): - if window not in self.buttons: - return - - button = self.buttons[window] - window.navigationBar().removeToolButton(button) - del self.buttons[window] - - def populateWebViewMenu(self, menu, view, hitTestResult): - if not self.config["contextMenu"]: - return - - self.view = view - - if (hitTestResult.imageUrl().isEmpty() - and hitTestResult.linkUrl().isEmpty() - and hitTestResult.mediaUrl().isEmpty() - and not hitTestResult.isContentEditable() - and not hitTestResult.isContentSelected()): - icon = "icon-light.png" if self.config["icon"] == "light" else "icon-dark.png" - menu.addAction( - QtGui.QIcon(os.path.join(os.path.dirname(__file__), "data", icon)), - "Readability", - self.makeReadability - ) - - def loadStyle(self): - dataDir = os.path.join(os.path.dirname(__file__), "data") - - iconClose = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-close.png")) - ).toString() - iconCloseHover = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-close-hover.png")) - ).toString() - iconDelete = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-Delete-24x24.png")) - ).toString() - iconPlus = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-Plus-24x24.png")) - ).toString() - iconMinus = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-Minus-24x24.png")) - ).toString() - iconArrow = Falkon.QzTools.readAllFileContents( - os.path.join(dataDir, "RM-Type-Controls-Arrow.png") - ) - iconControls = Falkon.QzTools.pixmapToDataUrl( - QtGui.QPixmap(os.path.join(dataDir, "RM-Type-Controls-24x24.png")) - ).toString() - - css = Falkon.QzTools.readAllFileContents( - os.path.join(dataDir, "style.css") - ).replace("\n", "") - css = css.replace("{iconClose}", iconClose) - css = css.replace("{iconCloseHover}", iconCloseHover) - css = css.replace("{iconDelete}", iconDelete) - css = css.replace("{iconPlus}", iconPlus) - css = css.replace("{iconMinus}", iconMinus) - css = css.replace("{iconArrow}", iconArrow) - css = css.replace("{iconControls}", iconControls) - - return css - - def makeReadability(self, view=None): - if view: - self.view = view - - dataDir = os.path.join(os.path.dirname(__file__), "data") - - if not self.style: - self.style = self.loadStyle() - if not self.scriptReadability: - self.scriptReadability = Falkon.QzTools.readAllFileContents( - os.path.join(dataDir, "Readability.js") - ) - if not self.scriptToolbar: - self.scriptToolbar = Falkon.QzTools.readAllFileContents( - os.path.join(dataDir, "Toolbar.js") - ) - if not self.scriptCall: - self.scriptCall = Falkon.QzTools.readAllFileContents( - os.path.join(dataDir, "Call.js") - ) - self.scriptCall = self.scriptCall.replace("{readability.js}", self.scriptReadability) - self.scriptCall = self.scriptCall.replace("{toolbar.js}", self.scriptToolbar) - self.scriptCall = self.scriptCall.replace("{style.css}", self.style) - - initConfigScript = "initConfig('{}', '{}', {});".format( - self.config["colorTheme"], - self.config["font"], - self.config["fontSize"] - ) - - self.view.page().runJavaScript( - self.scriptCall + initConfigScript, - Falkon.WebPage.SafeJsWorld - ) - - def showSettings(self, parent): - settings = SettingsDialog(self.config, parent) - settings.accepted.connect(self.saveSettings) - settings.accepted.connect(self.onConfigUpdate) - settings.exec_() - - def saveSettings(self): - settings = QtCore.QSettings(self.config["settingsFile"], QtCore.QSettings.IniFormat) - - settings.beginGroup("Readability") - settings.setValue("icon", self.config["icon"]) - settings.setValue("showInContextMenu", self.config["contextMenu"]) - settings.setValue("colorTheme", self.config["colorTheme"]) - settings.setValue("font", self.config["font"]) - settings.setValue("fontSize", self.config["fontSize"]) - settings.endGroup() - - settings.sync() - - def loadSettings(self): - settings = QtCore.QSettings(self.config["settingsFile"], QtCore.QSettings.IniFormat) - - settings.beginGroup("Readability") - self.config["icon"] = str(settings.value("icon", self.config["icon"])) - self.config["contextMenu"] = str2bool( - settings.value("showInContextMenu", self.config["contextMenu"]) - ) - self.config["colorTheme"] = str(settings.value("colorTheme", self.config["colorTheme"])) - self.config["font"] = str(settings.value("font", self.config["font"])) - self.config["fontSize"] = int(settings.value("fontSize", self.config["fontSize"])) - settings.endGroup() - - def onConfigUpdate(self): - for _, button in self.buttons.items(): - button.updateIcon(self.config["icon"]) - - -Falkon.registerPlugin(Readability()) diff --git a/readability/button.py b/readability/button.py deleted file mode 100644 index 9c42106..0000000 --- a/readability/button.py +++ /dev/null @@ -1,48 +0,0 @@ -# Readability - plugin for Falkon -# Copyright (C) 2019 Juraj Oravec -# -# 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 . - -import Falkon -import os -from PySide2 import QtGui - - -class Button(Falkon.AbstractButtonInterface): - def __init__(self, iconStyle): - super().__init__() - - icon = "icon-light.png" if iconStyle == "light" else "icon-dark.png" - self.setIcon(QtGui.QIcon( - os.path.join(os.path.dirname(__file__), "data", icon)) - ) - self.setTitle("Button") - self.setToolTip("Activate Readability") - - self.clicked.connect(self.onClicked) - - def id(self): - return "readability-button" - - def name(self): - return "Readability" - - def onClicked(self, controller): - pass - - def updateIcon(self, iconStyle): - icon = "icon-light.png" if iconStyle == "light" else "icon-dark.png" - self.setIcon(QtGui.QIcon( - os.path.join(os.path.dirname(__file__), "data", icon)) - ) diff --git a/readability/i18n.py b/readability/i18n.py deleted file mode 100644 index 3db8440..0000000 --- a/readability/i18n.py +++ /dev/null @@ -1,40 +0,0 @@ -# ============================================================ -# Falkon - Qt web browser -# Copyright (C) 2018 David Rosca -# Copyright (C) 2019 Juraj Oravec -# -# 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 . -# ============================================================ -import gettext -import os -from PySide2 import QtCore - -locale = QtCore.QLocale.system() -languages = [ - locale.name(), - locale.bcp47Name() -] -i = locale.name().find('_') -if i > 0: - languages.append(locale.name()[:i]) - -localedir = QtCore.QStandardPaths.locate( - QtCore.QStandardPaths.GenericDataLocation, - os.path.join(os.path.dirname(__file__), "locale"), - QtCore.QStandardPaths.LocateDirectory -) - -t = gettext.translation(__package__, localedir, languages, fallback=True) -i18n = t.gettext -i18np = t.ngettext diff --git a/readability/settingsDialog.py b/readability/settingsDialog.py deleted file mode 100644 index 4087fef..0000000 --- a/readability/settingsDialog.py +++ /dev/null @@ -1,101 +0,0 @@ -# ============================================================ -# Readability - plugin for Falkon -# Copyright (C) 2019 Juraj Oravec -# -# 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 . -# ============================================================ - -import Falkon -import os -from PySide2 import QtCore, QtWidgets, QtUiTools -from readability.i18n import i18n - - -class SettingsDialog(QtWidgets.QDialog): - ui = None - config = None - - def __init__(self, config, parent=None): - super().__init__(parent) - - self.config = config - - file = QtCore.QFile(os.path.join(os.path.dirname(__file__), "settingsDialog.ui")) - file.open(QtCore.QFile.ReadOnly) - self.ui = QtUiTools.QUiLoader().load(file, self) - file.close() - - layout = QtWidgets.QVBoxLayout(self) - layout.addWidget(self.ui) - self.setLayout(layout) - - self.translations() - self.applyConfig() - - self.ui.buttonBoxConfirm.accepted.connect(self.accept) - self.ui.buttonBoxConfirm.rejected.connect(self.reject) - - def applyConfig(self): - self.ui.radioButtonLight.setChecked(self.config["icon"] == "light") - self.ui.radioButtonDark.setChecked(self.config["icon"] == "dark") - - self.ui.radioButtonSchemeLight.setChecked(self.config["colorTheme"] == "light") - self.ui.radioButtonSchemeSepia.setChecked(self.config["colorTheme"] == "sepia") - self.ui.radioButtonSchemeDark.setChecked(self.config["colorTheme"] == "dark") - - self.ui.radioButtonFontSansSerif.setChecked(self.config["font"] == "sans-serif") - self.ui.radioButtonFontSerif.setChecked(self.config["font"] == "serif") - - self.ui.comboBoxFontSize.setCurrentIndex(self.config["fontSize"] - 1) - - self.ui.checkBoxContextMenu.setChecked(self.config["contextMenu"]) - - def translations(self): - self.setWindowTitle(i18n("Readability Settings")) - - self.ui.groupBoxIcon.setTitle(i18n("Menu icon")) - self.ui.radioButtonLight.setText(i18n("Light")) - self.ui.radioButtonDark.setText(i18n("Dark")) - - self.ui.groupBoxColorScheme.setTitle(i18n("Color scheme")) - self.ui.radioButtonSchemeLight.setText(i18n("Light")) - self.ui.radioButtonSchemeSepia.setText(i18n("Sepia")) - self.ui.radioButtonSchemeDark.setText(i18n("Dark")) - - self.ui.groupBoxFont.setTitle(i18n("Font")) - self.ui.radioButtonFontSansSerif.setText(i18n("Sans-Serif")) - self.ui.radioButtonFontSerif.setText(i18n("Serif")) - self.ui.labelFontSize.setText(i18n("Font size:")) - - self.ui.checkBoxContextMenu.setText(i18n("Show in context menu")) - - def updateData(self): - self.config["icon"] = "light" if self.ui.radioButtonLight.isChecked() else "dark" - - if self.ui.radioButtonSchemeLight.isChecked(): - self.config["colorTheme"] = "light" - elif self.ui.radioButtonSchemeSepia.isChecked(): - self.config["colorTheme"] = "sepia" - else: - self.config["colorTheme"] = "dark" - - self.config["font"] = "sans-serif" if self.ui.radioButtonFontSansSerif.isChecked() else "serif" - self.config["fontSize"] = self.ui.comboBoxFontSize.currentIndex() + 1 - - self.config["contextMenu"] = self.ui.checkBoxContextMenu.isChecked() - - def accept(self): - self.updateData() - - super().accept() diff --git a/readability/settingsDialog.ui b/readability/settingsDialog.ui deleted file mode 100644 index dc73889..0000000 --- a/readability/settingsDialog.ui +++ /dev/null @@ -1,182 +0,0 @@ - - - Form - - - - 0 - 0 - 350 - 344 - - - - Readability Settings - - - - - - - - - - true - - - Menu icon - - - - - - Light - - - - - - - Dark - - - - - - - - - - Color scheme - - - - - - Light - - - - - - - Sepia - - - - - - - Dark - - - - - - - - - - - - Font - - - - - - Sans-Serif - - - - - - - Serif - - - - - - - - - Font size: - - - - - - - - 10 px - - - - - 12 px - - - - - 14 px - - - - - 16 px - - - - - 18 px - - - - - 20 px - - - - - 22 px - - - - - 24 px - - - - - 26 px - - - - - - - - - - - - - Show in context menu - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - diff --git a/readability/str2bool.py b/readability/str2bool.py deleted file mode 100644 index 5490522..0000000 --- a/readability/str2bool.py +++ /dev/null @@ -1,55 +0,0 @@ -"""BSD 3-Clause License - -Copyright (c) 2017, SymonSoft -Copyright (c) 2019, Juraj Oravec -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.""" - -import sys - -_true_set = {'yes', 'true', 't', 'y', '1'} -_false_set = {'no', 'false', 'f', 'n', '0'} - - -def str2bool(value, raise_exc=False): - if isinstance(value, bool): - return value - - if isinstance(value, str) or sys.version_info[0] < 3 and isinstance(value, basestring): - value = value.lower() - if value in _true_set: - return True - if value in _false_set: - return False - - if raise_exc: - raise ValueError('Expected "%s"' % '", "'.join(_true_set | _false_set)) - return None - - -def str2bool_exc(value): - return str2bool(value, raise_exc=True)