Consolidated GUI

This commit is contained in:
Ircama 2024-07-29 03:29:30 +02:00
parent ea967238ef
commit 67e023bb28
6 changed files with 367 additions and 106 deletions

View file

@ -55,35 +55,64 @@ It is tested with Ubuntu / Windows Subsystem for Linux, Windows.
## Creating an executable for the GUI ## Creating an executable for the GUI
Install pyinstaller if not already installed with `pip install pyinstaller`. Install *pyinstaller* with `pip install pyinstaller`.
Run: `pyinstaller --onefile --noconsole ui.py`. To create an executable file named *epson_print_conf.exe* from *ui.py*, run the following:
Run the exe file created in the *dist/* folder. ```bash
pyinstaller --onefile ui.py --name epson_print_conf --hidden-import babel.numbers --windowed
```
Then run the *epson_print_conf.exe* file created in the *dist/* folder, which has the same options of `ui.py`.
The package includes another file named *gui.py*, which also automatically loads the configuration file *printer_conf.pickle*, merging it with the program configuration. In this case, the *epson_print_conf.spec* file helps creating an executable with *pyinstaller*.
Run the following to build the executable:
```bash
pip install pyinstaller # if not yet installed
curl -o devices.xml https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d
python3 parse_devices.py -a 192.168.178.29 -s XP-205 -p printer_conf.pickle # use your default IP address and printer model as default settings for the GUI
pyinstaller epson_print_conf.spec
```
Run the *epson_print_conf.exe* file created in the *dist/* folder. This executable program does not have options, embeds the *printer_conf.pickle* file and starts with the default IP address and printer model defined in the build phase.
## Usage ## Usage
Running the GUI: ### Running the GUI with Python
``` ```
python ui.py python ui.py
``` ```
Using the command-line tool: GUI usage:
``` ```
usage: epson_print_conf.py [-h] -m MODEL -a HOSTNAME [-p PORT] [-i] [-q QUERY_NAME] [--reset_waste_ink] [-d] ui.py [-h] [-P PICKLE_FILE] [-O]
[--write-first-ti-received-time YEAR MONTH DAY] [--write-poweroff-timer MINUTES]
[--dry-run] [-R ADDRESS_SET] [-W ADDRESS_VALUE_SET] optional arguments:
[-e FIRST_ADDRESS LAST_ADDRESS] [--detect-key] [-S SEQUENCE_STRING] [-t TIMEOUT] -h, --help show this help message and exit
[-r RETRIES] [-c CONFIG_FILE] [--simdata SIMDATA_FILE] -P PICKLE_FILE, --pickle PICKLE_FILE
Save a pickle archive for subsequent load by ui.py and epson_print_conf.py
-O, --override Override the default configuration with the one of the pickle file instead of merging
epson_print_conf GUI
```
### Using the command-line tool
```
epson_print_conf.py [-h] -m MODEL -a HOSTNAME [-p PORT] [-i] [-q QUERY_NAME] [--reset_waste_ink] [-d] [--write-first-ti-received-time YEAR MONTH DAY]
[--write-poweroff-timer MINUTES] [--dry-run] [-R ADDRESS_SET] [-W ADDRESS_VALUE_SET] [-e FIRST_ADDRESS LAST_ADDRESS] [--detect-key]
[-S SEQUENCE_STRING] [-t TIMEOUT] [-r RETRIES] [-c CONFIG_FILE] [--simdata SIMDATA_FILE] [-P PICKLE_FILE] [-O]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
-m MODEL, --model MODEL -m MODEL, --model MODEL
Printer model. Example: -m XP-205 (use ? to print all supported models) Printer model. Example: -m XP-205 (use ? to print all supported models)
-a HOSTNAME, --address HOSTNAME -a HOSTNAME, --address HOSTNAME
Printer host name or IP address. (Example: -m 192.168.1.87) Printer host name or IP address. (Example: -a 192.168.1.87)
-p PORT, --port PORT Printer port (default is 161) -p PORT, --port PORT Printer port (default is 161)
-i, --info Print all available information and statistics (default option) -i, --info Print all available information and statistics (default option)
-q QUERY_NAME, --query QUERY_NAME -q QUERY_NAME, --query QUERY_NAME
@ -98,8 +127,7 @@ optional arguments:
-R ADDRESS_SET, --read-eeprom ADDRESS_SET -R ADDRESS_SET, --read-eeprom ADDRESS_SET
Read the values of a list of printer EEPROM addreses. Format is: address [, ...] Read the values of a list of printer EEPROM addreses. Format is: address [, ...]
-W ADDRESS_VALUE_SET, --write-eeprom ADDRESS_VALUE_SET -W ADDRESS_VALUE_SET, --write-eeprom ADDRESS_VALUE_SET
Write related values to a list of printer EEPROM addresses. Format is: address: value Write related values to a list of printer EEPROM addresses. Format is: address: value [, ...]
[, ...]
-e FIRST_ADDRESS LAST_ADDRESS, --eeprom-dump FIRST_ADDRESS LAST_ADDRESS -e FIRST_ADDRESS LAST_ADDRESS, --eeprom-dump FIRST_ADDRESS LAST_ADDRESS
Dump EEPROM Dump EEPROM
--detect-key Detect the read_key via brute force --detect-key Detect the read_key via brute force
@ -110,10 +138,12 @@ optional arguments:
-r RETRIES, --retries RETRIES -r RETRIES, --retries RETRIES
SNMP GET retries (floating point argument) SNMP GET retries (floating point argument)
-c CONFIG_FILE, --config CONFIG_FILE -c CONFIG_FILE, --config CONFIG_FILE
read a configuration file including the full log dump of a previous operation with read a configuration file including the full log dump of a previous operation with '-d' flag (instead of accessing the printer via SNMP)
'-d' flag (instead of accessing the printer via SNMP)
--simdata SIMDATA_FILE --simdata SIMDATA_FILE
write SNMP dictionary map to simdata file write SNMP dictionary map to simdata file
-P PICKLE_FILE, --pickle PICKLE_FILE
Load a pickle configuration archive
-O, --override Override the default configuration with the one of the pickle file instead of merging
Epson Printer Configuration via SNMP (TCP/IP) Epson Printer Configuration via SNMP (TCP/IP)
``` ```
@ -160,7 +190,7 @@ Note: resetting the ink waste counter is just removing a warning; not replacing
Within an [issue](https://codeberg.org/atufi/reinkpy/issues/12#issue-716809) in repo https://codeberg.org/atufi/reinkpy there is an interesting [attachment](https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d) which reports an extensive XML database of Epson model features. Within an [issue](https://codeberg.org/atufi/reinkpy/issues/12#issue-716809) in repo https://codeberg.org/atufi/reinkpy there is an interesting [attachment](https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25bac4495a1d) which reports an extensive XML database of Epson model features.
The program "parse_devices.py" transforms this XML DB into the dictionary that *epson_print_conf.py* can use. The program *parse_devices.py* transforms this XML DB into the dictionary that *epson_print_conf.py* can use.
Here is a simple procedure to download that DB and run *parse_devices.py* to search for the XP-205 model and produce the related PRINTER_CONFIG dictionary to the standard output: Here is a simple procedure to download that DB and run *parse_devices.py* to search for the XP-205 model and produce the related PRINTER_CONFIG dictionary to the standard output:
@ -169,14 +199,15 @@ curl -o devices.xml https://codeberg.org/attachments/147f41a3-a6ea-45f6-8c2a-25b
python3 parse_devices.py -i -m XP-205 python3 parse_devices.py -i -m XP-205
``` ```
After generating the related printer configuration, *epson_print_conf.py* shall be manually edited to copy/paste the output of *parse_devices.py* within its PRINTER_CONFIG dictionary. After generating the related printer configuration, *epson_print_conf.py* shall be manually edited to copy/paste the output of *parse_devices.py* within its PRINTER_CONFIG dictionary. Alternatively, the program is able to create a *pickle* configuration file, which the other programs can load.
The `-m` option is optional and is used to filter the printer model in scope. If the produced output is not referred to the target model, use part of the model name as a filter (e.g., only the digits, like `parse_devices.py -i -m 315`) and select the appropriate model from the output. The `-m` option is optional and is used to filter the printer model in scope. If the produced output is not referred to the target model, use part of the model name as a filter (e.g., only the digits, like `parse_devices.py -i -m 315`) and select the appropriate model from the output.
Program usage: Program usage:
``` ```
parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE] parse_devices.py [-h] [-m PRINTER_MODEL] [-l LINE_LENGTH] [-i] [-d] [-t] [-v] [-f] [-e] [-c CONFIG_FILE] [-s DEFAULT_MODEL] -a HOSTNAME [-p PICKLE_FILE] [-I]
[-N] [-A] [-S]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
@ -192,6 +223,16 @@ optional arguments:
-e, --errors Add last_printer_fatal_errors -e, --errors Add last_printer_fatal_errors
-c CONFIG_FILE, --config CONFIG_FILE -c CONFIG_FILE, --config CONFIG_FILE
use the XML configuration file to generate the configuration use the XML configuration file to generate the configuration
-s DEFAULT_MODEL, --default_model DEFAULT_MODEL
Default printer model. Example: -s XP-205
-a HOSTNAME, --address HOSTNAME
Default printer host name or IP address. (Example: -a 192.168.1.87)
-p PICKLE_FILE, --pickle PICKLE_FILE
Save a pickle archive for subsequent load by ui.py and epson_print_conf.py
-I, --keep_invalid Do not remove printers without write_key or without read_key
-N, --keep_names Do not replace original names with converted names and add printers for all optional names
-A, --no_alias Do not add aliases for same printer with different names and remove aliased printers
-S, --no_same_as Do not add "same-as" for similar printers with different names
Generate printer configuration from devices.xml Generate printer configuration from devices.xml
``` ```
@ -316,9 +357,11 @@ AC = Value
### Specification ### Specification
```python ```python
EpsonPrinter(model, hostname, port, timeout, retries, dry_run) EpsonPrinter(conf_dict, replace_conf, model, hostname, port, timeout, retries, dry_run)
``` ```
- `conf_dict`: optional configuration file in place of the default PRINTER_CONFIG (optional, default to `{}`)
- `replace_conf`: (optional, default to False) set to True to replace PRINTER_CONFIG with `conf_dict` instead of merging it
- `model`: printer model - `model`: printer model
- `hostname`: IP address or network name of the printer - `hostname`: IP address or network name of the printer
- `port`: SNMP port number (default is 161) - `port`: SNMP port number (default is 161)

View file

@ -643,6 +643,8 @@ class EpsonPrinter:
def __init__( def __init__(
self, self,
conf_dict: dict = {},
replace_conf = False,
model: str = None, model: str = None,
hostname: str = None, hostname: str = None,
port: int = 161, port: int = 161,
@ -651,7 +653,19 @@ class EpsonPrinter:
dry_run: bool = False dry_run: bool = False
) -> None: ) -> None:
"""Initialise printer model.""" """Initialise printer model."""
def merge(source, destination):
for key, value in source.items():
if isinstance(value, dict):
merge(value, destination.setdefault(key, {}))
else:
if key == "alias" and "alias" in destination:
destination[key] += value
else:
destination[key] = value
return destination
# process "alias" definintion # process "alias" definintion
if conf_dict and replace_conf:
self.PRINTER_CONFIG = conf_dict
for printer_name, printer_data in self.PRINTER_CONFIG.copy().items(): for printer_name, printer_data in self.PRINTER_CONFIG.copy().items():
if "alias" in printer_data: if "alias" in printer_data:
aliases = printer_data["alias"] aliases = printer_data["alias"]
@ -672,6 +686,16 @@ class EpsonPrinter:
) )
else: else:
self.PRINTER_CONFIG[alias_name] = printer_data self.PRINTER_CONFIG[alias_name] = printer_data
if conf_dict and not replace_conf:
self.PRINTER_CONFIG = merge(self.PRINTER_CONFIG, conf_dict)
for key, values in self.PRINTER_CONFIG.items():
if 'alias' in values:
values['alias'] = [
i for i in values['alias']
if i not in self.PRINTER_CONFIG
]
if not values['alias']:
del values['alias']
# process "same-as" definintion # process "same-as" definintion
for printer_name, printer_data in self.PRINTER_CONFIG.copy().items(): for printer_name, printer_data in self.PRINTER_CONFIG.copy().items():
if "same-as" in printer_data: if "same-as" in printer_data:
@ -2035,7 +2059,7 @@ if __name__ == "__main__":
'--address', '--address',
dest='hostname', dest='hostname',
action="store", action="store",
help='Printer host name or IP address. (Example: -m 192.168.1.87)', help='Printer host name or IP address. (Example: -a 192.168.1.87)',
required=True) required=True)
parser.add_argument( parser.add_argument(
'-p', '-p',
@ -2174,6 +2198,24 @@ if __name__ == "__main__":
nargs=1, nargs=1,
metavar='SIMDATA_FILE' metavar='SIMDATA_FILE'
) )
parser.add_argument(
'-P',
"--pickle",
dest='pickle',
type=argparse.FileType('rb'),
help="Load a pickle configuration archive",
default=None,
nargs=1,
metavar='PICKLE_FILE'
)
parser.add_argument(
'-O',
"--override",
dest='override',
action='store_true',
help="Override the default configuration with the one of the pickle "
"file instead of merging",
)
args = parser.parse_args() args = parser.parse_args()
logging_level = logging.WARNING logging_level = logging.WARNING
@ -2198,7 +2240,13 @@ if __name__ == "__main__":
if args.debug: if args.debug:
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
conf_dict = {}
if args.pickle:
conf_dict = pickle.load(args.pickle[0])
printer = EpsonPrinter( printer = EpsonPrinter(
conf_dict=conf_dict,
replace_conf=args.override,
model=args.model, model=args.model,
hostname=args.hostname, hostname=args.hostname,
port=args.port, port=args.port,

11
gui.py Normal file
View file

@ -0,0 +1,11 @@
import pickle
from ui import EpsonPrinterUI
from os import path
PICKLE_CONF_FILE = "printer_conf.pickle"
path_to_pickle = path.abspath(path.join(path.dirname(__file__), PICKLE_CONF_FILE))
with open(path_to_pickle, 'rb') as fp:
conf_dict = pickle.load(fp)
app = EpsonPrinterUI(conf_dict=conf_dict, replace_conf=False)
app.mainloop()

View file

@ -219,71 +219,81 @@ def generate_config(config, traverse, add_fatal_errors, full, printer_model):
printer_config[printer_short_name] = chars printer_config[printer_short_name] = chars
return printer_config return printer_config
def normalize_config(config): def normalize_config(
config,
remove_invalid,
expand_names,
add_alias,
add_same_as,
):
# Remove printers without write_key or without read_key # Remove printers without write_key or without read_key
for base_key, base_items in config.copy().items(): if remove_invalid:
if 'write_key' not in base_items: for base_key, base_items in config.copy().items():
del config[base_key] if 'write_key' not in base_items:
continue del config[base_key]
if 'read_key' not in base_items: continue
del config[base_key] if 'read_key' not in base_items:
continue del config[base_key]
continue
# Replace original names with converted names and add printers for all optional names # Replace original names with converted names and add printers for all optional names
for key, items in config.copy().items(): if expand_names:
printer_list = get_printer_models(key) for key, items in config.copy().items():
del config[key] printer_list = get_printer_models(key)
for i in printer_list: del config[key]
if i in config and config[i] != items: for i in printer_list:
print("ERROR key", key) if i in config and config[i] != items:
quit() print("ERROR key", key)
config[i] = items quit()
config[i] = items
# Add aliases for same printer with different names and remove aliased printers # Add aliases for same printer with different names and remove aliased printers
for base_key, base_items in config.copy().items(): if add_alias:
found = False for base_key, base_items in config.copy().items():
for key, items in config.copy().items(): found = False
if not found: for key, items in config.copy().items():
if base_key == key and base_key in config: if not found:
found = True if base_key == key and base_key in config:
continue found = True
if base_key != key and items == base_items: # different name, same printer continue
if "alias" not in config[base_key]: if base_key != key and items == base_items: # different name, same printer
config[base_key]["alias"] = [] if "alias" not in config[base_key]:
for i in get_printer_models(key): config[base_key]["alias"] = []
if i not in config[base_key]["alias"]: for i in get_printer_models(key):
config[base_key]["alias"].append(i) if i not in config[base_key]["alias"]:
del config[key] config[base_key]["alias"].append(i)
del config[key]
# Add "same-as" for almost same printer (IGNORED_KEYS) with different names # Add "same-as" for almost same printer (IGNORED_KEYS) with different names
IGNORED_KEYS = ['write_key', 'read_key', 'alias', 'main_waste', 'borderless_waste'] if add_same_as:
for base_key, base_items in config.copy().items(): IGNORED_KEYS = ['write_key', 'read_key', 'alias', 'main_waste', 'borderless_waste']
found = False for base_key, base_items in config.copy().items():
for key, items in config.copy().items(): found = False
if not found: for key, items in config.copy().items():
if base_key == key and base_key in config: if not found:
found = True if base_key == key and base_key in config:
continue found = True
if base_key != key: continue
if equal_dicts(base_items, items, IGNORED_KEYS): # everything but the IGNORED_KEYS is the same if base_key != key:
# Get the IGNORED_KEYS from the printer if equal_dicts(base_items, items, IGNORED_KEYS): # everything but the IGNORED_KEYS is the same
write_key = base_items['write_key'] # Get the IGNORED_KEYS from the printer
read_key = base_items['read_key'] write_key = base_items['write_key']
alias = base_items['alias'] if 'alias' in base_items else [] read_key = base_items['read_key']
main_waste = base_items['main_waste'] if 'main_waste' in base_items else [] alias = base_items['alias'] if 'alias' in base_items else []
borderless_waste = base_items['borderless_waste'] if 'borderless_waste' in base_items else [] main_waste = base_items['main_waste'] if 'main_waste' in base_items else []
# Rebuild the printer with only the IGNORED_KEYS, then add the 'same-as' borderless_waste = base_items['borderless_waste'] if 'borderless_waste' in base_items else []
del config[base_key] # Rebuild the printer with only the IGNORED_KEYS, then add the 'same-as'
config[base_key] = {} del config[base_key]
config[base_key]['write_key'] = write_key config[base_key] = {}
config[base_key]['read_key'] = read_key config[base_key]['write_key'] = write_key
if alias: config[base_key]['read_key'] = read_key
config[base_key]['alias'] = alias if alias:
if main_waste: config[base_key]['alias'] = alias
config[base_key]['main_waste'] = main_waste if main_waste:
if borderless_waste: config[base_key]['main_waste'] = main_waste
config[base_key]['borderless_waste'] = borderless_waste if borderless_waste:
config[base_key]['same-as'] = key config[base_key]['borderless_waste'] = borderless_waste
config[base_key]['same-as'] = key
return config return config
@ -294,69 +304,69 @@ def equal_dicts(a, b, ignore_keys):
if __name__ == "__main__": if __name__ == "__main__":
import argparse import argparse
import pickle
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
epilog='Generate printer configuration from devices.xml' epilog='Generate printer configuration from devices.xml'
) )
parser.add_argument( parser.add_argument(
'-m', '-m',
'--model', '--model',
dest='printer_model', dest='printer_model',
default=False, default=False,
action="store", action="store",
help='Printer model. Example: -m XP-205') help='Printer model. Example: -m XP-205'
)
parser.add_argument( parser.add_argument(
'-l', '-l',
'--line', '--line',
dest='line_length', dest='line_length',
type=int, type=int,
help='Set line length of the output (default: 120)', help='Set line length of the output (default: 120)',
default=120) default=120
)
parser.add_argument( parser.add_argument(
'-i', '-i',
'--indent', '--indent',
dest='indent', dest='indent',
action='store_true', action='store_true',
help='Indent output of 4 spaces') help='Indent output of 4 spaces'
)
parser.add_argument( parser.add_argument(
'-d', '-d',
'--debug', '--debug',
dest='debug', dest='debug',
action='store_true', action='store_true',
help='Print debug information') help='Print debug information'
)
parser.add_argument( parser.add_argument(
'-t', '-t',
'--traverse', '--traverse',
dest='traverse', dest='traverse',
action='store_true', action='store_true',
help='Traverse the XML, dumping content related to the printer model') help='Traverse the XML, dumping content related to the printer model'
)
parser.add_argument( parser.add_argument(
'-v', '-v',
'--verbose', '--verbose',
dest='verbose', dest='verbose',
action='store_true', action='store_true',
help='Print verbose information') help='Print verbose information'
)
parser.add_argument( parser.add_argument(
'-f', '-f',
'--full', '--full',
dest='full', dest='full',
action='store_true', action='store_true',
help='Generate additional tags') help='Generate additional tags'
)
parser.add_argument( parser.add_argument(
'-e', '-e',
'--errors', '--errors',
dest='add_fatal_errors', dest='add_fatal_errors',
action='store_true', action='store_true',
help='Add last_printer_fatal_errors') help='Add last_printer_fatal_errors'
)
parser.add_argument( parser.add_argument(
'-c', '-c',
"--config", "--config",
@ -367,6 +377,59 @@ if __name__ == "__main__":
nargs=1, nargs=1,
metavar='CONFIG_FILE' metavar='CONFIG_FILE'
) )
parser.add_argument(
'-s',
'--default_model',
dest='default_model',
action="store",
help='Default printer model. Example: -s XP-205'
)
parser.add_argument(
'-a',
'--address',
dest='hostname',
action="store",
help='Default printer host name or IP address. (Example: -a 192.168.1.87)',
required=True
)
parser.add_argument(
'-p',
"--pickle",
dest='pickle',
type=argparse.FileType('wb'),
help="Save a pickle archive for subsequent load by ui.py and epson_print_conf.py",
default=0,
nargs=1,
metavar='PICKLE_FILE'
)
parser.add_argument(
'-I',
'--keep_invalid',
dest='keep_invalid',
action='store_true',
help='Do not remove printers without write_key or without read_key'
)
parser.add_argument(
'-N',
'--keep_names',
dest='keep_names',
action='store_true',
help='Do not replace original names with converted names and add printers for all optional names'
)
parser.add_argument(
'-A',
'--no_alias',
dest='no_alias',
action='store_true',
help='Do not add aliases for same printer with different names and remove aliased printers'
)
parser.add_argument(
'-S',
'--no_same_as',
dest='no_same_as',
action='store_true',
help='Do not add "same-as" for similar printers with different names'
)
args = parser.parse_args() args = parser.parse_args()
if args.debug: if args.debug:
@ -390,7 +453,26 @@ if __name__ == "__main__":
full=args.full, full=args.full,
printer_model=args.printer_model printer_model=args.printer_model
) )
normalized_config = normalize_config(printer_config) normalized_config = normalize_config(
config=printer_config,
remove_invalid=not args.keep_invalid,
expand_names=not args.keep_names,
add_alias=not args.no_alias,
add_same_as=not args.no_same_as,
)
if args.default_model:
if "internal_data" not in normalized_config:
normalized_config["internal_data"] = {}
normalized_config["internal_data"]["default_model"] = args.default_model
if args.hostname:
if "internal_data" not in normalized_config:
normalized_config["internal_data"] = {}
normalized_config["internal_data"]["hostname"] = args.hostname
if args.pickle:
pickle.dump(normalized_config, args.pickle[0]) # serialize the list
args.pickle[0].close()
quit()
try: try:
import black import black
config_str = "PRINTER_CONFIG = " + repr(normalized_config) config_str = "PRINTER_CONFIG = " + repr(normalized_config)

BIN
printer_conf.pickle Normal file

Binary file not shown.

97
ui.py
View file

@ -125,7 +125,7 @@ class ToolTip:
class EpsonPrinterUI(tk.Tk): class EpsonPrinterUI(tk.Tk):
def __init__(self): def __init__(self, conf_dict={}, replace_conf=False):
super().__init__() super().__init__()
self.title("Epson Printer Configuration - v" + VERSION) self.title("Epson Printer Configuration - v" + VERSION)
self.geometry("450x500") self.geometry("450x500")
@ -133,6 +133,8 @@ class EpsonPrinterUI(tk.Tk):
self.printer_scanner = PrinterScanner() self.printer_scanner = PrinterScanner()
self.ip_list = [] self.ip_list = []
self.ip_list_cycle = None self.ip_list_cycle = None
self.conf_dict = conf_dict
self.replace_conf = replace_conf
# configure the main window to be resizable # configure the main window to be resizable
self.columnconfigure(0, weight=1) self.columnconfigure(0, weight=1)
@ -167,13 +169,21 @@ class EpsonPrinterUI(tk.Tk):
model_frame.columnconfigure(1, weight=1) model_frame.columnconfigure(1, weight=1)
self.model_var = tk.StringVar() self.model_var = tk.StringVar()
if (
"internal_data" in conf_dict
and "default_model" in conf_dict["internal_data"]
):
self.model_var.set(conf_dict["internal_data"]["default_model"])
ttk.Label(model_frame, text="Model:").grid( ttk.Label(model_frame, text="Model:").grid(
row=0, column=0, sticky=tk.W, padx=PADX row=0, column=0, sticky=tk.W, padx=PADX
) )
self.model_dropdown = ttk.Combobox( self.model_dropdown = ttk.Combobox(
model_frame, textvariable=self.model_var, state="readonly" model_frame, textvariable=self.model_var, state="readonly"
) )
self.model_dropdown["values"] = sorted(EpsonPrinter().valid_printers) self.model_dropdown["values"] = sorted(EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf
).valid_printers)
self.model_dropdown.grid( self.model_dropdown.grid(
row=0, column=1, pady=PADY, padx=PADX, sticky=(tk.W, tk.E) row=0, column=1, pady=PADY, padx=PADX, sticky=(tk.W, tk.E)
) )
@ -193,6 +203,11 @@ class EpsonPrinterUI(tk.Tk):
ip_frame.columnconfigure(1, weight=1) ip_frame.columnconfigure(1, weight=1)
self.ip_var = tk.StringVar() self.ip_var = tk.StringVar()
if (
"internal_data" in conf_dict
and "hostname" in conf_dict["internal_data"]
):
self.ip_var.set(conf_dict["internal_data"]["hostname"])
ttk.Label(ip_frame, text="IP Address:").grid( ttk.Label(ip_frame, text="IP Address:").grid(
row=0, column=0, sticky=tk.W, padx=PADX row=0, column=0, sticky=tk.W, padx=PADX
) )
@ -446,7 +461,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update() self.update()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
po_timer = printer.stats()["stats"]["Power off timer"] po_timer = printer.stats()["stats"]["Power off timer"]
self.status_text.insert( self.status_text.insert(
@ -478,7 +498,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update_idletasks() self.update_idletasks()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
po_timer = printer.stats()["stats"]["Power off timer"] po_timer = printer.stats()["stats"]["Power off timer"]
po_timer = self.po_timer_var.get() po_timer = self.po_timer_var.get()
@ -525,7 +550,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update_idletasks() self.update_idletasks()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
date_string = datetime.strptime( date_string = datetime.strptime(
printer.stats()["stats"]["First TI received time"], "%d %b %Y" printer.stats()["stats"]["First TI received time"], "%d %b %Y"
@ -560,7 +590,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update_idletasks() self.update_idletasks()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
date_string = datetime.strptime( date_string = datetime.strptime(
printer.stats()["stats"]["First TI received time"], "%d %b %Y" printer.stats()["stats"]["First TI received time"], "%d %b %Y"
@ -624,7 +659,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update_idletasks() self.update_idletasks()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
self.show_treeview() self.show_treeview()
@ -662,7 +702,12 @@ class EpsonPrinterUI(tk.Tk):
self.config(cursor="") self.config(cursor="")
self.update_idletasks() self.update_idletasks()
return return
printer = EpsonPrinter(model=model, hostname=ip_address) printer = EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf,
model=model,
hostname=ip_address
)
try: try:
printer.stats() # query the printer first printer.stats() # query the printer first
response = messagebox.askyesno( response = messagebox.askyesno(
@ -714,7 +759,10 @@ class EpsonPrinterUI(tk.Tk):
) )
self.ip_var.set(printers[0]["ip"]) self.ip_var.set(printers[0]["ip"])
for model in get_printer_models(printers[0]["name"]): for model in get_printer_models(printers[0]["name"]):
if model in EpsonPrinter().valid_printers: if model in EpsonPrinter(
conf_dict=self.conf_dict,
replace_conf=self.replace_conf
).valid_printers:
self.model_var.set(model) self.model_var.set(model)
break break
else: else:
@ -835,5 +883,34 @@ class EpsonPrinterUI(tk.Tk):
if __name__ == "__main__": if __name__ == "__main__":
app = EpsonPrinterUI() import argparse
import pickle
parser = argparse.ArgumentParser(
epilog='epson_print_conf GUI'
)
parser.add_argument(
'-P',
"--pickle",
dest='pickle',
type=argparse.FileType('rb'),
help="Save a pickle archive for subsequent load by ui.py and epson_print_conf.py",
default=None,
nargs=1,
metavar='PICKLE_FILE'
)
parser.add_argument(
'-O',
"--override",
dest='override',
action='store_true',
help="Override the default configuration with the one of the pickle "
"file instead of merging",
)
args = parser.parse_args()
conf_dict = {}
if args.pickle:
conf_dict = pickle.load(args.pickle[0])
app = EpsonPrinterUI(conf_dict=conf_dict, replace_conf=args.override)
app.mainloop() app.mainloop()