JezerM
3 years ago
8 changed files with 30 additions and 485 deletions
@ -1,144 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# |
|
||||||
# errorPrompt.py |
|
||||||
# |
|
||||||
# Copyright © 2021 JezerM |
|
||||||
# |
|
||||||
# This file is part of Web Greeter. |
|
||||||
# |
|
||||||
# Web Greeter 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. |
|
||||||
# |
|
||||||
# Web Greeter 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. |
|
||||||
# |
|
||||||
# The following additional terms are in effect as per Section 7 of the license: |
|
||||||
# |
|
||||||
# The preservation of all legal notices and author attributions in |
|
||||||
# the material or in the Appropriate Legal Notices displayed |
|
||||||
# by works containing it is required. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with Web Greeter; If not, see <http://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
from whither.toolkits.bootstrap import WebPage |
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QDialogButtonBox, QDialog, QVBoxLayout, QLabel, QPushButton |
|
||||||
|
|
||||||
from logging import ( |
|
||||||
getLogger, |
|
||||||
DEBUG, |
|
||||||
ERROR, |
|
||||||
Formatter, |
|
||||||
StreamHandler, |
|
||||||
) |
|
||||||
|
|
||||||
import globals |
|
||||||
|
|
||||||
log_format = ''.join([ |
|
||||||
'%(asctime)s [ %(levelname)s ] %(filename)s %(', |
|
||||||
'lineno)d: %(message)s' |
|
||||||
]) |
|
||||||
formatter = Formatter(fmt=log_format, datefmt="%Y-%m-%d %H:%M:%S") |
|
||||||
logger = getLogger("javascript") |
|
||||||
logger.propagate = False |
|
||||||
stream_handler = StreamHandler() |
|
||||||
stream_handler.setLevel(DEBUG) |
|
||||||
stream_handler.setFormatter(formatter) |
|
||||||
logger.setLevel(DEBUG) |
|
||||||
logger.addHandler(stream_handler) |
|
||||||
|
|
||||||
|
|
||||||
def javaScriptConsoleMessage(self, level: WebPage.JavaScriptConsoleMessageLevel, message: str, lineNumber: int, sourceID: str): |
|
||||||
if sourceID == "": |
|
||||||
sourceID = "console" |
|
||||||
|
|
||||||
logLevel = 0 |
|
||||||
if level == WebPage.JavaScriptConsoleMessageLevel.ErrorMessageLevel: |
|
||||||
logLevel = 40 |
|
||||||
elif level == WebPage.JavaScriptConsoleMessageLevel.WarningMessageLevel: |
|
||||||
logLevel = 30 |
|
||||||
elif level == WebPage.JavaScriptConsoleMessageLevel.InfoMessageLevel: |
|
||||||
return |
|
||||||
else: |
|
||||||
return |
|
||||||
|
|
||||||
record = logger.makeRecord( |
|
||||||
name="javascript", |
|
||||||
level=logLevel, |
|
||||||
fn="", |
|
||||||
lno=lineNumber, |
|
||||||
msg=message, |
|
||||||
args=(), |
|
||||||
exc_info=None |
|
||||||
) |
|
||||||
record.filename = sourceID |
|
||||||
logger.handle(record) |
|
||||||
|
|
||||||
if logLevel == 40: |
|
||||||
errorMessage = "{source} {line}: {msg}".format( |
|
||||||
source=sourceID, line=lineNumber, msg=message) |
|
||||||
errorPrompt(errorMessage) |
|
||||||
|
|
||||||
|
|
||||||
class ErrorDialog(QDialog): |
|
||||||
def __init__(self, parent=None, err=""): |
|
||||||
super().__init__(parent) |
|
||||||
|
|
||||||
self.setWindowTitle("Error") |
|
||||||
|
|
||||||
self.buttonBox = QDialogButtonBox() |
|
||||||
cancelBtn = QPushButton("Cancel") |
|
||||||
defaultBtn = QPushButton("Set default theme") |
|
||||||
reloadBtn = QPushButton("Reload theme") |
|
||||||
|
|
||||||
reloadBtn.clicked.connect(self.handle_reload) |
|
||||||
|
|
||||||
self.buttonBox.addButton(defaultBtn, QDialogButtonBox.ButtonRole.AcceptRole) |
|
||||||
self.buttonBox.addButton(reloadBtn, QDialogButtonBox.ButtonRole.ResetRole) |
|
||||||
self.buttonBox.addButton(cancelBtn, QDialogButtonBox.ButtonRole.RejectRole) |
|
||||||
|
|
||||||
self.buttonBox.accepted.connect(self.accept) |
|
||||||
self.buttonBox.rejected.connect(self.reject) |
|
||||||
|
|
||||||
self.layout = QVBoxLayout() |
|
||||||
message = QLabel("An error ocurred. Do you want to change to default theme?") |
|
||||||
err = QLabel(err) |
|
||||||
self.layout.addWidget(message) |
|
||||||
self.layout.addWidget(err) |
|
||||||
self.layout.addWidget(self.buttonBox) |
|
||||||
self.setLayout(self.layout) |
|
||||||
|
|
||||||
def handle_reload(self, value: bool): |
|
||||||
self.done(2) |
|
||||||
|
|
||||||
|
|
||||||
def errorPrompt(err): |
|
||||||
|
|
||||||
if not globals.greeter.config.greeter.detect_theme_errors: |
|
||||||
return |
|
||||||
|
|
||||||
dia = ErrorDialog(globals.greeter._main_window.widget.centralWidget(), err) |
|
||||||
|
|
||||||
dia.exec() |
|
||||||
result = dia.result() |
|
||||||
|
|
||||||
if result == 0: # Cancel |
|
||||||
return |
|
||||||
elif result == 1: # Default theme |
|
||||||
globals.custom_config["app"]["greeter"]["theme"] = "gruvbox" |
|
||||||
globals.greeter.get_and_apply_user_config() |
|
||||||
globals.greeter.load_theme() |
|
||||||
return |
|
||||||
elif result == 2: # Reload |
|
||||||
globals.greeter.load_theme() |
|
||||||
return |
|
||||||
|
|
||||||
return |
|
||||||
|
|
||||||
|
|
||||||
WebPage.javaScriptConsoleMessage = javaScriptConsoleMessage |
|
@ -1,37 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# |
|
||||||
# interceptor.py |
|
||||||
# |
|
||||||
# Copyright © 2016-2017 Antergos |
|
||||||
# |
|
||||||
# This file is part of whither. |
|
||||||
# |
|
||||||
# whither 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. |
|
||||||
# |
|
||||||
# whither 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. |
|
||||||
# |
|
||||||
# The following additional terms are in effect as per Section 7 of the license: |
|
||||||
# |
|
||||||
# The preservation of all legal notices and author attributions in |
|
||||||
# the material or in the Appropriate Legal Notices displayed |
|
||||||
# by works containing it is required. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with whither; If not, see <http://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
""" Url Request Interceptor """ |
|
||||||
|
|
||||||
# 3rd-Party Libs |
|
||||||
from whither.bridge import UrlRequestInterceptor as Interceptor |
|
||||||
|
|
||||||
|
|
||||||
class UrlRequestInterceptor(Interceptor): |
|
||||||
|
|
||||||
def intercept_request(self, info): |
|
||||||
self.interceptRequest(info) |
|
@ -1,133 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# |
|
||||||
# pkg_json.py |
|
||||||
# |
|
||||||
# Copyright © 2016-2017 Antergos |
|
||||||
# |
|
||||||
# This file is part of Web Greeter for LightDM. |
|
||||||
# |
|
||||||
# Web Greeter 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. |
|
||||||
# |
|
||||||
# Web Greeter 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. |
|
||||||
# |
|
||||||
# The following additional terms are in effect as per Section 7 of the license: |
|
||||||
# |
|
||||||
# The preservation of all legal notices and author attributions in |
|
||||||
# the material or in the Appropriate Legal Notices displayed |
|
||||||
# by works containing it is required. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with Web Greeter; If not, see <http://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
""" Utility class used to manage greeter themes' package.json files. """ |
|
||||||
|
|
||||||
# Standard Lib |
|
||||||
import json |
|
||||||
import os |
|
||||||
|
|
||||||
|
|
||||||
class MissingKeyError(KeyError): |
|
||||||
|
|
||||||
def __init__(self, keys: list): |
|
||||||
self.keys = keys |
|
||||||
msg_part = ' is' if len(keys) == 1 else 's are' |
|
||||||
msg = 'Required key{0} missing: {1}'.format(msg_part, keys) |
|
||||||
|
|
||||||
super().__init__(msg) |
|
||||||
|
|
||||||
|
|
||||||
class PackageJSON: |
|
||||||
""" |
|
||||||
Holds data from a theme's package.json file. |
|
||||||
|
|
||||||
Attributes: |
|
||||||
_optional_keys (tuple): Top-level keys that aren't required. |
|
||||||
_required_keys (tuple): Top-level keys that are required. |
|
||||||
_wg_theme_keys (tuple): Keys nested under `wg_theme` key. All are required. |
|
||||||
|
|
||||||
author (dict): Author's info. Required: `name`. Optional: `email`, `url`. |
|
||||||
bugs (str): Issue tracker url. |
|
||||||
config (dict): Theme configuration data. |
|
||||||
description (str): Short description. |
|
||||||
display_name (str): Display name. |
|
||||||
entry_point (str): Path to HTML file relative to theme's root directory. |
|
||||||
homepage (str): Homepage url. |
|
||||||
name (str): Package name. |
|
||||||
scripts (list): All JavaScript files required by the theme. Paths should be relative |
|
||||||
to the theme's root directory. Vendor scripts provided by the greeter |
|
||||||
should be listed by their name instead of file path. |
|
||||||
styles (list): All CSS files required by the theme. Paths should be relative |
|
||||||
to the theme's root directory. Vendor styles provided by the greeter |
|
||||||
should be listed by their name instead of file path. |
|
||||||
supports (list): List of greeter versions supported by the theme. The version format |
|
||||||
is MAJOR[.MINOR[.PATCH]] where MINOR and PATCH are optional. |
|
||||||
Examples: |
|
||||||
`3` : `2.9.9` < compatible versions < `4.0.0` |
|
||||||
`3.0` : `3` < compatible versions < `3.1` |
|
||||||
`3.0.1`: compatible version == `3.0.1` |
|
||||||
version (str): Theme version. |
|
||||||
""" |
|
||||||
_optional_keys = ( |
|
||||||
'config', |
|
||||||
'description', |
|
||||||
'name', |
|
||||||
) |
|
||||||
|
|
||||||
_required_keys = ( |
|
||||||
'author', |
|
||||||
'bugs', |
|
||||||
'homepage', |
|
||||||
'version', |
|
||||||
'wg_theme', |
|
||||||
) |
|
||||||
|
|
||||||
_wg_theme_keys = ( |
|
||||||
'display_name', |
|
||||||
'entry_point', |
|
||||||
'scripts', |
|
||||||
'styles', |
|
||||||
'supports', |
|
||||||
) |
|
||||||
|
|
||||||
def __init__(self, path: str) -> None: |
|
||||||
""" |
|
||||||
Args: |
|
||||||
path (str): Absolute path to `package.json` file. |
|
||||||
""" |
|
||||||
self.path = path |
|
||||||
|
|
||||||
self._initialize() |
|
||||||
|
|
||||||
def _initialize(self): |
|
||||||
package_json = os.path.join(self.path, 'package.json') |
|
||||||
|
|
||||||
if not os.path.exists(package_json): |
|
||||||
raise FileNotFoundError |
|
||||||
|
|
||||||
data = json.loads(package_json) |
|
||||||
missing_keys = [k for k in self._required_keys if k not in data] |
|
||||||
|
|
||||||
if missing_keys: |
|
||||||
raise MissingKeyError(missing_keys) |
|
||||||
|
|
||||||
if not isinstance(data['wg_theme'], dict): |
|
||||||
raise TypeError('wg_theme: Expected type(dict)!') |
|
||||||
|
|
||||||
missing_keys = [k for k in self._wg_theme_keys if k not in data['wg_theme']] |
|
||||||
|
|
||||||
if missing_keys: |
|
||||||
raise MissingKeyError(missing_keys) |
|
||||||
|
|
||||||
for key, value in data['wg_theme'].items(): |
|
||||||
setattr(self, key, value) |
|
||||||
|
|
||||||
del data['wg_theme'] |
|
||||||
|
|
||||||
for key, value in data.items(): |
|
||||||
setattr(self, key, value) |
|
@ -1,113 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# |
|
||||||
# theme.py |
|
||||||
# |
|
||||||
# Copyright © 2016-2017 Antergos |
|
||||||
# |
|
||||||
# This file is part of whither. |
|
||||||
# |
|
||||||
# whither 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. |
|
||||||
# |
|
||||||
# whither 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. |
|
||||||
# |
|
||||||
# The following additional terms are in effect as per Section 7 of the license: |
|
||||||
# |
|
||||||
# The preservation of all legal notices and author attributions in |
|
||||||
# the material or in the Appropriate Legal Notices displayed |
|
||||||
# by works containing it is required. |
|
||||||
# |
|
||||||
# You should have received a copy of the GNU General Public License |
|
||||||
# along with whither; If not, see <http://www.gnu.org/licenses/>. |
|
||||||
|
|
||||||
""" Utility class used to find and manage greeter themes. """ |
|
||||||
|
|
||||||
# Standard Lib |
|
||||||
import os |
|
||||||
from os.path import abspath |
|
||||||
|
|
||||||
# This Application |
|
||||||
from .pkg_json import PackageJSON |
|
||||||
|
|
||||||
from logging import ( |
|
||||||
getLogger, |
|
||||||
DEBUG, |
|
||||||
Formatter, |
|
||||||
StreamHandler, |
|
||||||
) |
|
||||||
|
|
||||||
log_format = ''.join([ |
|
||||||
'%(asctime)s [ %(levelname)s ] %(filename)s %(', |
|
||||||
'lineno)d: %(message)s' |
|
||||||
]) |
|
||||||
formatter = Formatter(fmt=log_format, datefmt="%Y-%m-%d %H:%M:%S") |
|
||||||
logger = getLogger("theme") |
|
||||||
logger.propagate = False |
|
||||||
stream_handler = StreamHandler() |
|
||||||
stream_handler.setLevel(DEBUG) |
|
||||||
stream_handler.setFormatter(formatter) |
|
||||||
logger.setLevel(DEBUG) |
|
||||||
logger.addHandler(stream_handler) |
|
||||||
|
|
||||||
|
|
||||||
def checkTheme(self): |
|
||||||
theme: str = self.config.greeter.theme |
|
||||||
dir = self.config.themes_dir |
|
||||||
path_to_theme: str = os.path.join(dir, theme, "index.html") |
|
||||||
def_theme = "gruvbox" |
|
||||||
|
|
||||||
if theme.startswith("/"): path_to_theme = theme; |
|
||||||
elif "." in theme or "/" in theme: |
|
||||||
path_to_theme = os.path.abspath(theme) |
|
||||||
|
|
||||||
if not path_to_theme.endswith(".html"): |
|
||||||
path_to_theme = os.path.join(path_to_theme, "index.html") |
|
||||||
|
|
||||||
if not os.path.exists(path_to_theme): |
|
||||||
logger.error("\"{0}\" theme does not exists. Using \"{1}\"".format(theme, def_theme)) |
|
||||||
path_to_theme = os.path.join(dir, def_theme, "index.html") |
|
||||||
|
|
||||||
return path_to_theme |
|
||||||
|
|
||||||
|
|
||||||
def listThemes(self): |
|
||||||
themes_dir = self.config.themes_dir |
|
||||||
themes_dir = themes_dir if os.path.exists(themes_dir) else "/usr/share/web-greeter/themes" |
|
||||||
filenames = os.listdir(themes_dir) |
|
||||||
|
|
||||||
dirlist = [] |
|
||||||
for file in filenames: |
|
||||||
if os.path.isdir(os.path.join(themes_dir, file)): |
|
||||||
dirlist.append(file) |
|
||||||
|
|
||||||
return dirlist |
|
||||||
|
|
||||||
|
|
||||||
class Theme: |
|
||||||
""" |
|
||||||
Represents a greeter theme installed on the local system. |
|
||||||
|
|
||||||
Args: |
|
||||||
path (str): The absolute path to the theme's directory. |
|
||||||
|
|
||||||
Attributes: |
|
||||||
data (PackageJSON): The theme's data sourced from its `package.json` file. |
|
||||||
""" |
|
||||||
|
|
||||||
def __init__(self, path: str) -> None: |
|
||||||
self.path = path |
|
||||||
|
|
||||||
self._initialize() |
|
||||||
|
|
||||||
def _initialize(self) -> None: |
|
||||||
package_json = os.path.join(self.path, 'package.json') |
|
||||||
|
|
||||||
try: |
|
||||||
self.data = PackageJSON(package_json) |
|
||||||
except Exception: |
|
||||||
self.data = None |
|
Loading…
Reference in new issue