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