From 5925f2513fc8e28360282de7b8935d661b36cd8a Mon Sep 17 00:00:00 2001 From: Chase Lau Date: Thu, 22 Dec 2022 09:14:30 -0600 Subject: [PATCH 1/7] Update install instructions and requirements.txt --- README.md | 27 +++++++++++++++++++++++---- requirements.txt | 13 ++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5dd80c7f..a62d95be 100755 --- a/README.md +++ b/README.md @@ -35,11 +35,30 @@ and also themes your favourite editors like VSCode or Atom. ## Installation -To install Yin-Yang: -1. Install the dependencies: `systemd`, `python-systemd` and optionally `pyside6` (from your system package manager) for native widget style -2. Copy and run the command below and follow the instructions: +### Dependencies: +Yin-Yang depends on `python-systemd` and `pyside6` from pypi. `python-systemd` requires you have installed the systemd-headers from your package manager. + +For CentOS, RHEL, and Fedora: +```bash +sudo dnf install gcc systemd-devel +``` + +For Debian, Ubuntu, etc. +```bash +sudo apt update +sudo apt install libsystemd-{journal,daemon,login,id128}-dev gcc +``` + +### Yin-Yang ```bash -git clone https://github.com/oskarsh/Yin-Yang && cd Yin-Yang && ./scripts/install.sh +git clone https://github.com/oskarsh/Yin-Yang && cd Yin-Yang +## Create virtual environment for pypi packages +python3 -m venv .venv +source .venv/bin/activate +# Install pip requirements +pip3 install -r requirements.txt +# Install Yin-Yang +./scripts/install.sh ``` ## Documentation diff --git a/requirements.txt b/requirements.txt index d53ab366..ae0a672d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,10 @@ -PySide6>=6.0.0 -suntime~=1.2.5 -psutil~=5.9.1 \ No newline at end of file +numpy==1.23.5 +psutil==5.9.4 +PySide6==6.4.1 +PySide6-Addons==6.4.1 +PySide6-Essentials==6.4.1 +python-dateutil==2.8.2 +shiboken6==6.4.1 +six==1.16.0 +suntime==1.2.5 +systemd-python==234 From 24d1371b4d8e6708a3516f4d49ae8a203d7649b8 Mon Sep 17 00:00:00 2001 From: Chase Lau Date: Thu, 22 Dec 2022 10:00:27 -0600 Subject: [PATCH 2/7] Add catch if Firefox profile is missing --- src/plugins/firefox.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/plugins/firefox.py b/src/plugins/firefox.py index 6f844b76..4c98d444 100755 --- a/src/plugins/firefox.py +++ b/src/plugins/firefox.py @@ -1,5 +1,6 @@ import json from configparser import ConfigParser +import logging from os.path import isdir from pathlib import Path @@ -7,6 +8,8 @@ from ._plugin import ExternalPlugin +logger = logging.getLogger(__name__) + def get_default_profile_path() -> str: path = str(Path.home()) + '/.mozilla/firefox/' @@ -33,11 +36,15 @@ def available_themes(self) -> dict: path = get_default_profile_path() + '/extensions.json' themes: dict[str, str] = {} - with open(path, 'r') as file: - content = json.load(file) - for addon in content['addons']: - if addon['type'] == 'theme': - themes[addon['id']] = addon['defaultLocale']['name'] + try: + with open(path, 'r') as file: + content = json.load(file) + for addon in content['addons']: + if addon['type'] == 'theme': + themes[addon['id']] = addon['defaultLocale']['name'] + except FileNotFoundError as e: + logger.error(f'Error: {e}.') + return {} assert themes != {}, 'No themes found!' return themes From 0815698c9e4ed6e713d4d20d972a26c6ba5b61f4 Mon Sep 17 00:00:00 2001 From: Chase Lau Date: Thu, 22 Dec 2022 11:28:57 -0600 Subject: [PATCH 3/7] Change variables and cast to avoid linter errors --- src/plugins/_plugin.py | 30 ++++++++++++++---------------- src/ui/main_window_connector.py | 12 +++++++++--- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/plugins/_plugin.py b/src/plugins/_plugin.py index 91a06af3..35c2990a 100644 --- a/src/plugins/_plugin.py +++ b/src/plugins/_plugin.py @@ -87,32 +87,30 @@ def get_input(self, widget): inputs = [QComboBox(widget), QComboBox(widget)] # add all theme names - for i, inp in enumerate(inputs): - inp: QComboBox + for i, curComboBox in enumerate(inputs): themes = list(self.available_themes.values()) themes.sort() - inp.addItems(themes) + curComboBox.addItems(themes) # set index is_dark = i == 1 theme: str = self.theme_dark if is_dark else self.theme_light if theme == '': logger.warning(f'Used theme is unknown for plugin {self.name}') - inp.setCurrentIndex(0) + curComboBox.setCurrentIndex(0) else: - inp.setCurrentIndex(themes.index(self.available_themes[theme])) - + curComboBox.setCurrentIndex(themes.index(self.available_themes[theme])) return inputs + else: + for is_dark in [False, True]: + theme = 'Dark' if is_dark else 'Light' + # provide a line edit, if the possible themes are unknown + inp: QLineEdit = QLineEdit(widget) + inp.setObjectName(f'inp_{theme}') + inp.setPlaceholderText(f'{theme} Theme') + inp.setText(self.theme_dark if is_dark else self.theme_light) + inputs.append(inp) - for is_dark in [False, True]: - theme = 'Dark' if is_dark else 'Light' - # provide a line edit, if the possible themes are unknown - inp: QLineEdit = QLineEdit(widget) - inp.setObjectName(f'inp_{theme}') - inp.setPlaceholderText(f'{theme} Theme') - inp.setText(self.theme_dark if is_dark else self.theme_light) - inputs.append(inp) - - return inputs + return inputs def __str__(self): return self.name.lower() diff --git a/src/ui/main_window_connector.py b/src/ui/main_window_connector.py index f683a3b3..5dcb3391 100755 --- a/src/ui/main_window_connector.py +++ b/src/ui/main_window_connector.py @@ -1,9 +1,10 @@ import logging +from typing import cast from PySide6 import QtWidgets from PySide6.QtCore import QStandardPaths from PySide6.QtGui import QScreen, QColor -from PySide6.QtWidgets import QFileDialog, QMessageBox, QDialogButtonBox, QColorDialog +from PySide6.QtWidgets import QFileDialog, QMessageBox, QDialogButtonBox, QColorDialog,QGroupBox from src.ui.main_window import Ui_main_window @@ -109,13 +110,18 @@ def load_location(self): self.ui.inp_longitude.setValue(coordinates[1]) def load_plugins(self): - widget: QtWidgets.QGroupBox + # First, remove sample plugin + samplePlugin = cast(QGroupBox,self.ui.plugins_scroll_content.findChild(QGroupBox, 'samplePluginGroupBox')) + samplePlugin.hide() + + + widget: QGroupBox for plugin in plugins: # filter out plugins for application if plugin.name.casefold() in ['notification', 'sound']: continue - widget = self.ui.plugins_scroll_content.findChild(QtWidgets.QGroupBox, 'group' + plugin.name) + widget = cast(QGroupBox,self.ui.plugins_scroll_content.findChild(QGroupBox, 'group' + plugin.name)) if widget is None: widget = plugin.get_widget(self.ui.plugins_scroll_content) self.ui.plugins_scroll_content_layout.addWidget(widget) From 55d6c2ad5b807b9e6e4602de2edfbd971cfc0fde Mon Sep 17 00:00:00 2001 From: Chase Lau Date: Thu, 22 Dec 2022 11:43:23 -0600 Subject: [PATCH 4/7] Fix horizontal overlap - Set the main window minimum size and increased default size. - Fixed window overlap when shrinking too small horizontally. --- designer/main_window.ui | 61 +++++++++++++++++++++++++++++++++++++---- src/plugins/_plugin.py | 1 + src/ui/main_window.py | 52 +++++++++++++++++++++++++++++------ 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/designer/main_window.ui b/designer/main_window.ui index 0fa03808..ffe07f23 100755 --- a/designer/main_window.ui +++ b/designer/main_window.ui @@ -2,12 +2,26 @@ main_window + + + 0 + 0 + 550 + 800 + + - + 0 0 + + + 400 + 600 + + Yin & Yang @@ -29,7 +43,7 @@ - 0 + 1 @@ -316,11 +330,48 @@ 0 0 - 348 - 451 + 523 + 663 - + + + + + + + Sample Plugin + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + firefox-compact-light@mozilla.org + + + + + + + + + + QComboBox::AdjustToContentsOnFirstShow + + + firefox-compact-dark@mozilla.org + + + + + + + + + diff --git a/src/plugins/_plugin.py b/src/plugins/_plugin.py index 35c2990a..74501360 100644 --- a/src/plugins/_plugin.py +++ b/src/plugins/_plugin.py @@ -91,6 +91,7 @@ def get_input(self, widget): themes = list(self.available_themes.values()) themes.sort() curComboBox.addItems(themes) + curComboBox.setMinimumContentsLength(4) # set index is_dark = i == 1 theme: str = self.theme_dark if is_dark else self.theme_light diff --git a/src/ui/main_window.py b/src/ui/main_window.py index 00e385bc..32703329 100644 --- a/src/ui/main_window.py +++ b/src/ui/main_window.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'main_window.ui' ## -## Created by: Qt User Interface Compiler version 6.3.1 +## Created by: Qt User Interface Compiler version 6.4.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -15,22 +15,25 @@ QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QDialogButtonBox, - QDoubleSpinBox, QFormLayout, QFrame, QLabel, - QMainWindow, QRadioButton, QScrollArea, QSizePolicy, - QSpacerItem, QStatusBar, QTabWidget, QTimeEdit, - QVBoxLayout, QWidget) +from PySide6.QtWidgets import (QAbstractButton, QApplication, QCheckBox, QComboBox, + QDialogButtonBox, QDoubleSpinBox, QFormLayout, QFrame, + QGroupBox, QHBoxLayout, QLabel, QMainWindow, + QRadioButton, QScrollArea, QSizePolicy, QSpacerItem, + QStatusBar, QTabWidget, QTimeEdit, QVBoxLayout, + QWidget) import resources_rc class Ui_main_window(object): def setupUi(self, main_window): if not main_window.objectName(): main_window.setObjectName(u"main_window") - sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) + main_window.resize(550, 800) + sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(main_window.sizePolicy().hasHeightForWidth()) main_window.setSizePolicy(sizePolicy) + main_window.setMinimumSize(QSize(400, 600)) main_window.setWindowTitle(u"Yin & Yang") icon = QIcon() iconThemeName = u"yin_yang" @@ -38,7 +41,7 @@ def setupUi(self, main_window): icon = QIcon.fromTheme(iconThemeName) else: icon.addFile(u":/icons/logo", QSize(), QIcon.Normal, QIcon.Off) - + main_window.setWindowIcon(icon) main_window.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) self.central_widget = QWidget(main_window) @@ -240,11 +243,39 @@ def setupUi(self, main_window): self.plugins_scroll.setWidgetResizable(True) self.plugins_scroll_content = QWidget() self.plugins_scroll_content.setObjectName(u"plugins_scroll_content") - self.plugins_scroll_content.setGeometry(QRect(0, 0, 348, 451)) + self.plugins_scroll_content.setGeometry(QRect(0, 0, 523, 663)) self.plugins_scroll_content_layout = QVBoxLayout(self.plugins_scroll_content) self.plugins_scroll_content_layout.setSpacing(6) self.plugins_scroll_content_layout.setContentsMargins(11, 11, 11, 11) self.plugins_scroll_content_layout.setObjectName(u"plugins_scroll_content_layout") + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setSpacing(6) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.samplePluginGroupBox = QGroupBox(self.plugins_scroll_content) + self.samplePluginGroupBox.setObjectName(u"samplePluginGroupBox") + self.horizontalLayout_2 = QHBoxLayout(self.samplePluginGroupBox) + self.horizontalLayout_2.setSpacing(6) + self.horizontalLayout_2.setContentsMargins(11, 11, 11, 11) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.comboBox = QComboBox(self.samplePluginGroupBox) + self.comboBox.setObjectName(u"comboBox") + self.comboBox.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow) + + self.horizontalLayout_2.addWidget(self.comboBox) + + self.comboBox_2 = QComboBox(self.samplePluginGroupBox) + self.comboBox_2.setObjectName(u"comboBox_2") + self.comboBox_2.setCurrentText(u"") + self.comboBox_2.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow) + + self.horizontalLayout_2.addWidget(self.comboBox_2) + + + self.horizontalLayout.addWidget(self.samplePluginGroupBox) + + + self.plugins_scroll_content_layout.addLayout(self.horizontalLayout) + self.plugins_scroll.setWidget(self.plugins_scroll_content) self.plugins_layout.addWidget(self.plugins_scroll) @@ -287,6 +318,9 @@ def retranslateUi(self, main_window): self.toggle_sound.setText(QCoreApplication.translate("main_window", u"Make a sound when switching the theme", None)) self.toggle_notification.setText(QCoreApplication.translate("main_window", u"Send a notification", None)) self.tab_widget.setTabText(self.tab_widget.indexOf(self.settings), QCoreApplication.translate("main_window", u"Settings", None)) + self.samplePluginGroupBox.setTitle(QCoreApplication.translate("main_window", u"Sample Plugin", None)) + self.comboBox.setPlaceholderText(QCoreApplication.translate("main_window", u"firefox-compact-light@mozilla.org", None)) + self.comboBox_2.setPlaceholderText(QCoreApplication.translate("main_window", u"firefox-compact-dark@mozilla.org", None)) self.tab_widget.setTabText(self.tab_widget.indexOf(self.plugins), QCoreApplication.translate("main_window", u"Plugins", None)) pass # retranslateUi From df7c6dc07ab2814bfb8c9c014c78bd960d96d5b0 Mon Sep 17 00:00:00 2001 From: Chase Lau <6013163+chase9@users.noreply.github.com> Date: Thu, 22 Dec 2022 11:50:59 -0600 Subject: [PATCH 5/7] Update python-app.yml Add new workflow deps for systemd --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 4a38bed1..16d23561 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -31,7 +31,7 @@ jobs: ${{ runner.os }}- - name: Install dependencies run: | - sudo apt install qt6-base-dev + sudo apt install qt6-base-dev libsystemd-{journal,daemon,login,id128}-dev gcc python -m pip install --upgrade pip pip install flake8 pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi From 4c4a4dfe3157b5509ef4768e2fcb3fc223cc9003 Mon Sep 17 00:00:00 2001 From: Chase Lau Date: Thu, 22 Dec 2022 11:56:32 -0600 Subject: [PATCH 6/7] Fix Ubuntu deps (again) --- .github/workflows/python-app.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 16d23561..2a992395 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -31,7 +31,7 @@ jobs: ${{ runner.os }}- - name: Install dependencies run: | - sudo apt install qt6-base-dev libsystemd-{journal,daemon,login,id128}-dev gcc + sudo apt install qt6-base-dev libsystemd-dev gcc python -m pip install --upgrade pip pip install flake8 pytest if [ -f requirements.txt ]; then pip install -r requirements.txt; fi diff --git a/README.md b/README.md index a62d95be..c4b49a87 100755 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ sudo dnf install gcc systemd-devel For Debian, Ubuntu, etc. ```bash sudo apt update -sudo apt install libsystemd-{journal,daemon,login,id128}-dev gcc +sudo apt install libsystemd-dev gcc ``` ### Yin-Yang From 0250aea2901ddaa62d53b5c63ab6059f4e146443 Mon Sep 17 00:00:00 2001 From: l0drex Date: Mon, 2 Jan 2023 14:35:48 +0100 Subject: [PATCH 7/7] Fix #149 --- src/plugins/_plugin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/_plugin.py b/src/plugins/_plugin.py index 74501360..430e2fc0 100644 --- a/src/plugins/_plugin.py +++ b/src/plugins/_plugin.py @@ -95,11 +95,11 @@ def get_input(self, widget): # set index is_dark = i == 1 theme: str = self.theme_dark if is_dark else self.theme_light - if theme == '': - logger.warning(f'Used theme is unknown for plugin {self.name}') - curComboBox.setCurrentIndex(0) - else: + try: curComboBox.setCurrentIndex(themes.index(self.available_themes[theme])) + except (KeyError, ValueError): + logger.warning(f'Couldn\'t find theme {theme} in plugin {self.name}') + curComboBox.setCurrentIndex(0) return inputs else: for is_dark in [False, True]: