@JonB, it actually appears that it works on one (example) script:
#!/usr/bin/env -S python3
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
self.button = QPushButton("Press Me!")
self.button.clicked.connect(self.the_button_was_clicked)
self.resize(self.minimumSizeHint())
self.setCentralWidget(self.button)
def the_button_was_clicked(self):
self.button.setText("You already clicked me.")
self.button.setEnabled(False)
# Also change the window title.
self.setWindowTitle("My Oneshot App")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
...but not another, (more) complex one:
#!/usr/bin/env -S python3
##### **Description**
"""
This allows management of the brightness of a monitor.
It features multiple methods of interaction, and operates upon Windows and traditional Linux distributions (Fedora and OpenSUSE).
"""
##### **Dependency Importation**
import calendar
import time
from rich.console import Console
from rich.markdown import Markdown
#**Origin(s)**: [Stack Overflow](https://stackoverflow.com/revisions/76833666/1#:~:text=from%20rich.console%20import%20Console,%20%20%20%20console.print(md))
##### **Metadata Definition**
__LICENSE__: str = ["MIT"]
__COPYRIGHT__: str = ["Copyright 2024 Roke Julian Lockhart Beedell"]
__STATUS__: list = ["alpha"]
__VERSION__: list = ["1720556480"]
__MAINTAINERS__: list = ["[`RokeJulianLockhart`](https://dub.sh/jga)"]
__CREDITS__: list = ["[`RokeJulianLockhart`](https://dub.sh/jga)"]
if __name__ == "__main__":
#**Information**: As [this](https://realpython.com/if-name-main-python/#:~:text=What%20Does%20if%20__name__%20==%20%22__main__%22%20Do%20in%20Python?) explains, this prevents invocation as a module, restricting it to run solely as a script.
import sys
if sys.version_info[0] != 3 or sys.version_info[1] < 7:
#**Origin(s)**: [Avoiding `__init__.py` for Initial Imports](https://stackoverflow.com/revisions/6224814/2#:~:text=You%20should%20not%20use%20any,including%20real%20initial%20imports%2C%20here)
logging.getLogger().debug(
Console().print(Markdown(
'This script requires Python version 3.')))
raise SystemExit(-1)
#**Information**: [Understanding `sys.exit(n)` in Python](https://stackoverflow.com/revisions/44894090/2#:~:text=The%20call%20sys.exit(n)%20tells%20the,answered)
#**Task(s)**: convert to `wxwidgets`/`wxpython`?: \
#1. [wxWidgets Issue 19352: Migrated from Trac Ticket](https://github.com/wxWidgets/wxWidgets/issues/19352#issue-1100648687:~:text=Issue%20migrated%20from%20trac%20ticket,Thanks%20a%20lot!)
#1. [wxWidgets: wxQt Project Information](https://www.wxwidgets.org/about/#:~:text=10%20and%0Aabove.-,wxqt,-%3A%20wxQt%20is%20a)
##### **Dependency Importation**
import platform
import subprocess
import logging
import shutil
#```py
#logging.basicConfig(level=logging.DEBUG)
# #**Task(s)**: fix [*Placeholder*](https://github.com/Crozzers/screen_brightness_control/discussions/30#discussion-5041474) \.
# #**Origin(s)**: [*Placeholder*](https://stackoverflow.com/revisions/41797120/1#:~:text=Try%20this-,logging.basicConfig(level=logging.DEBUG),-answered%20Jan%2022%2C)
#```
##### **Dependency Management**
def which(package):
"""
A function that takes a package name as input, tries to import the package, and if it fails, installs the package using pip.
Parameters:
package (str): The name of the package to import or install.
Returns:
None
"""
try:
return __import__(package)
except ImportError:
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
#**Origin(s)**: [Installing Python Packages with `pip` from Script](https://stackoverflow.com/revisions/50255019/2#:~:text=The%20officially%20recommended%20way%20to,subprocess.check_call(%5Bsys.executable%2C%20%22%2Dm%22%2C%20%22pip%22%2C%20%22install%22%2C%20package%5D))
#**Origin(s): [*Placeholder*](https://stackoverflow.com/revisions/4527622/3#:~:text=package%20=%20'package_name',%20%20%20%20return%20None)
logging.getLogger().debug(
Console().print(Markdown(
package, 'exists.')))
which(package='screen_brightness_control')
which(package='PyQt5')
which(package='rich')
#```py
#subprocess.check_call([sys.executable, "-m", "pip", "install", 'PySide6']) #**Task(s)**: ascertain whether this should be used instead, since it is official. https://www.pythonguis.com/faq/pyqt6-vs-pyside6/#:~:text=PySide2-,PyQt6%20vs%20PySide6,-What's%20the%20difference
#```
##### **Dependency Importation**
import screen_brightness_control as sbc
from PyQt5.QtWidgets import QMenu, QMenuBar, QApplication, QMainWindow, QVBoxLayout, QWidget, QSlider, QLineEdit, QPushButton, QTreeWidget, QTreeWidgetItem
#**Task(s)**: replace with PyQt6.
from PyQt5 import QtCore
#**Task(s)**: replace with PyQt6.
from PyQt5.QtCore import Qt
#**Task(s)**: replace with PyQt6.
##### **Security**
if platform.system() == 'Linux':
import getpass
import grp
import os
if getpass.getuser() not in str(
subprocess.call(["powershell", "".join(
[os.path.dirname(os.path.realpath(__file__)), ''])])): # <code>../ [-] `{title: "Configurator", id: "s3wrcl"}`{.JSON5}.dir/ [-] `{title: "Code", id: ""}`{.JSON5}.dir/ [x] ``{title: "`Get-SuperuserUsername`{.PS1}", id: "settlu"}``{.JSON5}.txt.PS1</code>
#**Origin(s)**: \
#1. [*Placeholder*](https://stackoverflow.com/revisions/842096/4#:~:text=Look%20at%20getpass%20module,May%208%2C%202009%20at%2022:30)
#1. [`in`](https://stackoverflow.com/revisions/3437070/7#:~:text=Use%20the%20in%20operator:,Note:%20This%20is%20case%2Dsensitive.)
#1. [*Placeholder*](https://stackoverflow.com/revisions/3430395/13#:~:text=The%20special%20variable%20__file__%20contains,does%20the%20__file__%20variable%20mean/do?)
#1. [*Placeholder*](https://stackoverflow.com/revisions/40311142/3#:~:text=For%20your%20stated%20scenario%2C%20there,Oct%2028%2C%202016%20at%2018:29)
logging.getLogger().debug(
logging.getLogger().debug(
Console().print(Markdown(
getpass.getuser(), 'is not the superuser.'))))
#**Task(s)**: Fix concatenation problems: `.debug("Houston, we have a %s", "thorny problem", exc_info=1)` works.
try:
grp.getgrnam('i2c')
except Exception:
try:
subprocess.call(['sudo', 'groupadd', '--system', 'i2c'])
grp.getgrnam('i2c')
except Exception:
logging.exception('Unable to create group i2c.')
raise SystemExit(-1)
else:
logging.getLogger().debug(
Console().print(Markdown(
'i2c exists.')))
if not [match for match in grp.getgrnam('i2c').gr_mem if getpass.getuser() in match]:
#**Information**: [*Placeholder*](https://www.ddcutil.com/i2c_permissions/#:~:text=I2C%20Device%20Permissions-,I2C%20Device%20Permissions,$%20sudo%20chmod%20a+rw%20/dev/i2c%2D*,-Previous) \
#**Origin(s)**: [*Placeholder*](https://stackoverflow.com/revisions/15168560/2#:~:text=This%20answer%20builds%20upon%20the,print('Group%20somegrp%20does%20not%20exist.'))
logging.exception(getpass.getuser(), 'is not part of the i2c group.')
if subprocess.call(['sudo', 'usermod', getpass.getuser(), '-aG', 'i2c']) != 0:
logging.exception('Unable to add user to i2c.')
raise SystemExit(-1)
else:
logging.getLogger().debug(
Console().print(Markdown(
getpass.getuser(), 'added to i2c.')))
else:
logging.getLogger().debug(
Console().print(Markdown(
getpass.getuser(), 'is part of i2c.')))
import shutil
ddcutil_available = False
logging.getLogger().debug(
Console().print(Markdown(
'0: ddcutil_available = False')))
if shutil.which('ddcutil') is None:
logging.getLogger().error(
Console().print(Markdown(
'Code RSJQ4A: the ddcutils binary is unavailable.')))
ddcutil_available = False
logging.getLogger().debug(
Console().print(Markdown(
'1: ddcutil_available = False')))
elif os.path.exists(shutil.which('ddcutil')):
ddcutil_available = True
logging.getLogger().debug(
Console().print(Markdown(
'2: ddcutil_available = True')))
else:
ddcutil_available = False
logging.getLogger().error(
Console().print(Markdown(
'Invalid output of shutil. Defaulting to assumption that ddcutil is unavailable.')))
if (sbc.list_monitors(method='ddcutil') == sbc.list_monitors()) == False:
logging.getLogger().error(
Console().print(Markdown(
'Code RSJPK5: ddcutils is unable to acquire the list of monitors. Operations may become slow.')))
ddcutil_available = False
logging.getLogger().debug(
Console().print(Markdown(
'3: ddcutil_available = False')))
elif (sbc.list_monitors(method='ddcutil') == sbc.list_monitors()) == True:
logging.getLogger().debug(
Console().print(Markdown(
'4: ddcutil is available.')))
ddcutil_available = True
logging.getLogger().debug(
Console().print(Markdown(
'5: ddcutil_available = True')))
else:
logging.exception(
Console().print(Markdown(
'ddcutil_available contains invalid value.')))
raise Exception(1)
##### **GUI**
class MainWindow(QMainWindow):
"""
* The class `MainWindow` inherits from `QMainWindow` and sets up a main window layout with monitor information.
* `__init__`: Initializes the main window layout, sets up monitor list, slider, input area, and apply configuration button.
* `on_click`: Handles the logic for applying the configuration to every checked monitor in the list.
"""
def __init__(self, *args, **kwargs):
"""
Initializes the MainWindow class.
Args:
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
Returns:
None
"""
super(MainWindow, self).__init__(*args, **kwargs)
layout_1 = QVBoxLayout()
layout_1.setAlignment(QtCore.Qt.AlignTop)
widget_1 = QWidget()
widget_1.setLayout(layout_1)
self.setCentralWidget(widget_1)
self.resize(self.minimumSizeHint())
monitor_list = QTreeWidget()
layout_1.addWidget(monitor_list)
#```py
#monitor_list.setWindowTitle('Monitors')
# #**Task(s)**: ascertain what this does.
#```
headers = (['Model', 'Brightness'])
monitor_list.setColumnCount(len(headers))
monitor_list.setHeaderLabels(headers)
counter = 0
if ddcutil_available == True:
#**Origin(s)**: [*Placeholder*](https://stackoverflow.com/revisions/11269627/7#:~:text=For%20python%20%3E=%203.3%2C%20Redirect,=%20os.system(%22echo%20'foo'%20%26%3E%20/dev/null%22))
while counter < len(sbc.list_monitors(method='ddcutil')):
#**Task(s)**: this doesn't operate with more than 1 monitor attached.
rowcount = monitor_list.topLevelItemCount()
monitor_list.addTopLevelItem(QTreeWidgetItem(rowcount))
monitor_list.topLevelItem(rowcount).setText(rowcount, sbc.list_monitors(method='ddcutil')[counter])
if sbc.list_monitors(method='ddcutil')[rowcount] == sbc.list_monitors(method='ddcutil')[0]:
monitor_list.topLevelItem(rowcount).setSelected(True)
#**Origin(s)**: [*Placeholder*](https://stackoverflow.com/posts/30213421/revisions#:~:text=You%20can%20interact%20with%20the,%7D)
else:
monitor_list.topLevelItem(rowcount).setSelected(False)
monitor_list.topLevelItem(rowcount).setCheckState(rowcount, QtCore.Qt.Unchecked)
monitor_list.topLevelItem(rowcount).setFlags(monitor_list.topLevelItem(rowcount).flags() | QtCore.Qt.ItemIsUserCheckable)
counter = counter + 1
if ddcutil_available == False:
while counter < len(sbc.list_monitors()):
#**Task(s)**: this doesn't operate with more than 1 monitor attached.
rowcount = monitor_list.topLevelItemCount()
monitor_list.addTopLevelItem(QTreeWidgetItem(rowcount))
monitor_list.topLevelItem(rowcount).setText(rowcount, sbc.list_monitors()[counter])
if sbc.list_monitors()[rowcount] == sbc.list_monitors()[0]:
monitor_list.topLevelItem(rowcount).setSelected(True)
#**Origin(s)**: [*Placeholder*](https://stackoverflow.com/posts/30213421/revisions#:~:text=You%20can%20interact%20with%20the,%7D)
monitor_list.topLevelItem(rowcount).setCheckState(rowcount, QtCore.Qt.Checked)
else:
monitor_list.topLevelItem(rowcount).setSelected(False)
monitor_list.topLevelItem(rowcount).setCheckState(rowcount, QtCore.Qt.Unchecked)
monitor_list.topLevelItem(rowcount).setFlags(monitor_list.topLevelItem(rowcount).flags() | QtCore.Qt.ItemIsUserCheckable)
counter = counter + 1
if not platform.system() == 'Windows' and not platform.system() == 'Darwin':
logging.getLogger().debug(
Console().print(Markdown(
"Unknown and consequently unsupported platform.")))
#```py
#for monitor in sbc.list_monitors():
# logging.getLogger().debug(
# Console().print(Markdown(
# monitor, ':', sbc.get_brightness(display=monitor), '%'))
#```
chosen_display = 0
slider = QSlider(Qt.Orientation.Horizontal, self)
layout_1.addWidget(slider)
slider.setRange(0, 100)
#**Task(s)**: add checkbox to override chosen colour with value provided by external device (brightness sensor)
#```py
#label = QLabel(sbc.list_monitors()[chosen_display], self)
#layout_1.addWidget(label)
# #**Task(s)**: this should be to the left of the input box.
#```
if ddcutil_available == True:
#**Origin(s)**: [Redirecting Output to `/dev/null` in Python 3.3+](https://stackoverflow.com/revisions/11269627/7#:~:text=For%20python%20%3E=%203.3%2C%20Redirect,=%20os.system(%22echo%20'foo'%20%26%3E%20/dev/null%22))
slider.setValue(sbc.get_brightness(method='ddcutil')[0])
#**Task(s)**: discover whether specification of a method is necessary, and if so, which to utilize.
elif ddcutil_available == False:
slider.setValue(sbc.get_brightness()[0])
#**Information**: `sbc.get_brightness(method='ddcutil')` is significantly more quick.
if not platform.system() == 'Windows' and not platform.system() == 'Darwin':
logging.getLogger().debug(
Console().print(Markdown(
"Unknown and consequently unsupported platform.")))
input_area = QLineEdit(self)
layout_1.addWidget(input_area)
if ddcutil_available == True:
#**Information**: [Pylint Singleton Comparison Convention](https://pylint.pycqa.org/en/latest/user_guide/messages/convention/singleton-comparison.html)
input_area.setPlaceholderText(str(sbc.get_brightness(method='ddcutil')[chosen_display]))
#**Task(s)**: discover whether specification of a method is necessary, and if so, which to utilize.
else:
input_area.setPlaceholderText(str(sbc.get_brightness()[chosen_display]))
#**Task(s)**: discover whether specification of a method is necessary, and if so, which to utilize.
if not platform.system() == 'Windows' and not platform.system() == 'Darwin':
logging.getLogger().debug(
Console().print(Markdown(
"Unknown and consequently unsupported platform.")))
application = QPushButton('Apply configuration', self)
layout_1.addWidget(application)
#```py
#def onSlide(slider):
# input_area.setPlaceholderText(slider.value())
#slider.valueChanged.connect(slider.valueChanged)
#```
#**Information**: [*Placeholder*](https://www.reddit.com/r/QtFramework/comments/10ac5kg/comment/j4734je/?utm_source=share&utm_medium=web2x&context=3)
def on_click():
#**Task(s)**: Use [*Placeholder*](https://stackoverflow.com/a/60785652/9731176) to apply to every checked monitor in list.
if ddcutil_available == True:
#**Information**: [*Placeholder*](https://pylint.pycqa.org/en/latest/user_guide/messages/convention/singleton-comparison.html)
sbc.set_brightness(slider.value(), method='ddcutil')
#**Origin(s)**: [*Placeholder*](https://stackoverflow.com/a/15765621/9731176)
input_area.setPlaceholderText(str(sbc.get_brightness(method='ddcutil')[chosen_display]))
elif ddcutil_available == False:
sbc.set_brightness(slider.value())
input_area.setPlaceholderText(str(sbc.get_brightness()[chosen_display]))
if not platform.system() == 'Windows' and not platform.system() == 'Darwin':
logging.getLogger().debug(
Console().print(Markdown(
"Unknown and consequently unsupported platform.")))
application.clicked.connect(on_click)
application.click()
#**Information**: [*Placeholder*](https://forum.qt.io/topic/94834/differences-between-qapplication-qguiappication-qcoreapplication-classes?_=1720556789808&lang=en-GB#:~:text=QCoreApplication%20%2D%20base%20class.%20Use,starts%20when%20you%20call%20app.exec();.)
app = QApplication
#**Information**: \
#1. Set attributes before `sys.argv` is passed to `QApplication` constructor.
#1. [*Placeholder*](https://medium.com/analytics-vidhya/how-to-build-your-first-desktop-application-in-python-7568c7d74311#:~:text=the%20qquickwindow.setscenegraphbackend('software')%20should%20be%20included%20in%20your%20code%20as%20a%20fallback%20option%20for%20uses%20with%20old%20hardware%20specs%2C%20other%20than%20that%20they%20would%20see%20an%20error%20information%20as%20seen%20below%3A)
from PyQt6.QtQuick import QQuickWindow
QQuickWindow.setTextRenderType(
QQuickWindow.TextRenderType.NativeTextRendering)
#**Information**: Should enable High DPI scaling, but isn't necesssary for Qt6.
app.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
#**Information**: [Ensures that widgets have native windows.](https://doc.qt.io/qt-6/qt.html#:~:text=qt%3A%3Aaa_nativewindows)
app.setAttribute(QtCore.Qt.AA_NativeWindows, True)
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
#**Information**: Hardcoded exit code unnecessary because `sys.exit()` provides it.
sys.exit(app.exec())
#**Information**: [`exec()` rather than `exec_()` is due to non-backward compatbility.](https://stackoverflow.com/revisions/22614643/4#:~:text=That's%20because%20until%20Python%203%2C,methods%20have%20been%20removed.%20...)
raise SystemExit(-1)
...per:
[image: 0JZ6ARW.mp4]
I suppose that that means that I'm doing something in one of the scripts that is incompatible with the command, rather than the operation itself being unsupported. Apologies if so.