commit 3f55fd0eb94f69acf4888e14e8c3398eed39d07e Author: Juraj Oravec Date: Wed May 15 19:42:17 2019 +0200 Initial commit Signed-off-by: Juraj Oravec diff --git a/autoZoomer/__init__.py b/autoZoomer/__init__.py new file mode 100644 index 0000000..bea6199 --- /dev/null +++ b/autoZoomer/__init__.py @@ -0,0 +1,75 @@ +# ============================================================ +# Auto Zoomer - 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 +from autoZoomer.autoZoomer import AutoZoomer +from autoZoomer.button import AutoZoomerButton + + +class Zoomer_Plugin(Falkon.PluginInterface, QtCore.QObject): + manager = None + buttons = {} + + def init(self, state, settingsPath): + plugins = Falkon.MainApplication.instance().plugins() + + plugins.mainWindowCreated.connect(self.mainWindowCreated) + plugins.mainWindowDeleted.connect(self.mainWindowDeleted) + + plugins.webPageCreated.connect(self.onWebPageCreated) + + if state == Falkon.PluginInterface.LateInitState: + for window in Falkon.MainApplication.instance().windows(): + self.mainWindowCreated(window) + + self.manager = AutoZoomer(settingsPath) + + def unload(self): + self.manager.saveSettings() + self.mainWindowDeleted(self.window) + + def testPlugin(self): + return True + + def showSettings(self, parent): + self.manager.showSettings(parent) + + def mainWindowCreated(self, window): + b = AutoZoomerButton(self.manager) + window.statusBar().addButton(b) + window.navigationBar().addToolButton(b) + self.buttons[window] = b + + def mainWindowDeleted(self, window): + if window not in self.buttons: + return + + b = self.buttons[window] + window.statusBar().removeButton(b) + window.navigationBar().removeToolButton(b) + del self.buttons[window] + + def onWebPageCreated(self, page): + def onLoadFinished(ok): + self.manager.onLoadFinished(page) + + page.loadFinished.connect(onLoadFinished) + + +Falkon.registerPlugin(Zoomer_Plugin()) diff --git a/autoZoomer/autoZoomer.py b/autoZoomer/autoZoomer.py new file mode 100644 index 0000000..c9a7e42 --- /dev/null +++ b/autoZoomer/autoZoomer.py @@ -0,0 +1,107 @@ +# ============================================================ +# Auto Zoomer - 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, QtWidgets +from autoZoomer.settingsDialog import SettingsDialog +from autoZoomer.str2bool import str2bool + +class AutoZoomer(QtCore.QObject): + data = None + remove = None + config = None + + def __init__(self, settingsPath, parent=None): + super().__init__(parent) + + self.config = { + "settingsFile": os.path.join(settingsPath, "autoZoomer", "settings.ini"), + "active": True + } + self.data = {} + self.remove = [] + + self.loadSettings() + + def showSettings(self, parent=None): + settings = SettingsDialog(self.config, self.data, self.remove, parent) + settings.exec_() + + self.saveSettings() + + def loadSettings(self): + settings = QtCore.QSettings(self.config["settingsFile"], QtCore.QSettings.IniFormat) + + settings.beginGroup("AutoZoomer") + self.config["active"] = str2bool(settings.value("active", True)) + settings.endGroup() + + for group in settings.childGroups(): + if group == "AutoZoomer": + continue + + settings.beginGroup(group) + self.data[group] = { + "active": str2bool(settings.value("active", False)), + "zoom": int(settings.value("zoom", 6)) + } + settings.endGroup() + + def saveSettings(self): + settings = QtCore.QSettings(self.config["settingsFile"], QtCore.QSettings.IniFormat) + + settings.beginGroup("AutoZoomer") + settings.setValue("active", self.config["active"]) + settings.endGroup() + + for host in self.remove: + settings.remove(host) + self.remove.clear() + + for key, value in self.data.items(): + settings.beginGroup(key) + settings.setValue("active", value["active"]) + settings.setValue("zoom", value["zoom"]) + settings.endGroup() + + settings.sync() + + def onLoadFinished(self, page): + if not self.config["active"]: + return + + view = page.view() + host = page.url().host() + + if host in self.data.keys(): + if self.data[host]["active"]: + view.setZoomLevel(self.data[host]["zoom"]) + + def addItem(self, host, zoom=6, active=True): + if not host: + return + + if host in self.data.keys(): + self.data[host]["zoom"] = zoom + self.data[host]["active"] = active + else: + self.data[host] = { + "active": active, + "zoom": zoom + } diff --git a/autoZoomer/button.py b/autoZoomer/button.py new file mode 100644 index 0000000..4adb5e1 --- /dev/null +++ b/autoZoomer/button.py @@ -0,0 +1,47 @@ +# ============================================================ +# Auto Zoomer - 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 AutoZoomerButton(Falkon.AbstractButtonInterface): + manager = None + + def __init__(self, manager): + super().__init__() + self.manager = manager + + self.setIcon(QtGui.QIcon(os.path.join(os.path.dirname(__file__), "icon.svg"))) + self.setTitle("Auto Zoomer") + self.setToolTip("Save current zoom level") + + self.clicked.connect(self.onClicked) + + def id(self): + return "auto-zoomer-button" + + def name(self): + return "Auto Zoomer button" + + def onClicked(self, controller): + host = self.webView().page().url().host() + zoom = self.webView().zoomLevel() + + self.manager.addItem(host=host, zoom=zoom) diff --git a/autoZoomer/icon.svg b/autoZoomer/icon.svg new file mode 100644 index 0000000..7706a12 --- /dev/null +++ b/autoZoomer/icon.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + Z + diff --git a/autoZoomer/listItem.py b/autoZoomer/listItem.py new file mode 100644 index 0000000..ae4a1cd --- /dev/null +++ b/autoZoomer/listItem.py @@ -0,0 +1,57 @@ +# ============================================================ +# Auto Zoomer - 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 os +from PySide2 import QtCore, QtWidgets, QtUiTools + + +class ListItem(QtWidgets.QWidget): + ui = None + + def __init__(self, parent=None): + super().__init__(parent) + + file = QtCore.QFile(os.path.join(os.path.dirname(__file__), "listItem.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) + + def active(self): + return self.ui.checkBoxActive.isChecked() + + def host(self): + return self.ui.labelHost.text() + + def zoom(self): + return self.ui.spinBoxZoomLevel.value() + + def setActive(self, active): + active = bool(active) + self.ui.checkBoxActive.setChecked(active) + + def setHost(self, host): + host = str(host) + self.ui.labelHost.setText(host) + + def setZoom(self, zoom): + zoom = int(zoom) + self.ui.spinBoxZoomLevel.setValue(zoom) diff --git a/autoZoomer/listItem.ui b/autoZoomer/listItem.ui new file mode 100644 index 0000000..5fff85e --- /dev/null +++ b/autoZoomer/listItem.ui @@ -0,0 +1,55 @@ + + + Form + + + + 0 + 0 + 354 + 30 + + + + Form + + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + + + + + + + + + + + + Host + + + + + + + 18 + + + + + + + + + + diff --git a/autoZoomer/metadata.desktop b/autoZoomer/metadata.desktop new file mode 100644 index 0000000..f720427 --- /dev/null +++ b/autoZoomer/metadata.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Auto Zoomer +Comment=Remember zoom level per site + +Type=Service +X-Falkon-Type=Extension/Python + +X-Falkon-Author=Juraj Oravec +X-Falkon-Email=sgd.orava@gmail.com +X-Falkon-Version=1.0.0 +X-Falkon-Settings=true diff --git a/autoZoomer/settings.ui b/autoZoomer/settings.ui new file mode 100644 index 0000000..843d9d2 --- /dev/null +++ b/autoZoomer/settings.ui @@ -0,0 +1,128 @@ + + + SettingsDialog + + + + 0 + 0 + 379 + 334 + + + + Auto Zoomer Settings + + + + + + + + + + + www.example.com + + + true + + + + + + + 18 + + + 6 + + + + + + + + + + + QAbstractScrollArea::AdjustIgnored + + + true + + + QAbstractItemView::ScrollPerPixel + + + true + + + true + + + + + + + + + Add + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Enable AutoZoomer + + + + + + + false + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + pushButtonAdd + pushButtonRemove + listWidget + checkBoxEnableAutoZoomer + + + + diff --git a/autoZoomer/settingsDialog.py b/autoZoomer/settingsDialog.py new file mode 100644 index 0000000..0459bef --- /dev/null +++ b/autoZoomer/settingsDialog.py @@ -0,0 +1,138 @@ +# ============================================================ +# Auto Zoomer - 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 os +from PySide2 import QtCore, QtWidgets, QtUiTools +from autoZoomer.listItem import ListItem +from autoZoomer.i18n import i18n + + +class SettingsDialog(QtWidgets.QDialog): + ui = None + data = None + remove = None + prepareRemove = None + config = None + + def __init__(self, config, data, remove, parent=None): + super().__init__(parent) + + self.config = config + self.data = data + self.remove = remove + self.prepareRemove = [] + + file = QtCore.QFile(os.path.join(os.path.dirname(__file__), "settings.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.ui.checkBoxEnableAutoZoomer.setChecked(self.config["active"]) + + for key, value in self.data.items(): + widget = ListItem() + widget.setHost(key) + widget.setActive(value["active"]) + widget.setZoom(value["zoom"]) + + item = QtWidgets.QListWidgetItem(self.ui.listWidget) + item.setSizeHint(widget.sizeHint() * 1.2) + self.ui.listWidget.setItemWidget(item, widget) + + self.ui.pushButtonRemove.clicked.connect(self.handleItemRemove) + self.ui.pushButtonAdd.clicked.connect(self.handleItemAdd) + + self.ui.buttonBoxConfirm.accepted.connect(self.accept) + self.ui.buttonBoxConfirm.rejected.connect(self.reject) + + def addListItem(self, host, zoom=6, active=True): + if not host: + return + + if host in self.data.keys(): + for i in range(0, self.ui.listWidget.count()): + item = self.ui.listWidget.item(i) + widget = self.ui.listWidget.itemWidget(item) + + if widget.host() == host: + widget.setActive(active) + widget.setZoom(zoom) + + break + else: + widget = ListItem() + widget.setHost(host) + widget.setActive(active) + widget.setZoom(zoom) + + item = QtWidgets.QListWidgetItem(self.ui.listWidget) + item.setSizeHint(widget.sizeHint() * 1.2) + self.ui.listWidget.setItemWidget(item, widget) + + def updateData(self): + self.config["active"] = self.ui.checkBoxEnableAutoZoomer.isChecked() + + self.data.clear() + + for i in range(0, self.ui.listWidget.count()): + item = self.ui.listWidget.item(i) + widget = self.ui.listWidget.itemWidget(item) + + self.data[widget.host()] = { + "active": widget.active(), + "zoom": widget.zoom() + } + + self.remove.clear() + + for host in self.prepareRemove: + self.remove.append(host) + + self.prepareRemove.clear() + + def handleItemAdd(self): + host = self.ui.lineEditNew.text() + zoom = self.ui.spinBoxNew.value() + + if not host: + return + + self.ui.lineEditNew.clear() + + self.addListItem(host, zoom=zoom) + + def handleItemRemove(self): + listWidget = self.ui.listWidget + itemList = listWidget.selectedItems() + + if not itemList: + return + + self.prepareRemove.append(listWidget.itemWidget(itemList[-1]).host()) + + listWidget.takeItem(listWidget.row(itemList[-1])) + + def accept(self): + self.updateData() + + super().accept() + self.close() diff --git a/autoZoomer/str2bool.py b/autoZoomer/str2bool.py new file mode 100644 index 0000000..f55392f --- /dev/null +++ b/autoZoomer/str2bool.py @@ -0,0 +1,55 @@ +"""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)