-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
163 lines (148 loc) · 5.97 KB
/
app.py
File metadata and controls
163 lines (148 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import logging
import os
import sys
import threading
import urllib.request
from typing import Optional
LOG = logging.getLogger("illogical-updots")
if not LOG.handlers:
level = logging.DEBUG if os.environ.get("UPDOTS_DEBUG") else logging.INFO
logging.basicConfig(level=level, format="%(levelname)s %(message)s")
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gio, GLib, Gtk
from main_window import (
APP_ID,
APP_TITLE,
REPO_PATH,
SETTINGS,
MainWindow,
_save_settings,
)
class App(Gtk.Application):
def __init__(self) -> None:
super().__init__(application_id=APP_ID)
GLib.set_prgname("illogical-updots")
GLib.set_application_name("Illogical Updots")
try:
Gtk.Window.set_default_icon_name("illogical-updots")
except Exception:
pass
def _try_set_icon_file(p: str) -> bool:
if p and os.path.isfile(p):
try:
Gtk.Window.set_default_icon_from_file(p)
return True
except Exception:
return False
return False
base_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [
"/usr/share/icons/hicolor/256x256/apps/illogical-updots.png",
"/usr/share/icons/hicolor/scalable/apps/illogical-updots.svg",
"/usr/share/pixmaps/illogical-updots.png",
os.path.join(base_dir, ".github", "assets", "logo.png"),
os.path.join(base_dir, "assets", "logo.png"),
]
if not any(_try_set_icon_file(p) for p in candidates):
cache_dir = os.path.join(os.path.expanduser("~/.cache"), "illogical-updots")
cache_path = os.path.join(cache_dir, "icon.png")
if not _try_set_icon_file(cache_path):
def _download_icon():
try:
os.makedirs(cache_dir, exist_ok=True)
url = "https://github.com/FoxyIsCoding/illogical-updots/blob/main/.github/assets/logo.png?raw=true"
urllib.request.urlretrieve(url, cache_path)
GLib.idle_add(lambda: _try_set_icon_file(cache_path))
except Exception:
pass
try:
threading.Thread(target=_download_icon, daemon=True).start()
except Exception:
pass
_icon_file = ".github/assets/logo.png"
if os.path.isfile(_icon_file):
try:
Gtk.Window.set_default_icon_from_file(_icon_file)
except Exception:
pass
def do_activate(self) -> None:
global REPO_PATH
if not SETTINGS.get("onboarding_shown") or not REPO_PATH or not os.path.isdir(REPO_PATH):
from dialogs.onboarding import show_onboarding_dialog
if not show_onboarding_dialog(None, SETTINGS):
alert = Gtk.MessageDialog(
transient_for=None,
flags=0,
message_type=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.NONE,
text="Repository not found",
)
alert.format_secondary_text(
"No repository path is configured.\n"
"Would you like to select your repository folder manually?"
)
alert.add_button("Cancel", Gtk.ResponseType.CANCEL)
alert.add_button("Select Manually", Gtk.ResponseType.OK)
resp_alert = alert.run()
alert.destroy()
if resp_alert != Gtk.ResponseType.OK:
return
chooser = Gtk.FileChooserDialog(
title="Select repository directory",
transient_for=None,
action=Gtk.FileChooserAction.SELECT_FOLDER,
)
chooser.add_buttons(
"Cancel", Gtk.ResponseType.CANCEL, "Select", Gtk.ResponseType.OK
)
try:
start_dir = os.path.expanduser("~")
if os.path.isdir(start_dir):
chooser.set_current_folder(start_dir)
except Exception:
pass
resp = chooser.run()
if resp == Gtk.ResponseType.OK:
chosen = chooser.get_filename()
if chosen and os.path.isdir(chosen):
SETTINGS["repo_path"] = chosen
_save_settings(SETTINGS)
REPO_PATH = chosen
chooser.destroy()
else:
REPO_PATH = str(SETTINGS.get("repo_path", ""))
if not REPO_PATH or not os.path.isdir(REPO_PATH):
return
if not self.props.active_window:
MainWindow(self)
win = self.props.active_window
if win:
try:
win.set_icon_name("illogical-updots")
except Exception:
pass
win.present()
def do_shutdown(self) -> None:
Gtk.Application.do_shutdown(self)
def main(argv: Optional[list[str]] = None) -> int:
import argparse
parser = argparse.ArgumentParser(description="Illogical Updots - Hyprland Dotfiles Manager")
parser.add_argument("--tui", action="store_true", help="Start in TUI mode")
parser.add_argument("--version", action="version", version="1.0.0")
args = parser.parse_args(argv[1:] if argv is not None else sys.argv[1:])
if args.tui:
try:
from tui import main_menu
main_menu()
return 0
except ImportError:
print("Rich library not found. TUI mode requires 'rich'.")
return 1
except Exception as e:
print(f"TUI Error: {e}")
return 1
app = App()
return app.run(argv if argv is not None else sys.argv)
if __name__ == "__main__":
raise SystemExit(main())