Skip to content

Commit b350b08

Browse files
committed
+ One-click config creation
1 parent 1d11012 commit b350b08

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ Path to config can be configured with `-c`/`--config` params on start
3030
BulkStartStop.exe --config path/to/config.json
3131
```
3232

33-
Path to rules list file can be set with config.
33+
Path to rules list file can be set with config.
34+
35+
Use `Make new config` button for that purpose.

main.py

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import os.path
44
import re
55
import shlex
6+
import subprocess
67
import sys
8+
import textwrap
79
import tkinter as tk
810
import tkinter.filedialog
911
import tkinter.ttk as ttk
1012
import winreg
1113
import argparse
14+
1215
from WinJobster import Process
1316
import jsons
1417

@@ -68,7 +71,9 @@ def load(self):
6871
with open(self.filename, 'r', encoding='utf-8-sig') as file:
6972
self.config = jsons.loads(file.read(), Config)
7073
except OSError:
71-
pass
74+
self.save()
75+
except jsons.DeserializationError:
76+
self.save()
7277

7378
def save(self):
7479
with open(self.filename, 'w', encoding='utf-8-sig') as file:
@@ -164,6 +169,10 @@ def save_settings(self):
164169
self._config_storage.save()
165170

166171

172+
def open_path(path):
173+
os.system(f'explorer /select,"{os.path.normpath(path)}"')
174+
175+
167176
class AppView(ttk.Frame):
168177
def __init__(self, parent, app: ProcessModel,
169178
toggle_callback, delete_callback):
@@ -183,7 +192,7 @@ def __init__(self, parent, app: ProcessModel,
183192
).pack(side=tk.LEFT, padx=4, pady=8)
184193
self.open_folder_btn = ttk.Button(
185194
master=self, text="Open folder",
186-
command=lambda: self.open_app_path(self.app.path)
195+
command=lambda: open_path(self.app.path)
187196
)
188197
self.open_folder_btn.pack(side=tk.LEFT, padx=4, pady=8)
189198
self.set_app(app)
@@ -207,8 +216,23 @@ def get_state(app: ProcessModel):
207216
return "ACTIVE"
208217
return "NOT ACTIVE"
209218

210-
def open_app_path(self, path):
211-
os.system(f'explorer /select,"{os.path.normpath(path)}"')
219+
220+
def make_shortcut(app_path: str, args: str, shortcut_path: str):
221+
workdir = os.path.dirname(app_path)
222+
command = textwrap.dedent(f"""
223+
Set objWS = WScript.CreateObject("WScript.Shell")
224+
Set objLink = objWS.CreateShortcut("{shortcut_path}")
225+
226+
objLink.TargetPath = "{app_path}"
227+
objLink.Arguments = "{args}"
228+
objLink.IconLocation = "{app_path}"
229+
objLink.WorkingDirectory = "{workdir}"
230+
objLink.Save
231+
""").strip()
232+
with open("make_shortcut.vbs", 'w') as f:
233+
f.write(command)
234+
os.system("CSCRIPT .\\make_shortcut.vbs")
235+
os.remove(".\\make_shortcut.vbs")
212236

213237

214238
class View(ttk.Frame):
@@ -238,6 +262,8 @@ def __init__(self, parent):
238262
variable=self.run_at_startup, command=lambda: self.controller.set_run_at_startup(bool(self.run_at_startup.get()))).pack(anchor="w")
239263
ttk.Checkbutton(master=bottom_bar, text="Kill all apps when program closed",
240264
variable=self.kill_on_close, command=lambda: self.controller.set_kill_on_close(bool(self.kill_on_close.get()))).pack(anchor="w")
265+
ttk.Button(master=bottom_bar, text="Make new config", command=self.make_new_config_callback)\
266+
.pack(anchor="w", pady=8)
241267
self._apps_stored = []
242268
self._apps_views = []
243269
self.refresh()
@@ -292,6 +318,33 @@ def get_apps_paths(self) -> tuple[str]:
292318
filetypes=(("Executable", ".exe .bat .cmd .url .lnk"), ("Other", "*.*"))
293319
) or tuple()
294320

321+
def make_new_config_callback(self):
322+
new_config = self.get_new_config_path()
323+
if not new_config:
324+
return
325+
new_config = os.path.normpath(new_config)
326+
config_dir = os.path.dirname(new_config)
327+
app_name = os.path.basename(sys.argv[0]).split(".")[0]
328+
config_name = os.path.basename(new_config).split(".")[0]
329+
config_storage = ConfigStorage(new_config)
330+
config_storage.config.rules_path = os.path.join(config_dir, config_storage.config.rules_path)
331+
config_storage.save()
332+
link_path = os.path.join(config_dir, f"New {app_name} for {config_name}.lnk")
333+
make_shortcut(
334+
sys.argv[0],
335+
f'-c ""{new_config}""',
336+
link_path
337+
)
338+
open_path(link_path)
339+
340+
def get_new_config_path(self) -> str:
341+
return tk.filedialog.asksaveasfilename(
342+
defaultextension="json",
343+
initialfile="config",
344+
filetypes=(("json", ".json",),),
345+
title='Save new config to',
346+
) or None
347+
295348
def delete_app_callback(self, app):
296349
self.controller.delete_app(app)
297350

@@ -350,11 +403,12 @@ def set_kill_on_close(self, value: bool):
350403
self.model.save_settings()
351404

352405

406+
353407
class App(tk.Tk):
354408
def __init__(self, args):
355409
super().__init__()
356410
self.title('Apps bulk start/stop')
357-
self.geometry('640x480')
411+
self.geometry('640x520')
358412
self.apply_theme()
359413
model = Model(args)
360414
view = View(self)

0 commit comments

Comments
 (0)