psiutils 0.2.6__tar.gz → 0.2.19__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {psiutils-0.2.6 → psiutils-0.2.19}/PKG-INFO +6 -2
- {psiutils-0.2.6 → psiutils-0.2.19}/pyproject.toml +6 -2
- psiutils-0.2.19/src/psiutils/__init__.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/_about_frame.py +3 -1
- psiutils-0.2.19/src/psiutils/_date_picker.py +210 -0
- psiutils-0.2.19/src/psiutils/_notify.py +17 -0
- psiutils-0.2.19/src/psiutils/_version.py +1 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/buttons.py +14 -7
- psiutils-0.2.19/src/psiutils/constants.py +92 -0
- psiutils-0.2.19/src/psiutils/icons/backup.png +0 -0
- psiutils-0.2.19/src/psiutils/icons/download.png +0 -0
- psiutils-0.2.19/src/psiutils/icons/restore.png +0 -0
- psiutils-0.2.19/src/psiutils/icons/restore_database.png +0 -0
- psiutils-0.2.19/src/psiutils/icons/restore_page.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/messagebox.py +12 -10
- psiutils-0.2.19/src/psiutils/text.py +121 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/utilities.py +15 -4
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/widgets.py +10 -5
- psiutils-0.2.6/src/psiutils/__init__.py +0 -15
- psiutils-0.2.6/src/psiutils/_notify.py +0 -11
- psiutils-0.2.6/src/psiutils/_version.py +0 -1
- psiutils-0.2.6/src/psiutils/constants.py +0 -65
- psiutils-0.2.6/src/psiutils/text.py +0 -46
- {psiutils-0.2.6 → psiutils-0.2.19}/README.md +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/_logger.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/drag_manager.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/errors.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icecream_init.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/build.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/cancel.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/check.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/clear.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/code.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/compare.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/copy_clipboard.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/copy_docs.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/delete.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/diff.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/done.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/edit.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/gear.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/new.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/next.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/open.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/pause.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/preferences.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/previous.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/process.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/redo.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/refresh.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/rename.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/report.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/reset.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/revert.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/save.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/script.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/search.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/send.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/start.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/update.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/upgrade.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/icons/windows.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/images/icon-error.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/images/icon-info.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/images/icon-query.png +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/known_paths.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/menus.py +0 -0
- {psiutils-0.2.6 → psiutils-0.2.19}/src/psiutils/treeview.py +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: psiutils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.19
|
|
4
4
|
Summary: Various TKinter utilities.
|
|
5
5
|
Author: Jeff
|
|
6
6
|
Author-email: Jeff <<jeffwatkins2000@gmail.com>>
|
|
7
|
+
Requires-Dist: appdirs>=1.4.4
|
|
7
8
|
Requires-Dist: iniconfig>=2.1.0
|
|
8
9
|
Requires-Dist: markdown>=3.8.2
|
|
9
10
|
Requires-Dist: packaging>=25.0
|
|
@@ -11,12 +12,15 @@ Requires-Dist: pillow>=11.3.0
|
|
|
11
12
|
Requires-Dist: pluggy>=1.6.0
|
|
12
13
|
Requires-Dist: psi-toml>=0.0.12
|
|
13
14
|
Requires-Dist: psiconfig>=0.0.14
|
|
15
|
+
Requires-Dist: pycairo>=1.28.0
|
|
14
16
|
Requires-Dist: pygments>=2.19.2
|
|
17
|
+
Requires-Dist: pygobject>=3.54.2
|
|
18
|
+
Requires-Dist: structlog>=25.4.0
|
|
15
19
|
Requires-Dist: tkinterweb>=4.4.4
|
|
16
20
|
Requires-Dist: tkinterweb-tkhtml>=1.1.1
|
|
17
21
|
Requires-Dist: tomli>=2.2.1
|
|
18
22
|
Requires-Dist: tomli-w>=1.2.0
|
|
19
|
-
Requires-Python:
|
|
23
|
+
Requires-Python: >=3.10, <3.13
|
|
20
24
|
Description-Content-Type: text/markdown
|
|
21
25
|
|
|
22
26
|
# psiutils
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "psiutils"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.19"
|
|
4
4
|
description = "Various TKinter utilities."
|
|
5
5
|
authors = [{name = "Jeff", "email" = "<jeffwatkins2000@gmail.com>"}]
|
|
6
|
-
requires-python = '
|
|
6
|
+
requires-python = '>= 3.10, < 3.13'
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
|
|
9
9
|
include = ["HISTORY.md", "src/psiutils/icons/*.png"]
|
|
10
10
|
|
|
11
11
|
dependencies = [
|
|
12
|
+
"appdirs>=1.4.4",
|
|
12
13
|
"iniconfig>=2.1.0",
|
|
13
14
|
"markdown>=3.8.2",
|
|
14
15
|
"packaging>=25.0",
|
|
@@ -16,7 +17,10 @@ dependencies = [
|
|
|
16
17
|
"pluggy>=1.6.0",
|
|
17
18
|
"psi-toml>=0.0.12",
|
|
18
19
|
"psiconfig>=0.0.14",
|
|
20
|
+
"pycairo>=1.28.0",
|
|
19
21
|
"pygments>=2.19.2",
|
|
22
|
+
"pygobject>=3.54.2",
|
|
23
|
+
"structlog>=25.4.0",
|
|
20
24
|
"tkinterweb>=4.4.4",
|
|
21
25
|
"tkinterweb-tkhtml>=1.1.1",
|
|
22
26
|
"tomli>=2.2.1",
|
|
File without changes
|
|
@@ -8,7 +8,9 @@ import markdown
|
|
|
8
8
|
from psiutils.constants import PAD, Pad
|
|
9
9
|
from psiutils.utilities import window_resize
|
|
10
10
|
|
|
11
|
-
from psiutils import
|
|
11
|
+
from psiutils.text import Text
|
|
12
|
+
|
|
13
|
+
txt = Text()
|
|
12
14
|
|
|
13
15
|
DEFAULT_GEOMETRY = '400x200'
|
|
14
16
|
HISTORY_GEOMETRY = '800x750'
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import tkinter as tk
|
|
2
|
+
from tkinter import ttk
|
|
3
|
+
import tkinter.font as tkFont
|
|
4
|
+
from tkcalendar import DateEntry
|
|
5
|
+
from functools import partial
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from dateutil.parser import parse
|
|
8
|
+
|
|
9
|
+
from text import Text
|
|
10
|
+
|
|
11
|
+
txt = Text()
|
|
12
|
+
|
|
13
|
+
PAD = 2
|
|
14
|
+
TIME_WIDTH = 3
|
|
15
|
+
INCREMENT_BUTTON_SIZE = 2
|
|
16
|
+
INCREMENT_BUTTON_FONT_SIZE = 8
|
|
17
|
+
DATE_FORMAT = '%d/%m/%Y'
|
|
18
|
+
PICKER_DATE_PATTERN = 'dd/mm/yyyy',
|
|
19
|
+
MAX_HOURS = 23
|
|
20
|
+
MAX_MINS = 59
|
|
21
|
+
TALL_COMBO_PADDING = 6
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DatePicker(tk.Frame):
|
|
25
|
+
def __init__(
|
|
26
|
+
self, master: tk.Frame,
|
|
27
|
+
initial_date: datetime = None,
|
|
28
|
+
date_format: str = ''):
|
|
29
|
+
super().__init__(master)
|
|
30
|
+
if not initial_date:
|
|
31
|
+
initial_date = datetime.now()
|
|
32
|
+
if not date_format:
|
|
33
|
+
date_format = DATE_FORMAT
|
|
34
|
+
|
|
35
|
+
self._date_input = tk.StringVar(
|
|
36
|
+
value=initial_date.strftime(DATE_FORMAT))
|
|
37
|
+
|
|
38
|
+
style = ttk.Style()
|
|
39
|
+
style.configure(
|
|
40
|
+
'Increment.TButton',
|
|
41
|
+
font=('Helvetica', INCREMENT_BUTTON_FONT_SIZE),
|
|
42
|
+
padding=0,)
|
|
43
|
+
style.configure('Tall.TCombobox', padding=TALL_COMBO_PADDING)
|
|
44
|
+
|
|
45
|
+
main_frame = self._picker()
|
|
46
|
+
main_frame.pack()
|
|
47
|
+
|
|
48
|
+
def _picker(self) -> tk.Frame:
|
|
49
|
+
frame = ttk.Frame(self)
|
|
50
|
+
|
|
51
|
+
column = 0
|
|
52
|
+
date_picker = self._date_picker(frame, self._date_input)
|
|
53
|
+
date_picker.grid(row=0, column=column, rowspan=2, sticky=tk.NS)
|
|
54
|
+
|
|
55
|
+
column += 1
|
|
56
|
+
button = ttk.Button(
|
|
57
|
+
frame,
|
|
58
|
+
text=txt.INCREMENT_ARROW,
|
|
59
|
+
command=partial(self._date_increment, self._date_input),
|
|
60
|
+
width=INCREMENT_BUTTON_SIZE,
|
|
61
|
+
style='Increment.TButton',
|
|
62
|
+
)
|
|
63
|
+
button.grid(row=0, column=column, padx=PAD)
|
|
64
|
+
|
|
65
|
+
button = ttk.Button(
|
|
66
|
+
frame,
|
|
67
|
+
text=txt.DECREMENT_ARROW,
|
|
68
|
+
command=partial(self._date_increment, self._date_input, -1),
|
|
69
|
+
width=INCREMENT_BUTTON_SIZE,
|
|
70
|
+
style='Increment.TButton',
|
|
71
|
+
)
|
|
72
|
+
button.grid(row=1, column=column, padx=PAD)
|
|
73
|
+
|
|
74
|
+
column += 1
|
|
75
|
+
|
|
76
|
+
return frame
|
|
77
|
+
|
|
78
|
+
def _date_picker(
|
|
79
|
+
self, master: tk.Frame, textvariable: tk.StringVar) -> DateEntry:
|
|
80
|
+
event_date = datetime.now()
|
|
81
|
+
return DateEntry(
|
|
82
|
+
master,
|
|
83
|
+
date_pattern=PICKER_DATE_PATTERN,
|
|
84
|
+
year=event_date.year,
|
|
85
|
+
month=event_date.month,
|
|
86
|
+
day=event_date.day,
|
|
87
|
+
textvariable=textvariable,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def date(self) -> datetime:
|
|
92
|
+
return parse(self._date_input.get())
|
|
93
|
+
|
|
94
|
+
def _date_increment(
|
|
95
|
+
self,
|
|
96
|
+
textvariable: tk.StringVar,
|
|
97
|
+
increment: int = 1, *args) -> None:
|
|
98
|
+
date = parse(textvariable.get(), dayfirst=True).date()
|
|
99
|
+
new_date = date + timedelta(days=increment)
|
|
100
|
+
textvariable.set(new_date.strftime(DATE_FORMAT))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TimePicker(tk.Frame):
|
|
104
|
+
def __init__(
|
|
105
|
+
self, master: tk.Frame,
|
|
106
|
+
use_seconds: bool = False,
|
|
107
|
+
use_labels: bool = False):
|
|
108
|
+
super().__init__(master)
|
|
109
|
+
self.use_seconds = use_seconds
|
|
110
|
+
self.use_labels = use_labels
|
|
111
|
+
|
|
112
|
+
self._hour_input = tk.StringVar(value='00')
|
|
113
|
+
self._minute_input = tk.StringVar(value='00')
|
|
114
|
+
self._second_input = tk.StringVar(value='00')
|
|
115
|
+
|
|
116
|
+
style = ttk.Style()
|
|
117
|
+
style.configure('Increment.TButton', font=('Helvetica', 8))
|
|
118
|
+
|
|
119
|
+
main_frame = self._picker()
|
|
120
|
+
main_frame.grid(row=0, column=0)
|
|
121
|
+
|
|
122
|
+
def _picker(self) -> tk.Frame:
|
|
123
|
+
frame = ttk.Frame(self)
|
|
124
|
+
|
|
125
|
+
column = 0
|
|
126
|
+
row = 0
|
|
127
|
+
if self.use_labels:
|
|
128
|
+
label = ttk.Label(frame, text='Hour')
|
|
129
|
+
label.grid(row=row, column=column, sticky=tk.W)
|
|
130
|
+
|
|
131
|
+
label = ttk.Label(frame, text='Mins')
|
|
132
|
+
label.grid(row=row, column=column+1, sticky=tk.W)
|
|
133
|
+
|
|
134
|
+
if self.use_seconds:
|
|
135
|
+
label = ttk.Label(frame, text='Secs')
|
|
136
|
+
label.grid(row=row, column=column+5, sticky=tk.E)
|
|
137
|
+
|
|
138
|
+
row += 1
|
|
139
|
+
hour_timer = self._timer_element(frame, self._hour_input, MAX_HOURS)
|
|
140
|
+
hour_timer.grid(row=row, column=column)
|
|
141
|
+
|
|
142
|
+
column += 1
|
|
143
|
+
minute_timer = self._timer_element(frame, self._minute_input)
|
|
144
|
+
minute_timer.grid(row=row, column=column)
|
|
145
|
+
|
|
146
|
+
if self.use_seconds:
|
|
147
|
+
column += 1
|
|
148
|
+
second_timer = self._timer_element(frame, self._second_input)
|
|
149
|
+
second_timer.grid(row=row, column=column)
|
|
150
|
+
|
|
151
|
+
return frame
|
|
152
|
+
|
|
153
|
+
def _timer_element(
|
|
154
|
+
self,
|
|
155
|
+
master: tk.Frame,
|
|
156
|
+
textvariable: tk.StringVar,
|
|
157
|
+
max_value: int = MAX_MINS,
|
|
158
|
+
) -> tk.Frame:
|
|
159
|
+
frame = ttk.Frame(master)
|
|
160
|
+
column = 0
|
|
161
|
+
|
|
162
|
+
combobox = ttk.Combobox(
|
|
163
|
+
frame,
|
|
164
|
+
textvariable=textvariable,
|
|
165
|
+
values=[f'{x:02d}' for x in range(max_value+1)],
|
|
166
|
+
width=TIME_WIDTH,
|
|
167
|
+
style='Tall.TCombobox',
|
|
168
|
+
)
|
|
169
|
+
combobox.grid(row=0, column=column, rowspan=2, sticky=tk.W)
|
|
170
|
+
|
|
171
|
+
column += 1
|
|
172
|
+
|
|
173
|
+
button = ttk.Button(
|
|
174
|
+
frame,
|
|
175
|
+
text=txt.INCREMENT_ARROW,
|
|
176
|
+
command=partial(self._time_increment, textvariable, 1, max_value),
|
|
177
|
+
width=INCREMENT_BUTTON_SIZE,
|
|
178
|
+
style='Increment.TButton',
|
|
179
|
+
)
|
|
180
|
+
button.grid(row=0, column=column, padx=PAD)
|
|
181
|
+
|
|
182
|
+
button = ttk.Button(
|
|
183
|
+
frame,
|
|
184
|
+
text=txt.DECREMENT_ARROW,
|
|
185
|
+
command=partial(self._time_increment, textvariable, -1, max_value),
|
|
186
|
+
width=INCREMENT_BUTTON_SIZE,
|
|
187
|
+
style='Increment.TButton',
|
|
188
|
+
)
|
|
189
|
+
button.grid(row=1, column=column, padx=PAD)
|
|
190
|
+
return frame
|
|
191
|
+
|
|
192
|
+
def _time_increment(
|
|
193
|
+
self,
|
|
194
|
+
textvariable: tk.StringVar,
|
|
195
|
+
increment,
|
|
196
|
+
max_value) -> None:
|
|
197
|
+
value = int(textvariable.get()) + increment
|
|
198
|
+
if value < 0:
|
|
199
|
+
value = max_value
|
|
200
|
+
if value > max_value:
|
|
201
|
+
value = 0
|
|
202
|
+
textvariable.set(f'{value:02d}')
|
|
203
|
+
|
|
204
|
+
@property
|
|
205
|
+
def time(self) -> datetime:
|
|
206
|
+
return datetime(
|
|
207
|
+
hours=int(self._hour_input.get()),
|
|
208
|
+
minutes=int(self._minute_input.get()),
|
|
209
|
+
seconds=int(self._second_input.get()),
|
|
210
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Provide notifications on Linux platforms."""
|
|
2
|
+
|
|
3
|
+
import platform
|
|
4
|
+
|
|
5
|
+
if platform.system() == 'Linux':
|
|
6
|
+
import gi
|
|
7
|
+
gi.require_version('Gio', '2.0')
|
|
8
|
+
gi.require_version('GioUnix', '2.0')
|
|
9
|
+
gi.require_version('Notify', '0.7')
|
|
10
|
+
from gi.repository import Notify
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _notify(title: str, message: str) -> None:
|
|
14
|
+
if platform.system() != 'Linux':
|
|
15
|
+
return
|
|
16
|
+
Notify.init(title)
|
|
17
|
+
Notify.Notification.new(message).show()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.2.19'
|
|
@@ -4,10 +4,12 @@ from tkinter import ttk
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from PIL import Image, ImageTk
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from psiutils.text import Text
|
|
8
8
|
|
|
9
|
-
from .constants import PAD, Pad
|
|
10
|
-
from .widgets import enter_widget, clickable_widget, HAND
|
|
9
|
+
from psiutils.constants import PAD, Pad
|
|
10
|
+
from psiutils.widgets import enter_widget, clickable_widget, HAND
|
|
11
|
+
|
|
12
|
+
txt = Text()
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class IconButton(ttk.Frame):
|
|
@@ -16,8 +18,8 @@ class IconButton(ttk.Frame):
|
|
|
16
18
|
master,
|
|
17
19
|
button_text,
|
|
18
20
|
icon,
|
|
19
|
-
dimmable: bool = False,
|
|
20
21
|
command=None,
|
|
22
|
+
dimmable: bool = False,
|
|
21
23
|
sticky: str = '',
|
|
22
24
|
icon_path: str = '',
|
|
23
25
|
**kwargs):
|
|
@@ -48,7 +50,7 @@ class IconButton(ttk.Frame):
|
|
|
48
50
|
def __repr__(self) -> str:
|
|
49
51
|
return f'IconButton: {self.text} {self.icon}'
|
|
50
52
|
|
|
51
|
-
def state(self) -> dict:
|
|
53
|
+
def state(self, *args, **kwargs) -> dict:
|
|
52
54
|
return self._state
|
|
53
55
|
|
|
54
56
|
def enable(self, enable: bool = True) -> None:
|
|
@@ -124,8 +126,8 @@ class ButtonFrame(ttk.Frame):
|
|
|
124
126
|
def icon_button(
|
|
125
127
|
self,
|
|
126
128
|
id_: str,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
command: object = None,
|
|
130
|
+
dimmable: bool = False,) -> IconButton:
|
|
129
131
|
button = self.icon_buttons[id_]
|
|
130
132
|
button.dimmable = dimmable
|
|
131
133
|
button.command = command
|
|
@@ -215,6 +217,7 @@ def enable_buttons(buttons: list[Button], enable: bool = True):
|
|
|
215
217
|
|
|
216
218
|
|
|
217
219
|
icon_buttons = {
|
|
220
|
+
'backup': (txt.BACKUP, 'backup'),
|
|
218
221
|
'build': (txt.BUILD, 'build'),
|
|
219
222
|
'check': (txt.CHECK, 'check'),
|
|
220
223
|
'clear': (txt.CLEAR, 'clear'),
|
|
@@ -225,6 +228,7 @@ icon_buttons = {
|
|
|
225
228
|
'copy_docs': (txt.COPY, 'copy_docs'),
|
|
226
229
|
'copy_clipboard': (txt.COPY, 'copy_clipboard'),
|
|
227
230
|
'delete': (txt.DELETE, 'delete'),
|
|
231
|
+
'download': (txt.DOWNLOAD, 'download'),
|
|
228
232
|
'diff': (txt.DIFF, 'diff'),
|
|
229
233
|
'done': (txt.DONE, 'done'),
|
|
230
234
|
'edit': (txt.EDIT, 'edit'),
|
|
@@ -241,6 +245,9 @@ icon_buttons = {
|
|
|
241
245
|
'rename': (txt.RENAME, 'rename'),
|
|
242
246
|
'report': (txt.REPORT, 'report'),
|
|
243
247
|
'reset': (txt.RESET, 'reset'),
|
|
248
|
+
'restore': (txt.RESTORE, 'restore'),
|
|
249
|
+
'restore_database': (txt.RESTORE, 'restore_database'),
|
|
250
|
+
'restore_page': (txt.RESTORE, 'restore_page'),
|
|
244
251
|
'revert': (txt.REVERT, 'revert'),
|
|
245
252
|
'run': (txt.RUN, 'start'),
|
|
246
253
|
'save': (txt.SAVE, 'save'),
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Constants for the tkinter psiutils."""
|
|
2
|
+
from enum import Enum, auto
|
|
3
|
+
|
|
4
|
+
# from .utilities import invert
|
|
5
|
+
from .known_paths import get_documents_dir, get_downloads_dir
|
|
6
|
+
|
|
7
|
+
DEFAULT_GEOMETRY = '500x400'
|
|
8
|
+
|
|
9
|
+
# # TODO is this needed with Status?
|
|
10
|
+
# DIALOG_STATUS: dict = {
|
|
11
|
+
# 'yes': True,
|
|
12
|
+
# 'no': False,
|
|
13
|
+
# 'cancel': None,
|
|
14
|
+
# 'null': 0,
|
|
15
|
+
# 'undefined': 0,
|
|
16
|
+
# 'exit': 1,
|
|
17
|
+
# 'ok': 2,
|
|
18
|
+
# 'updated': 3,
|
|
19
|
+
# 'error': 4,
|
|
20
|
+
# }
|
|
21
|
+
# DIALOG_STATUS = invert(DIALOG_STATUS)
|
|
22
|
+
|
|
23
|
+
# # TODO is this needed with Mode?
|
|
24
|
+
# MODES: dict[int, str] | dict[str, int] = {
|
|
25
|
+
# 0: 'view',
|
|
26
|
+
# 1: 'new',
|
|
27
|
+
# 2: 'edit',
|
|
28
|
+
# 3: 'delete'
|
|
29
|
+
# }
|
|
30
|
+
# MODES = invert(MODES)
|
|
31
|
+
|
|
32
|
+
# GUI
|
|
33
|
+
PAD = 5
|
|
34
|
+
PADR = (0, PAD)
|
|
35
|
+
PADL = (PAD, 0)
|
|
36
|
+
PADT = (PAD, 0)
|
|
37
|
+
PADB = (0, PAD)
|
|
38
|
+
LARGE_FONT = ('Arial', 16)
|
|
39
|
+
BOLD_FONT = ('Arial', 12, 'bold')
|
|
40
|
+
|
|
41
|
+
# Colours
|
|
42
|
+
COLOURS = {
|
|
43
|
+
'pale-umber': '#ffcfa0',
|
|
44
|
+
'pale-red': '#ff9999',
|
|
45
|
+
'pale-grey': '#e8e8e8'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
CSV_FILE_TYPES = (
|
|
49
|
+
('csv files', '*.csv'),
|
|
50
|
+
('All files', '*.*')
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
TXT_FILE_TYPES = (
|
|
54
|
+
('csv files', '*.txt'),
|
|
55
|
+
('All files', '*.*')
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
XML_FILE_TYPES = (
|
|
59
|
+
('xml files', '*.xml'),
|
|
60
|
+
('All files', '*.*')
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Pad():
|
|
65
|
+
W = (0, PAD)
|
|
66
|
+
E = (PAD, 0)
|
|
67
|
+
N = (PAD, 0)
|
|
68
|
+
S = (0, PAD)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
DOCUMENTS_DIR = get_documents_dir()
|
|
72
|
+
DOWNLOADS_DIR = get_downloads_dir()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Mode(Enum):
|
|
76
|
+
VIEW = auto()
|
|
77
|
+
NEW = auto()
|
|
78
|
+
EDIT = auto()
|
|
79
|
+
DELETE = auto()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Status(Enum):
|
|
83
|
+
YES = True
|
|
84
|
+
NO = False
|
|
85
|
+
CANCEL = None
|
|
86
|
+
NULL = 0
|
|
87
|
+
EXIT = 1
|
|
88
|
+
OK = 2
|
|
89
|
+
SUCCESS = 3
|
|
90
|
+
UPDATED = 4
|
|
91
|
+
ERROR = 5
|
|
92
|
+
WARNING = 6
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -5,9 +5,11 @@ from tkinter import font
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from PIL import ImageTk, Image
|
|
7
7
|
|
|
8
|
-
from psiutils.constants import PAD
|
|
8
|
+
from psiutils.constants import PAD, Status
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
from psiutils.text import Text
|
|
11
|
+
|
|
12
|
+
txt = Text()
|
|
11
13
|
|
|
12
14
|
icons = {
|
|
13
15
|
'info': 'icon-info.png',
|
|
@@ -113,29 +115,29 @@ class MessageBox():
|
|
|
113
115
|
def _get_buttons(self, frame: ttk.Frame) -> dict[str, ttk.Button]:
|
|
114
116
|
return {
|
|
115
117
|
'ok': ttk.Button(
|
|
116
|
-
frame, text=
|
|
118
|
+
frame, text=txt.OK, command=self._ok, underline=0),
|
|
117
119
|
'yes': ttk.Button(
|
|
118
|
-
frame, text=
|
|
120
|
+
frame, text=txt.YES, command=self._yes, underline=0),
|
|
119
121
|
'no': ttk.Button(
|
|
120
|
-
frame, text=
|
|
122
|
+
frame, text=txt.NO, command=self._no, underline=0),
|
|
121
123
|
'cancel': ttk.Button(
|
|
122
|
-
frame, text=
|
|
124
|
+
frame, text=txt.CANCEL, command=self._cancel, underline=0),
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
def _ok(self, *args) -> None:
|
|
126
|
-
self.status =
|
|
128
|
+
self.status = Status.OK
|
|
127
129
|
self._dismiss()
|
|
128
130
|
|
|
129
131
|
def _yes(self, *args) -> None:
|
|
130
|
-
self.status =
|
|
132
|
+
self.status = Status.YES
|
|
131
133
|
self._dismiss()
|
|
132
134
|
|
|
133
135
|
def _no(self, *args) -> None:
|
|
134
|
-
self.status =
|
|
136
|
+
self.status = Status.NO
|
|
135
137
|
self._dismiss()
|
|
136
138
|
|
|
137
139
|
def _cancel(self, *args) -> None:
|
|
138
|
-
self.status =
|
|
140
|
+
self.status = Status.CANCEL
|
|
139
141
|
self._dismiss()
|
|
140
142
|
|
|
141
143
|
def _dismiss(self, *args) -> None:
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
""" Handle standard text for psiutils."""
|
|
2
|
+
|
|
3
|
+
from copy import copy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
psi_strings = {
|
|
7
|
+
'BACKUP': 'Backup',
|
|
8
|
+
'BUILD': 'Build',
|
|
9
|
+
'CANCEL': 'Cancel',
|
|
10
|
+
'CHECK': 'Check',
|
|
11
|
+
'CLEAR': 'Clear',
|
|
12
|
+
'CLOSE': 'Close',
|
|
13
|
+
'CODE': 'Code',
|
|
14
|
+
'COMPARE': 'Compare',
|
|
15
|
+
'CONFIG': 'Config',
|
|
16
|
+
'COPY': 'Copy',
|
|
17
|
+
'DECREMENT_ARROW': '▼',
|
|
18
|
+
'DELETE': 'Delete',
|
|
19
|
+
'DELETE_THESE_ITEMS': 'Are you sure you want to delete these item(s)?',
|
|
20
|
+
'DIFF': 'Diff',
|
|
21
|
+
'DONE': 'Done',
|
|
22
|
+
'DOWNLOAD': 'Download',
|
|
23
|
+
'EDIT': 'Edit',
|
|
24
|
+
'ELLIPSIS': ' ...',
|
|
25
|
+
'EVENT': 'Event',
|
|
26
|
+
'EXIT': 'Exit',
|
|
27
|
+
'HELP': 'Help',
|
|
28
|
+
'INCREMENT_ARROW': '▲',
|
|
29
|
+
'LOGS': 'Logs',
|
|
30
|
+
'NEW': 'New',
|
|
31
|
+
'NEXT': 'Next',
|
|
32
|
+
'NO': 'No',
|
|
33
|
+
'NO_SUCH_FILE': 'no such file or directory',
|
|
34
|
+
'OK': 'OK',
|
|
35
|
+
'OPEN': 'Open',
|
|
36
|
+
'PAUSE': 'Pause',
|
|
37
|
+
'PREFERENCES': 'Preferences',
|
|
38
|
+
'PREVIOUS': 'Prev',
|
|
39
|
+
'PROCESS': 'Process',
|
|
40
|
+
'QUIT': 'Quit',
|
|
41
|
+
'REDO': 'Redo',
|
|
42
|
+
'REFRESH': 'Refresh',
|
|
43
|
+
'REPORT': 'Report',
|
|
44
|
+
'RENAME': 'Rename',
|
|
45
|
+
'RESET': 'Reset',
|
|
46
|
+
'RESTORE': 'Restore',
|
|
47
|
+
'REVERT': 'Revert',
|
|
48
|
+
'RUN': 'Run',
|
|
49
|
+
'SAVE': 'Save',
|
|
50
|
+
'SCRIPT': 'Script',
|
|
51
|
+
'SAVE_PDF': 'Save as PDF',
|
|
52
|
+
'SEARCH': 'Search',
|
|
53
|
+
'SEND': 'Send',
|
|
54
|
+
'START': 'Start',
|
|
55
|
+
'UPDATE': 'Update',
|
|
56
|
+
'UPGRADE': 'Upgrade',
|
|
57
|
+
'USE': 'Use',
|
|
58
|
+
'WINDOWS': 'Windows',
|
|
59
|
+
'YES': 'Yes',
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
strings = copy(psi_strings)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Text():
|
|
66
|
+
"""Combines package level and psiutils strings."""
|
|
67
|
+
def __init__(self) -> None:
|
|
68
|
+
"""
|
|
69
|
+
Initialise the object with attributes based on the key-value pairs
|
|
70
|
+
in the `strings` dictionary.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
self: The instance of the class.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
None
|
|
77
|
+
"""
|
|
78
|
+
self.strings = strings
|
|
79
|
+
for key, string in strings.items():
|
|
80
|
+
setattr(self, key, string)
|
|
81
|
+
|
|
82
|
+
# Optionally display contents of `strings`
|
|
83
|
+
def display(self, compare: dict = None) -> None:
|
|
84
|
+
"""Print out contents of `strings` and compare if
|
|
85
|
+
a dict of strings is provided."""
|
|
86
|
+
duplicates = 0
|
|
87
|
+
overrides = 0
|
|
88
|
+
app_strings = 0
|
|
89
|
+
if not compare:
|
|
90
|
+
compare = {}
|
|
91
|
+
|
|
92
|
+
for key, item in compare.items():
|
|
93
|
+
if key not in strings:
|
|
94
|
+
strings[key] = item
|
|
95
|
+
|
|
96
|
+
for item in sorted(list(strings)):
|
|
97
|
+
output = f'{item:.<20} {strings[item]}'
|
|
98
|
+
if item in compare:
|
|
99
|
+
if strings[item] != compare[item]:
|
|
100
|
+
output = (f'{output}, {compare[item]} '
|
|
101
|
+
f'<{"-"*10} //override//')
|
|
102
|
+
overrides += 1
|
|
103
|
+
elif item not in psi_strings:
|
|
104
|
+
output = f'{output} <{"="*10} //app string//'
|
|
105
|
+
app_strings += 1
|
|
106
|
+
else:
|
|
107
|
+
output = f'{output} <{"="*10} //duplicate//'
|
|
108
|
+
duplicates += 1
|
|
109
|
+
print(output)
|
|
110
|
+
|
|
111
|
+
if duplicates:
|
|
112
|
+
print()
|
|
113
|
+
print(f'{duplicates} duplicates found')
|
|
114
|
+
|
|
115
|
+
if overrides:
|
|
116
|
+
print()
|
|
117
|
+
print(f'{overrides} overrides found')
|
|
118
|
+
|
|
119
|
+
if app_strings:
|
|
120
|
+
print()
|
|
121
|
+
print(f'{app_strings} application strings found')
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Common methods for psiutils."""
|
|
2
|
+
import sys
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
import tkinter as tk
|
|
4
5
|
import ctypes
|
|
@@ -6,13 +7,12 @@ from typing import Any
|
|
|
6
7
|
import platform
|
|
7
8
|
|
|
8
9
|
from psiconfig import TomlConfig
|
|
9
|
-
import psiutils.text as txt
|
|
10
|
-
|
|
11
|
-
# Exposes psi_logger to other applications
|
|
12
10
|
from psiutils._logger import psi_logger
|
|
13
11
|
from psiutils._notify import _notify as notify
|
|
12
|
+
from psiutils.constants import DEFAULT_GEOMETRY
|
|
13
|
+
from psiutils.text import Text
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
txt = Text()
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def display_icon(root: tk.Tk, icon_file_path: str,
|
|
@@ -28,6 +28,16 @@ def display_icon(root: tk.Tk, icon_file_path: str,
|
|
|
28
28
|
print(f'Cannot find icon file: {icon_file_path}')
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def resource_path(base: Path, relative_path: Path):
|
|
32
|
+
""" Get absolute path to resource, works for dev and for PyInstaller."""
|
|
33
|
+
try:
|
|
34
|
+
# PyInstaller creates a temp folder and stores path in _MEIPASS
|
|
35
|
+
base_path = sys._MEIPASS
|
|
36
|
+
except Exception:
|
|
37
|
+
base_path = Path(base).parent
|
|
38
|
+
return Path(base_path, relative_path)
|
|
39
|
+
|
|
40
|
+
|
|
31
41
|
class Enum():
|
|
32
42
|
def __init__(self, values: dict) -> None:
|
|
33
43
|
self.values = invert(values)
|
|
@@ -75,6 +85,7 @@ def enable_frame(parent: tk.Frame, enable: bool = True) -> None:
|
|
|
75
85
|
else:
|
|
76
86
|
child.configure(state=state)
|
|
77
87
|
|
|
88
|
+
|
|
78
89
|
def geometry(config: TomlConfig, file: Path, default: str = '') -> str:
|
|
79
90
|
if not default:
|
|
80
91
|
default = DEFAULT_GEOMETRY
|
|
@@ -6,6 +6,7 @@ import contextlib
|
|
|
6
6
|
|
|
7
7
|
from .constants import PAD, COLOURS
|
|
8
8
|
from ._about_frame import AboutFrame
|
|
9
|
+
from psiutils._date_picker import DatePicker, TimePicker
|
|
9
10
|
|
|
10
11
|
HAND = 'hand2'
|
|
11
12
|
DIM_TEXT = '#555'
|
|
@@ -23,16 +24,16 @@ class PsiText(tk.Text):
|
|
|
23
24
|
tk.Text.__init__(self, *args, **kwargs)
|
|
24
25
|
|
|
25
26
|
# create a proxy for the underlying widget
|
|
26
|
-
self._orig = f
|
|
27
|
-
self.tk.call(
|
|
27
|
+
self._orig = f'{self._w}_orig'
|
|
28
|
+
self.tk.call('rename', self._w, self._orig)
|
|
28
29
|
self.tk.createcommand(self._w, self._proxy)
|
|
29
30
|
|
|
30
31
|
def _proxy(self, command, *args):
|
|
31
32
|
cmd = (self._orig, command) + args
|
|
32
33
|
result = self.tk.call(cmd)
|
|
33
34
|
|
|
34
|
-
if command in (
|
|
35
|
-
self.event_generate(
|
|
35
|
+
if command in ('insert', 'delete', 'replace'):
|
|
36
|
+
self.event_generate('<<TextModified>>')
|
|
36
37
|
|
|
37
38
|
return result
|
|
38
39
|
|
|
@@ -62,6 +63,7 @@ def get_styles() -> ttk.Style:
|
|
|
62
63
|
|
|
63
64
|
style.configure('red-bg.TEntry', fieldbackground='red')
|
|
64
65
|
style.configure('green-bg.TEntry', fieldbackground='green')
|
|
66
|
+
style.configure('blue-bg.TEntry', fieldbackground='blue')
|
|
65
67
|
style.configure('orange-bg.TEntry', fieldbackground='orange')
|
|
66
68
|
style.configure(
|
|
67
69
|
'pale-umber-bg.TEntry', fieldbackground=COLOURS['pale-umber'])
|
|
@@ -71,6 +73,7 @@ def get_styles() -> ttk.Style:
|
|
|
71
73
|
# Entries - foreground
|
|
72
74
|
style.configure('red-fg.TEntry', foreground='red')
|
|
73
75
|
style.configure('green-fg.TEntry', foreground='green')
|
|
76
|
+
style.configure('blue-fg.TEntry', foreground='blue')
|
|
74
77
|
style.configure('orange-fg.TEntry', foreground='orange')
|
|
75
78
|
|
|
76
79
|
# Frames
|
|
@@ -83,6 +86,8 @@ def get_styles() -> ttk.Style:
|
|
|
83
86
|
# radiobuttons
|
|
84
87
|
style.configure('red-fg.TRadiobutton', foreground='red')
|
|
85
88
|
style.configure('green-fg.TRadiobutton', foreground='green')
|
|
89
|
+
style.configure('blue-fg.TRadiobutton', foreground='blue')
|
|
90
|
+
style.configure('orange-fg.TRadiobutton', foreground='orange')
|
|
86
91
|
|
|
87
92
|
# Tree view
|
|
88
93
|
style.map('Treeview',
|
|
@@ -345,7 +350,7 @@ class Tooltip:
|
|
|
345
350
|
|
|
346
351
|
x, y = tip_pos_calculator(widget, label)
|
|
347
352
|
|
|
348
|
-
self.tw.wm_geometry(
|
|
353
|
+
self.tw.wm_geometry('+%d+%d' % (x, y+self.vertical_offset))
|
|
349
354
|
# self.tw.wm_geometry(f'{x}x{y}')
|
|
350
355
|
|
|
351
356
|
def hide(self):
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import gi
|
|
3
|
-
gi.require_version('Gio', '2.0')
|
|
4
|
-
gi.require_version('GioUnix', '2.0')
|
|
5
|
-
gi.require_version('Notify', '0.7')
|
|
6
|
-
from gi.repository import Notify
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def _notify(title: str, message: str) -> None:
|
|
10
|
-
Notify.init(title)
|
|
11
|
-
Notify.Notification.new(message).show()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.2.6'
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"""Constants for the tkinter psiutils."""
|
|
2
|
-
from .utilities import invert
|
|
3
|
-
from .known_paths import get_documents_dir, get_downloads_dir
|
|
4
|
-
|
|
5
|
-
DIALOG_STATUS: dict = {
|
|
6
|
-
'yes': True,
|
|
7
|
-
'no': False,
|
|
8
|
-
'cancel': None,
|
|
9
|
-
'null': 0,
|
|
10
|
-
'undefined': 0,
|
|
11
|
-
'exit': 1,
|
|
12
|
-
'ok': 2,
|
|
13
|
-
'updated': 3,
|
|
14
|
-
'error': 4,
|
|
15
|
-
}
|
|
16
|
-
DIALOG_STATUS = invert(DIALOG_STATUS)
|
|
17
|
-
|
|
18
|
-
MODES: dict[int, str] | dict[str, int] = {
|
|
19
|
-
0: 'view',
|
|
20
|
-
1: 'new',
|
|
21
|
-
2: 'edit',
|
|
22
|
-
3: 'delete'
|
|
23
|
-
}
|
|
24
|
-
MODES = invert(MODES)
|
|
25
|
-
|
|
26
|
-
# GUI
|
|
27
|
-
PAD = 5
|
|
28
|
-
PADR = (0, PAD)
|
|
29
|
-
PADL = (PAD, 0)
|
|
30
|
-
PADT = (PAD, 0)
|
|
31
|
-
PADB = (0, PAD)
|
|
32
|
-
LARGE_FONT = ('Arial', 16)
|
|
33
|
-
BOLD_FONT = ('Arial', 12, 'bold')
|
|
34
|
-
|
|
35
|
-
# Colours
|
|
36
|
-
COLOURS = {
|
|
37
|
-
'pale-umber': '#ffcfa0',
|
|
38
|
-
'pale-red': '#ff9999',
|
|
39
|
-
'pale-grey': '#e8e8e8'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
CSV_FILE_TYPES = (
|
|
43
|
-
('csv files', '*.csv'),
|
|
44
|
-
('All files', '*.*')
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
TXT_FILE_TYPES = (
|
|
48
|
-
('csv files', '*.txt'),
|
|
49
|
-
('All files', '*.*')
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
XML_FILE_TYPES = (
|
|
53
|
-
('xml files', '*.xml'),
|
|
54
|
-
('All files', '*.*')
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class Pad():
|
|
59
|
-
W = (0, PAD)
|
|
60
|
-
E = (PAD, 0)
|
|
61
|
-
N = (PAD, 0)
|
|
62
|
-
S = (0, PAD)
|
|
63
|
-
|
|
64
|
-
DOCUMENTS_DIR = get_documents_dir()
|
|
65
|
-
DOWNLOADS_DIR = get_downloads_dir()
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
BUILD = 'Build'
|
|
2
|
-
CANCEL = 'Cancel'
|
|
3
|
-
CHECK = 'Check'
|
|
4
|
-
CLEAR = 'Clear'
|
|
5
|
-
CLOSE = 'Close'
|
|
6
|
-
CODE = 'Code'
|
|
7
|
-
COMPARE = 'Compare'
|
|
8
|
-
CONFIG = 'Config'
|
|
9
|
-
COPY = 'Copy'
|
|
10
|
-
DELETE = 'Delete'
|
|
11
|
-
DELETE_THESE_ITEMS = 'Are you sure you want to delete these item(s)?'
|
|
12
|
-
DIFF = 'Diff'
|
|
13
|
-
DONE = 'Done'
|
|
14
|
-
EDIT = 'Edit'
|
|
15
|
-
EVENT = 'Event'
|
|
16
|
-
EXIT = 'Exit'
|
|
17
|
-
HELP = 'Help'
|
|
18
|
-
NEW = 'New'
|
|
19
|
-
NEXT = 'Next'
|
|
20
|
-
NO = 'No'
|
|
21
|
-
NO_SUCH_FILE = 'no such file or directory'
|
|
22
|
-
OK = 'OK'
|
|
23
|
-
OPEN = 'Open'
|
|
24
|
-
PAUSE = 'Pause'
|
|
25
|
-
PREFERENCES = 'Preferences'
|
|
26
|
-
PREVIOUS = 'Prev'
|
|
27
|
-
PROCESS = 'Process'
|
|
28
|
-
QUIT = 'Quit'
|
|
29
|
-
REDO = 'Redo'
|
|
30
|
-
REFRESH = 'Refresh'
|
|
31
|
-
REPORT = 'Report'
|
|
32
|
-
RENAME = 'Rename'
|
|
33
|
-
RESET = 'Reset'
|
|
34
|
-
REVERT = 'Revert'
|
|
35
|
-
RUN = 'Run'
|
|
36
|
-
SAVE = 'Save'
|
|
37
|
-
SCRIPT = 'Script'
|
|
38
|
-
SAVE_PDF = 'Save as PDF'
|
|
39
|
-
SEARCH = 'Search'
|
|
40
|
-
SEND = 'Send'
|
|
41
|
-
START = 'Start'
|
|
42
|
-
UPDATE = 'Update'
|
|
43
|
-
UPGRADE = 'Upgrade'
|
|
44
|
-
USE = 'Use'
|
|
45
|
-
WINDOWS = 'Windows'
|
|
46
|
-
YES = 'Yes'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|