diff --git a/.gitignore b/.gitignore index 3516a57..e3c2527 100755 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,6 @@ ENV/ .mypy* # idea -.idea* \ No newline at end of file +.idea* +brightness-controller-linux/test.txt +brightness-controller-linux/testDdc.txt diff --git a/brightness-controller-linux/brightness_controller_linux/init.py b/brightness-controller-linux/brightness_controller_linux/init.py index e84468c..e3e6959 100755 --- a/brightness-controller-linux/brightness_controller_linux/init.py +++ b/brightness-controller-linux/brightness_controller_linux/init.py @@ -18,8 +18,8 @@ # . import sys -import getpass -from os import path, remove, makedirs +import getpass, argparse, os, traceback +from os import path, remove, makedirs, getenv from qtpy import QtGui, QtCore, QtWidgets from qtpy.QtCore import QSize, Qt from qtpy.QtGui import QIcon @@ -33,42 +33,75 @@ from brightness_controller_linux.util import write_config as WriteConfig from brightness_controller_linux.util import read_config as ReadConfig from brightness_controller_linux.util import resource_provider as rp + +import brightness_controller_linux.util.log as log # import util.filepath_handler as Filepath_handler import subprocess import threading +verbosity = 1 + class MyApplication(QtWidgets.QMainWindow): ddcutil_Installed = False + waylandEnvironment = False displayMaxes = [] displayValues = [] - displayNames = [] + # ["connection", "name"] ordered the same as ddcutil lists + + global parser + + def verbose(self, verbosityLevel : int, message : str) -> None: + if verbosity>= verbosityLevel: + print(message) def __assign_displays(self): """assigns display name """ - self.displays = CDisplay.detect_display_devices() + self.displays = CDisplay.extract_display_names() # returns ['connection', 'display name'] self.no_of_displays = len(self.displays) self.no_of_connected_dev = self.no_of_displays + log.info(f"{self.no_of_displays} detected displays:") + log.info(str(self.displays)) + log.info("") + + self.verbose(2, str(self.displays) + " " + str(self.no_of_displays)) + if self.no_of_displays == 1: - self.display1 = self.displays[0] + self.display1 = self.displays[0][0] elif self.no_of_displays >= 2: - self.display1 = self.displays[0] - self.display2 = self.displays[1] + self.display1 = self.displays[0][0] + self.display2 = self.displays[1][0] + + def directlySetBrightness(self, displayNum, value): + self.verbose(2, f"Updating brightness for display {self.displays[displayNum][1]} with value {value}") + log.info(f"Updating brightness for display {displayNum} {self.displays[displayNum][1]} with value {value}") - def directlySetMaxBrightness(self, displayNum, percentage): + if self.displays[displayNum][0].startswith("eDP"): + print("ATTEMPTED TO SET LAPTOP DISPLAY: ABORTING") + return - percentage = round(percentage) / 100 + try: + subprocess.run(["ddcutil", "setvcp", "10", str(int(value)), "-d", str(displayNum + 1)]) + except: + print(f"Error while setting display {self.displays[displayNum][1]} with value {value}") + log.error(f"Error while setting display {displayNum} {self.displays[displayNum][1]} with value {value}") - subprocess.run(["ddcutil", "setvcp", "10", str(int( - self.displayMaxes[displayNum - 1] * percentage)), "-d", - str(displayNum)]) def __init__(self, parent=None): """Initializes""" QtWidgets.QMainWindow.__init__(self, parent) + log.begin() + + # warn if wayland is installed + if os.getenv("XDG_SESSION_TYPE") == "wayland": + print("Warning: Wayland session detected! Wayland is in experimental support! Expect buggy behavior") + self.waylandEnvironment = True + log.warning("Wayland session detected!") + QtWidgets.QMessageBox.warning(self, "Wayland Environment", "Wayland is in EXPERIMENTAL support. Software brightness is currently broken.") + # check if ddcutil is installed try: if "ddcutil" in str( @@ -76,43 +109,37 @@ def __init__(self, parent=None): if "sudo modprobe" in str( subprocess.check_output(["ddcutil", "environment"]), 'utf-8'): - self.ui.ddcutilsNotInstalled.setText( - "add i2c-dev to etc/modules-load.d") - else: - self.ddcutil_Installed = True - except: - self.ddcutil_Installed = False + self.ui.ddcutilsNotInstalled.setText("add i2c-dev to etc/modules-load.d") - try: - getNames = str(subprocess.check_output(["ddcutil", "detect"]), - 'utf-8').split("\n") + envCheck = str(subprocess.check_output(["ddcutil", "environment"]), 'utf-8') - for i in range(len(getNames)): - if "Model:" in getNames[i]: + if "not a member of group i2c" in envCheck: - if not getNames[i].split(":")[1].strip() == "": - self.displayNames.append( - getNames[i].split(":")[1].strip()) + log.fatal(f"[DDCUtil] User is not part of i2c group! Run 'sudo usermod -G i2c -a {getpass.getuser()}'") + errorBox = QtWidgets.QMessageBox.critical(None, + "DDCUtil User config error!", + f"User is not part of i2c group! Run 'sudo usermod -G i2c -a {getpass.getuser()}'", + QtWidgets.QMessageBox.StandardButton.Close) + exit() + else: + self.ddcutil_Installed = True + except Exception: + self.ddcutil_Installed = False - if "Invalid display" in getNames[i]: - self.displayNames.append(getNames[i].strip()) + log.info(f"DDCUtils installed: {self.ddcutil_Installed}") - for i in range(len(self.displayNames)): - if not self.displayNames[i] == "Invalid display": - brightnessValue = str(subprocess.check_output( - ["ddcutil", "getvcp", "10", "-d", str(i + 1)]), 'utf-8') + if (not self.ddcutil_Installed) and self.waylandEnvironment: + # Just exit entirely if we are on wayland and dont have ddcutil since it just won't do anything + log.fatal("Wayland environment detected and ddcutils is not installed! Exiting") + errorBox = QtWidgets.QMessageBox.critical(None, + "DDCUtil Missing", + "Software brightness is broken on wayland and ddcutil doesn't appear to be installed! Please install the package `ddcutil` to use this program on wayland.", + QtWidgets.QMessageBox.StandardButton.Close) + sys.exit() + - self.displayMaxes.append(int( - brightnessValue.split(",")[1].split("=")[1].strip())) - - self.displayValues.append(int( - brightnessValue.split(',')[0].split('=')[1].strip())) - else: - self.displayMaxes.append(1) - self.displayValues.append(1) - - except Exception as e: - print("error: " + str(e)) + + self.updatingMode = False self.tray_menu = None self.tray_icon = None @@ -135,6 +162,43 @@ def __init__(self, parent=None): self.temperature = 'Default' self.no_of_connected_dev = 0 self.__assign_displays() + + #moved to directly after __assign_displays to prevent comboboxes having items added in the original order from xrandr + if self.ddcutil_Installed: + self.displays = CDisplay.match_ddc_order(self.displays) + + self.verbose(2, str(self.displays) + " : reordered displays") + + self.ui.ddcutilsNotInstalled.setVisible(False) + + log.info("Getting display brightness ranges.") + + for i in range(len(self.displays)): + self.ui.directControlBox.setEnabled(True) + + brightnessValue = "" + + brightnessValue = subprocess.getoutput(f"ddcutil getvcp 10 -d {i + 1}") # Ignores the return value + log.info(brightnessValue) + if "Display not found" in brightnessValue: + log.error(f"Display wasn't found for command `ddcutil getvcp 10 -d {i + 1}`") + self.ui.ddcutilsNotInstalled.setVisible(True) + self.ui.ddcutilsNotInstalled.setText("Laptop Displays Not Supported") + self.displayMaxes.append(1) + self.displayValues.append(1) + continue + + self.displayMaxes.append(int( + brightnessValue.split(",")[1].split("=")[1].strip())) + + self.displayValues.append(int( + brightnessValue.split(',')[0].split('=')[1].strip())) + + log.info(f"current display values {self.displayValues}") + log.info(f"display maxes: {self.displayMaxes}") + + + self.setup_default_directory() self.generate_dynamic_items() self.default_config = '/home/{}/.config/' \ @@ -148,21 +212,20 @@ def __init__(self, parent=None): self.connect_handlers() self.setup_widgets() + if self.ddcutil_Installed and self.waylandEnvironment: + self.ui.directControlBox.setChecked(True) # Auto turn on ddc control since xrandr doesnt work on wayland + self.ui.directControlBox.setEnabled(False) + if path.exists(self.default_config): self.load_settings(self.default_config) - if self.ddcutil_Installed: - res = all(ele == "Invalid display" for ele in self.displayNames) + """ + res = all(ele == "Invalid display" for ele in self.displays) if not res: - self.ui.directControlBox.setEnabled(True) - self.ui.ddcutilsNotInstalled.setVisible(False) + else: - self.ui.ddcutilsNotInstalled.setText( - "Laptop Displays Not Supported") - - print(self.displayNames) + """ - print(self.ddcutil_Installed) self.canCloseToTray = False @@ -170,6 +233,8 @@ def __init__(self, parent=None): self.canCloseToTray = True self.setup_tray(parent) + log.info("Init finished!") + def setup_default_directory(self): """ Create default settings directory if it doesnt exist """ directory = '/home/{}/.config/' \ @@ -191,6 +256,7 @@ def closeEvent(self, event): QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: event.accept() + log.info("Application Exiting!") sys.exit(self.APP.exec_()) else: event.ignore() @@ -208,6 +274,7 @@ def trayClose(self): QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: + log.info("Application Exiting!") sys.exit(self.APP.exec_()) def setup_tray(self, parent): @@ -277,15 +344,15 @@ def generate_brightness_sources(self): self.ui.primary_combobox.setEnabled(False) return - if self.ddcutil_Installed: + """if self.ddcutil_Installed: for i in range(self.no_of_connected_dev): self.ui.secondary_combo.addItem(self.displayNames[i]) self.ui.primary_combobox.addItem(self.displayNames[i]) pass - else: - for display in self.displays: - self.ui.secondary_combo.addItem(display) - self.ui.primary_combobox.addItem(display) + else:""" + for display in self.displays: + self.ui.secondary_combo.addItem(display[1]) + self.ui.primary_combobox.addItem(display[1]) def connect_handlers(self): """Connects the handlers of GUI widgets""" @@ -327,29 +394,55 @@ def connect_handlers(self): self.ui.actionLoad.triggered.connect(self.load_settings) def directControlUpdate(self, value): + + if self.ddcutil_Installed and self.waylandEnvironment and not self.ui.directControlBox.isChecked(): + self.ui.directControlBox.setChecked(True) # Force wayland users to only use ddc + + log.info(f"ddc mode toggled to: {self.ui.directControlBox.isChecked()}") + + self.updatingMode = True + if self.ui.directControlBox.isChecked(): self.ui.primary_brightness.setMaximum(100) - self.ui.primary_brightness.setValue(int(round( - (self.displayValues[0] / self.displayMaxes[0]) * 100))) - self.ui.primary_brightness.setFocusPolicy(Qt.NoFocus) - self.ui.primary_brightness.setTracking(False) - print("Update: " + self.ui.primary_combobox.currentText()) + primaryComboIndex = self.ui.primary_combobox.currentIndex() + secondaryComboIndex = self.ui.secondary_combo.currentIndex() - if self.ui.primary_combobox.currentText() == "Invalid display": + # if display has valid max value, set the brightness slider's max value to display max + # otherwise we disable the slider since it either errored or is a laptop display and cant be controlled + if self.displayMaxes[primaryComboIndex] > 0: + + if not self.displays[primaryComboIndex][0].startswith("eDP"): + self.ui.primary_brightness.setEnabled(True) + self.ui.primary_brightness.setMaximum(self.displayMaxes[primaryComboIndex]) + self.ui.primary_brightness.setValue(int(round( + (self.displayValues[primaryComboIndex] / self.displayMaxes[primaryComboIndex]) * 100))) + else: + self.ui.primary_brightness.setEnabled(False) + + self.ui.primary_brightness.setFocusPolicy(Qt.NoFocus) + self.ui.primary_brightness.setTracking(False) + else: self.ui.primary_brightness.setEnabled(False) if self.no_of_displays > 1: - self.ui.secondary_brightness.setMaximum(100) - self.ui.secondary_brightness.setValue(int(round( - (self.displayValues[1] / self.displayMaxes[1]) * 100))) - self.ui.secondary_brightness.setFocusPolicy(Qt.NoFocus) - self.ui.secondary_brightness.setTracking(False) - - if self.ui.secondary_combo.currentText() == "Invalid display": + if self.displayMaxes[secondaryComboIndex] > 0: + if not self.displays[secondaryComboIndex][0].startswith("eDP"): + self.ui.secondary_brightness.setEnabled(True) + self.ui.secondary_brightness.setMaximum(self.displayMaxes[secondaryComboIndex]) + self.ui.secondary_brightness.setValue(int(round( + (self.displayValues[secondaryComboIndex] / self.displayMaxes[secondaryComboIndex]) * 100))) + else: + self.ui.secondary_brightness.setEnabled(False) + + self.ui.secondary_brightness.setFocusPolicy(Qt.NoFocus) + self.ui.secondary_brightness.setTracking(False) + else: self.ui.secondary_brightness.setEnabled(False) else: + self.ui.primary_brightness.setEnabled(True) + self.ui.secondary_brightness.setEnabled(True) self.ui.primary_brightness.setMaximum(99) self.ui.secondary_brightness.setMaximum(99) self.ui.primary_brightness.setValue(99) @@ -359,11 +452,8 @@ def directControlUpdate(self, value): self.ui.secondary_brightness.setFocusPolicy(Qt.StrongFocus) self.ui.secondary_brightness.setTracking(True) - if self.no_of_displays == 1: - self.ui.primary_brightness.setEnabled(True) - else: - self.ui.primary_brightness.setEnabled(True) - self.ui.secondary_brightness.setEnabled(True) + self.updatingMode = False + def enable_secondary_widgets(self, boolean): """ @@ -390,14 +480,12 @@ def connect_secondary_widgets(self): def change_value_pbr(self): """Changes Primary Display Brightness""" - if self.ui.directControlBox.isChecked(): + if self.updatingMode: return - setValue = threading.Thread(target=self.directlySetMaxBrightness, - args=( - self.ui.primary_combobox.currentIndex() + 1, - self.ui.primary_brightness.value())) + if self.ui.directControlBox.isChecked(): - setValue.start() + self.directlySetBrightness(self.ui.primary_combobox.currentIndex(), + self.ui.primary_brightness.value()) self.displayValues[self.ui.primary_combobox.currentIndex()] = int( round(self.ui.primary_brightness.value() / 100 * @@ -461,15 +549,12 @@ def change_value_sbr(self): """ Changes Secondary Display Brightness """ + if self.updatingMode: return if self.ui.directControlBox.isChecked(): - setValue = threading.Thread(target=self.directlySetMaxBrightness, - args=( - self.ui.secondary_combo.currentIndex() + 1, - self.ui.secondary_brightness.value())) - - setValue.start() + self.directlySetBrightness(self.ui.secondary_combo.currentIndex(), + self.ui.secondary_brightness.value()) self.displayValues[self.ui.secondary_combo.currentIndex()] = int( round((self.ui.secondary_brightness.value() / 100 * @@ -545,33 +630,30 @@ def secondary_source_combo_activated(self, text): assigns combo value to display """ self.display2 = self.displays[ - self.ui.secondary_combo.currentIndex()] # text - print(self.ui.secondary_combo.currentText()) - if self.ui.directControlBox.isChecked(): - if self.ui.secondary_combo.currentText() == "Invalid display": - self.ui.secondary_brightness.setEnabled(False) - print("secondary disabled") - else: - self.ui.secondary_brightness.setEnabled(True) - print("secondary enabled") + self.ui.secondary_combo.currentIndex()][0] # text + + if self.ddcutil_Installed and self.displays[self.ui.secondary_combo.currentIndex()][0].startswith("eDP"): + self.ui.primary_brightness.setEnabled(False) else: - self.ui.secondary_brightness.setEnabled(True) + self.ui.primary_brightness.setEnabled(True) + + + if self.ui.directControlBox.isChecked(): + self.directControlUpdate(0) def primary_source_combo_activated(self, text): """assigns combo value to display""" self.display1 = self.displays[ - self.ui.primary_combobox.currentIndex()] # text + self.ui.primary_combobox.currentIndex()][0] # text - print(self.ui.primary_combobox.currentText()) - if self.ui.directControlBox.isChecked(): - if self.ui.primary_combobox.currentText() == "Invalid display": - self.ui.primary_brightness.setEnabled(False) - print("primary disabled") - else: - self.ui.primary_brightness.setEnabled(True) - print("primary enabled") + # Disable slider if laptop display + if self.ddcutil_Installed and self.displays[self.ui.primary_combobox.currentIndex()][0].startswith("eDP"): + self.ui.primary_brightness.setEnabled(False) else: - self.ui.secondary_brightness.setEnabled(True) + self.ui.primary_brightness.setEnabled(True) + + if self.ui.directControlBox.isChecked(): + self.directControlUpdate(0) def combo_activated(self, text): """ Designates values to display and to sliders """ @@ -895,6 +977,15 @@ def set_main_window(self, main_win): """assigns main_win as main_window""" self.main_window = main_win + +parser = argparse.ArgumentParser(prog='ProgramName', + description='What the program does', + epilog='use --help to show cli arguments') +parser.add_argument('-v', '--verbose', action='store_const', const=2, default=1) + +args = parser.parse_args() +verbosity = args.verbose + def main(): UUID = 'PHIR-HWOH-MEIZ-AHTA' APP = QtSingleApplication(UUID, sys.argv) @@ -907,4 +998,7 @@ def main(): sys.exit(APP.exec_()) if __name__ == "__main__": - main() + try: + main() + except: + log.fatal(traceback.format_exc()) diff --git a/brightness-controller-linux/brightness_controller_linux/util/check_displays.py b/brightness-controller-linux/brightness_controller_linux/util/check_displays.py index d87aaff..c5df6d6 100644 --- a/brightness-controller-linux/brightness_controller_linux/util/check_displays.py +++ b/brightness-controller-linux/brightness_controller_linux/util/check_displays.py @@ -16,10 +16,16 @@ # You should have received a copy of the GNU General Public License # along with Brightness Controller. If not, see . -import subprocess +import subprocess, os import shlex import re +debug = False +try: + import brightness_controller_linux.util.log as log +except: + import log #used in testing + debug = True def query_xrandr(): query = "xrandr --query" @@ -38,6 +44,196 @@ def extract_displays(output): return connected_displays +def extract_edid_name(edid_hex): + try: + display_name = edid_hex[edid_hex.find('fc00') + 4:] + display_name = display_name[:display_name.find('0a')] + + return bytes.fromhex(display_name).decode() + + except Exception as e: + print("Error:", e) + return None + +def x11_Monitor_Name_Extractor(xrandr_monitors : list): + + displays = [] + + for monitor in xrandr_monitors: + monitorInfo = [] + gettingEDID = False + currentEdid = "" + for line in monitor: + + if "connected" in line: + monitorInfo.append(line[:line.find(' ')]) + + if gettingEDID and line.startswith("\t\t"): + currentEdid += line[2:] + elif gettingEDID: + break + else: + gettingEDID = False + + if line == "\tEDID: ": + gettingEDID = True + + + monitorName = extract_edid_name(currentEdid) + if monitorName: + monitorInfo.append(monitorName) + log.info(f"{monitor[0]} name is {monitorName}") + else: + print(f"Failed to get display name from monitor {monitor[0]}") + log.info(f"Failed to get display name from monitor {monitor[0]}") + monitorInfo.append(monitorInfo[0]) + + displays.append(monitorInfo) + + log.info(f"[x11] Monitor names extracted: [{displays}]") + + return displays + +def wayland_Monitor_Info_Extractor(monitorInfo): + + connectionName = None + modelName = None + + for line in monitorInfo: + #print(line) + + if line.startswith('\tname:'): + connectionName = line.split(':')[1].strip() + + if line.startswith("\tmake:"): + model = line.split(',')[1] + modelName = model[ model.find("'") + 1 : model.rfind("/") ] + #print(modelName) + + if modelName and connectionName: + return [connectionName, modelName] + else: + return None + + +def wayland_Monitor_Name_Extractor(): + + waylandInfo = [] + displays = [] + currentDisplay = [] + + try: + waylandInfo = subprocess.check_output(["wayland-info"]).decode().splitlines() + except: + print("ERROR: Please install the package \"wayland-utils\" for the wayland-info command!") + print("Monitor names will not be shown as they can't be labeled") + return None + + i = -1 + for line in waylandInfo: + i += 1 + + if line.startswith("interface: 'wl_output',") or i == len(waylandInfo) - 1: + if currentDisplay[0].startswith("interface: 'wl_output',"): + #get display info out + monitorInfo = wayland_Monitor_Info_Extractor(currentDisplay) + if not monitorInfo[0].startswith("Unknown"): + displays.append(monitorInfo) + #print(currentDisplay) + currentDisplay = [] + + currentDisplay.append(line) + + log.info(f"[wayland] Monitor names extracted: {displays}") + + return displays + + +def extract_display_names(testInfo = None): + xrandr_output = subprocess.check_output(["xrandr", "--verbose"]).decode().splitlines() + + displayVerboseInfo = [] + display = [] + + #get verbose data for displays + i = -1 + for line in xrandr_output: + i += 1 + + if line.startswith("Screen"): continue + + if i == len(xrandr_output) - 1: + display.append(line) + if "disconnected" not in display[0]: + if not display[0].startswith("Unknown"): + displayVerboseInfo.append(display) + + if not line.startswith("\t") and "connected" in line: + if len(display) > 0: + if "disconnected" not in display[0]: + if not display[0].startswith("Unknown"): + displayVerboseInfo.append(display) + + display = [] + display.append(line) + else: + display.append(line) + + log.info(f"Display info : {len(displayVerboseInfo)} displays.") + log.info(displayVerboseInfo) + log.info("") + + if os.getenv("XDG_SESSION_TYPE") == "wayland": + waylandDisplayNames = wayland_Monitor_Name_Extractor() + if waylandDisplayNames == None: + # fall back to old nameing + log.warning("Fell back to x11 monitor name extraction!") + print("ERROR Falling back to x11 monitor name extractor! Names may not be extracted!") + return x11_Monitor_Name_Extractor(displayVerboseInfo) + + # we got display names from wayland! + return waylandDisplayNames + + else: + return x11_Monitor_Name_Extractor(displayVerboseInfo) + + +def match_ddc_order(monitorNames): + + detectedMonitors = subprocess.check_output(["ddcutil", "detect"]).decode().splitlines() + + log.info("ddcutil detect output:") + log.info(detectedMonitors) + + reorderedMonitors = [] + + #laptopMonitorNames = [['eDP-1', 'eDP-1'], ['HDMI-1', 'VG279']] + + #laptopTestCase = ['Display 1', ' I2C bus: /dev/i2c-1', ' EDID synopsis:', ' Mfg id: AUS', ' Model: VG279', ' Serial number: Redacted', ' Manufacture year: 2020', ' EDID version: 1.3', ' VCP version: 2.2', '', 'Invalid display', ' I2C bus: /dev/i2c-4', ' EDID synopsis:', ' Mfg id: BOE', ' Model: ', ' Serial number: ', ' Manufacture year: 2015', ' EDID version: 1.4', ' DDC communication failed', ' This is an eDP laptop display. Laptop displays do not support DDC/CI.', ''] + + for line in detectedMonitors: + if "Model" in line: + for monitor in monitorNames: + modelName = line.split(":")[1].strip() + log.info(f"[ddcReorder] Model name output {modelName}") + if modelName == '': + if monitor[1].startswith('eDP'): + reorderedMonitors.append(monitor) + log.info(f"[ddcReorder] added {monitor} from {modelName}") + break + + if monitor[1] in modelName: + reorderedMonitors.append(monitor) + log.info(f"[ddcReorder] added {monitor} from {modelName}") + break + + if len(monitorNames) != len(reorderedMonitors): + print(f"ERROR IN MONITOR REORDERING please create an issue on the github with your log file at ~/.config/brightness_controller/log.txt") + log.error(f"Failed attempting to reorder monitors, input: {monitorNames} attempted output: {reorderedMonitors}") + return monitorNames # fall back to unreordered output + return reorderedMonitors + + def detect_display_devices(): """ Detects available displays. @@ -47,5 +243,9 @@ def detect_display_devices(): return extract_displays(query_xrandr()) -if __name__ == '__main__': - print(detect_display_devices()) +if debug: + #print(detect_display_devices()) + with open("test.txt", 'r') as file: + testInfo = file.readlines() + + extract_display_names(testInfo) diff --git a/brightness-controller-linux/brightness_controller_linux/util/executor.py b/brightness-controller-linux/brightness_controller_linux/util/executor.py index 5c109ac..c19ddb5 100644 --- a/brightness-controller-linux/brightness_controller_linux/util/executor.py +++ b/brightness-controller-linux/brightness_controller_linux/util/executor.py @@ -20,4 +20,7 @@ def execute_command(string_cmd): - subprocess.check_output(string_cmd, shell=True) + try: + subprocess.check_output(string_cmd, shell=True) + except: + None \ No newline at end of file diff --git a/brightness-controller-linux/brightness_controller_linux/util/log.py b/brightness-controller-linux/brightness_controller_linux/util/log.py new file mode 100644 index 0000000..d2d4bbe --- /dev/null +++ b/brightness-controller-linux/brightness_controller_linux/util/log.py @@ -0,0 +1,57 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +# This file is part of Brightness Controller. +# +# Brightness Controller 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. +# +# Brightness Controller 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 Brightness Controller. If not, see +# . + +import os, sys +from datetime import datetime + +logPath = f"/home/{os.getlogin()}/.config/brightness_controller/log.txt" + +def write(logString, level): + currentTime = datetime.now() + with open(logPath, 'a') as file: + if type(logString) is list: + for line in logString: + if type(line) is list: + write(line, level) + else: + file.write(f"[{currentTime}] [{level}] {line}\n") + else: + file.write(f"[{currentTime}] [{level}] {logString}\n") + +def info(logString): + write(logString, "info") + +def warning(logString): + write(logString, "warning") + +def error(logString): + write(logString, "ERROR") + +def fatal(logString): + write(logString, "FATAL") + +def begin(): + if not os.path.exists(logPath): + try: + os.makedirs(f"/home/{os.getlogin()}/.config/brightness_controller") + except: + None + open(logPath, 'w').close() + + info("Application start!") \ No newline at end of file diff --git a/brightness-controller-linux/brightness_controller_linux/util/resource_provider.py b/brightness-controller-linux/brightness_controller_linux/util/resource_provider.py index 3650012..e9eca67 100644 --- a/brightness-controller-linux/brightness_controller_linux/util/resource_provider.py +++ b/brightness-controller-linux/brightness_controller_linux/util/resource_provider.py @@ -1,7 +1,7 @@ from importlib import resources from pathlib import Path -import brightness_controller_linux.icons as icons +import icons as icons def icon_path(module_name=icons): diff --git a/brightness-controller-linux/poetry.lock b/brightness-controller-linux/poetry.lock index 58f2a9b..68ad105 100644 --- a/brightness-controller-linux/poetry.lock +++ b/brightness-controller-linux/poetry.lock @@ -1,40 +1,54 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + [[package]] name = "attrs" version = "22.1.0" description = "Classes Without Boilerplate" -category = "dev" optional = false python-versions = ">=3.5" +files = [ + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, +] [package.extras] dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] name = "colorama" version = "0.4.5" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, + {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, +] [[package]] name = "iniconfig" version = "1.1.1" description = "iniconfig: brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = "*" +files = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] [[package]] name = "packaging" version = "21.3" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] [package.dependencies] pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" @@ -43,9 +57,12 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] [package.extras] dev = ["pre-commit", "tox"] @@ -55,17 +72,23 @@ testing = ["pytest", "pytest-benchmark"] name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] [[package]] name = "pyparsing" version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" optional = false python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] [package.extras] diagrams = ["jinja2", "railroad-diagrams"] @@ -74,9 +97,15 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "PyQt5" version = "5.15.7" description = "Python bindings for the Qt cross platform application toolkit" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "PyQt5-5.15.7-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:1a793748c60d5aff3850b7abf84d47c1d41edb11231b7d7c16bef602c36be643"}, + {file = "PyQt5-5.15.7-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:e319c9d8639e0729235c1b09c99afdadad96fa3dbd8392ab561b5ab5946ee6ef"}, + {file = "PyQt5-5.15.7-cp37-abi3-win32.whl", hash = "sha256:08694f0a4c7d4f3d36b2311b1920e6283240ad3b7c09b515e08262e195dcdf37"}, + {file = "PyQt5-5.15.7-cp37-abi3-win_amd64.whl", hash = "sha256:232fe5b135a095cbd024cf341d928fc672c963f88e6a52b0c605be8177c2fdb5"}, + {file = "PyQt5-5.15.7.tar.gz", hash = "sha256:755121a52b3a08cb07275c10ebb96576d36e320e572591db16cfdbc558101594"}, +] [package.dependencies] PyQt5-Qt5 = ">=5.15.0" @@ -86,25 +115,55 @@ PyQt5-sip = ">=12.11,<13" name = "PyQt5-Qt5" version = "5.15.2" description = "The subset of a Qt installation needed by PyQt5." -category = "main" optional = false python-versions = "*" +files = [ + {file = "PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962"}, +] [[package]] name = "PyQt5-sip" version = "12.11.0" description = "The sip module support for PyQt5" -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "PyQt5_sip-12.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f9e312ff8284d6dfebc5366f6f7d103f84eec23a4da0be0482403933e68660"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:4031547dfb679be309094bfa79254f5badc5ddbe66b9ad38e319d84a7d612443"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-win32.whl", hash = "sha256:ad21ca0ee8cae2a41b61fc04949dccfab6fe008749627d94e8c7078cb7a73af1"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3126c84568ab341c12e46ded2230f62a9a78752a70fdab13713f89a71cd44f73"}, + {file = "PyQt5_sip-12.11.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bd733667098cac70e89279d9c239106d543fb480def62a44e6366ccb8f68510b"}, + {file = "PyQt5_sip-12.11.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec1d8ce50be76c5c1d1c86c6dc0ccacc2446172dde98b663a17871f532f9bd44"}, + {file = "PyQt5_sip-12.11.0-cp311-cp311-win32.whl", hash = "sha256:43dfe6dd409e713edeb67019b85419a7a0dc9923bfc451d6cf3778471c122532"}, + {file = "PyQt5_sip-12.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:afa4ffffc54e306669bf2b66ea37abbc56c5cdda4f3f474d20324e3634302b12"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0f77655c62ec91d47c2c99143f248624d44dd2d8a12d016e7c020508ad418aca"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ec5e9ef78852e1f96f86d7e15c9215878422b83dde36d44f1539a3062942f19c"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-win32.whl", hash = "sha256:d12b81c3a08abf7657a2ebc7d3649852a1f327eb2146ebadf45930486d32e920"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b69a1911f768b489846335e31e49eb34795c6b5a038ca24d894d751e3b0b44da"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e377789d59196213eddf458e6927f33ba9d217b614d17d20df16c9a8b2c41c"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4e5c1559311515291ea0ab0635529f14536954e3b973a7c7890ab7e4de1c2c23"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-win32.whl", hash = "sha256:9bca450c5306890cb002fe36bbca18f979dd9e5b810b766dce8e3ce5e66ba795"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:f6b72035da4e8fecbb0bc4a972e30a5674a9ad5608dbddaa517e983782dbf3bf"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9356260d4feb60dbac0ab66f8a791a0d2cda1bf98c9dec8e575904a045fbf7c5"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205f3e1b3eea3597d8e878936c1a06e04bd23a59e8b179ee806465d72eea3071"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-win32.whl", hash = "sha256:686071be054e5be6ca5aaaef7960931d4ba917277e839e2e978c7cbe3f43bb6e"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:42320e7a94b1085ed85d49794ed4ccfe86f1cae80b44a894db908a8aba2bc60e"}, + {file = "PyQt5_sip-12.11.0.tar.gz", hash = "sha256:b4710fd85b57edef716cc55fae45bfd5bfac6fc7ba91036f1dcc3f331ca0eb39"}, +] [[package]] name = "pytest" version = "7.1.3" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, +] [package.dependencies] attrs = ">=19.2.0" @@ -122,9 +181,12 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. name = "QtPy" version = "2.2.0" description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." -category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "QtPy-2.2.0-py3-none-any.whl", hash = "sha256:d283cfba378b0dbe36a55b68aea8ee2f86cd6ccf06c023af25bbe705ffbb29e5"}, + {file = "QtPy-2.2.0.tar.gz", hash = "sha256:d85f1b121f24a41ad26c55c446e66abdb7c528839f8c4f11f156ec4541903914"}, +] [package.dependencies] packaging = "*" @@ -136,85 +198,14 @@ test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" - -[metadata] -lock-version = "1.1" -python-versions = "^3.8" -content-hash = "6cb55fbae7c75eef595c187aa6c8b5487a0875c8feddee2d8d9697dd55a5748e" - -[metadata.files] -attrs = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, -] -colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -PyQt5 = [ - {file = "PyQt5-5.15.7-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:1a793748c60d5aff3850b7abf84d47c1d41edb11231b7d7c16bef602c36be643"}, - {file = "PyQt5-5.15.7-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:e319c9d8639e0729235c1b09c99afdadad96fa3dbd8392ab561b5ab5946ee6ef"}, - {file = "PyQt5-5.15.7-cp37-abi3-win32.whl", hash = "sha256:08694f0a4c7d4f3d36b2311b1920e6283240ad3b7c09b515e08262e195dcdf37"}, - {file = "PyQt5-5.15.7-cp37-abi3-win_amd64.whl", hash = "sha256:232fe5b135a095cbd024cf341d928fc672c963f88e6a52b0c605be8177c2fdb5"}, - {file = "PyQt5-5.15.7.tar.gz", hash = "sha256:755121a52b3a08cb07275c10ebb96576d36e320e572591db16cfdbc558101594"}, -] -PyQt5-Qt5 = [ - {file = "PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962"}, -] -PyQt5-sip = [ - {file = "PyQt5_sip-12.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f9e312ff8284d6dfebc5366f6f7d103f84eec23a4da0be0482403933e68660"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:4031547dfb679be309094bfa79254f5badc5ddbe66b9ad38e319d84a7d612443"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-win32.whl", hash = "sha256:ad21ca0ee8cae2a41b61fc04949dccfab6fe008749627d94e8c7078cb7a73af1"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3126c84568ab341c12e46ded2230f62a9a78752a70fdab13713f89a71cd44f73"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0f77655c62ec91d47c2c99143f248624d44dd2d8a12d016e7c020508ad418aca"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ec5e9ef78852e1f96f86d7e15c9215878422b83dde36d44f1539a3062942f19c"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-win32.whl", hash = "sha256:d12b81c3a08abf7657a2ebc7d3649852a1f327eb2146ebadf45930486d32e920"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b69a1911f768b489846335e31e49eb34795c6b5a038ca24d894d751e3b0b44da"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e377789d59196213eddf458e6927f33ba9d217b614d17d20df16c9a8b2c41c"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4e5c1559311515291ea0ab0635529f14536954e3b973a7c7890ab7e4de1c2c23"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-win32.whl", hash = "sha256:9bca450c5306890cb002fe36bbca18f979dd9e5b810b766dce8e3ce5e66ba795"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:f6b72035da4e8fecbb0bc4a972e30a5674a9ad5608dbddaa517e983782dbf3bf"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9356260d4feb60dbac0ab66f8a791a0d2cda1bf98c9dec8e575904a045fbf7c5"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205f3e1b3eea3597d8e878936c1a06e04bd23a59e8b179ee806465d72eea3071"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-win32.whl", hash = "sha256:686071be054e5be6ca5aaaef7960931d4ba917277e839e2e978c7cbe3f43bb6e"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:42320e7a94b1085ed85d49794ed4ccfe86f1cae80b44a894db908a8aba2bc60e"}, - {file = "PyQt5_sip-12.11.0.tar.gz", hash = "sha256:b4710fd85b57edef716cc55fae45bfd5bfac6fc7ba91036f1dcc3f331ca0eb39"}, -] -pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, -] -QtPy = [ - {file = "QtPy-2.2.0-py3-none-any.whl", hash = "sha256:d283cfba378b0dbe36a55b68aea8ee2f86cd6ccf06c023af25bbe705ffbb29e5"}, - {file = "QtPy-2.2.0.tar.gz", hash = "sha256:d85f1b121f24a41ad26c55c446e66abdb7c528839f8c4f11f156ec4541903914"}, -] -tomli = [ +files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "f9db7aab91a3ce3666d74a685330a389ce052d2aadc35266d12518d9edd4f71d" diff --git a/brightness-controller-linux/pyproject.toml b/brightness-controller-linux/pyproject.toml index 05dcfbb..642d5cd 100644 --- a/brightness-controller-linux/pyproject.toml +++ b/brightness-controller-linux/pyproject.toml @@ -3,7 +3,7 @@ name = "brightness-controller-linux" version = "2.4" description = "Using Brightness Controller, you can control brightness of both primary and external displays in Linux. Check it out!" authors = ["Amit "] -readme = "readme.md" +readme = "README.md" homepage = "https://github.com/LordAmit/Brightness" repository = "https://github.com/LordAmit/Brightness" keywords = [