quickmacapp 2025.4.15__py3-none-any.whl → 2025.6.24__py3-none-any.whl
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.
- quickmacapp/__init__.py +2 -1
- quickmacapp/_quickapp.py +86 -23
- {quickmacapp-2025.4.15.dist-info → quickmacapp-2025.6.24.dist-info}/METADATA +1 -1
- quickmacapp-2025.6.24.dist-info/RECORD +12 -0
- {quickmacapp-2025.4.15.dist-info → quickmacapp-2025.6.24.dist-info}/WHEEL +1 -1
- quickmacapp-2025.4.15.dist-info/RECORD +0 -12
- {quickmacapp-2025.4.15.dist-info → quickmacapp-2025.6.24.dist-info}/licenses/LICENSE +0 -0
- {quickmacapp-2025.4.15.dist-info → quickmacapp-2025.6.24.dist-info}/top_level.txt +0 -0
quickmacapp/__init__.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from ._quickapp import Actionable, Status, mainpoint, menu, quit
|
|
1
|
+
from ._quickapp import Actionable, ItemState, Status, mainpoint, menu, quit
|
|
2
2
|
from ._interactions import ask, choose, answer, getpass
|
|
3
3
|
from ._background import dockIconWhenVisible
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"Actionable",
|
|
7
|
+
"ItemState",
|
|
7
8
|
"Status",
|
|
8
9
|
"mainpoint",
|
|
9
10
|
"menu",
|
quickmacapp/_quickapp.py
CHANGED
|
@@ -3,31 +3,48 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
import traceback
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
from
|
|
9
|
-
|
|
10
|
-
from Foundation import (
|
|
11
|
-
NSObject,
|
|
12
|
-
NSException,
|
|
13
|
-
)
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from types import FunctionType
|
|
8
|
+
from typing import Any, Callable, Iterable, Protocol, Sequence, Literal
|
|
14
9
|
|
|
15
10
|
from AppKit import (
|
|
16
11
|
NSApp,
|
|
17
12
|
NSApplication,
|
|
18
13
|
NSEvent,
|
|
19
|
-
NSResponder,
|
|
20
|
-
NSMenu,
|
|
21
14
|
NSImage,
|
|
15
|
+
NSMenu,
|
|
22
16
|
NSMenuItem,
|
|
17
|
+
NSResponder,
|
|
23
18
|
NSStatusBar,
|
|
24
19
|
NSVariableStatusItemLength,
|
|
20
|
+
NSControlStateValueOn,
|
|
21
|
+
NSControlStateValueOff,
|
|
25
22
|
)
|
|
26
|
-
|
|
23
|
+
from ExceptionHandling import NSStackTraceKey # type:ignore
|
|
24
|
+
from Foundation import NSException, NSObject
|
|
25
|
+
from objc import IBAction, ivar, super
|
|
27
26
|
from PyObjCTools.Debugging import _run_atos, isPythonException
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def asSelectorString(f: FunctionType) -> str:
|
|
30
|
+
"""
|
|
31
|
+
Convert a method on a PyObjC class into a selector string.
|
|
32
|
+
"""
|
|
33
|
+
return f.__name__.replace("_", ":")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(kw_only=True)
|
|
37
|
+
class ItemState:
|
|
38
|
+
"""
|
|
39
|
+
The state of a menu item.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
enabled: bool = True
|
|
43
|
+
"Should the menu item be disabled? True if not, False if so."
|
|
44
|
+
checked: bool = False
|
|
45
|
+
"Should the menu item display a check-mark next to itself? True if so, False if not."
|
|
46
|
+
key: str | None = None
|
|
47
|
+
"Should the menu shortcut mnemonic key be set, blank, or derived from the item's title?"
|
|
31
48
|
|
|
32
49
|
|
|
33
50
|
class Actionable(NSObject):
|
|
@@ -35,15 +52,20 @@ class Actionable(NSObject):
|
|
|
35
52
|
Wrap a Python no-argument function call in an NSObject with a C{doIt:}
|
|
36
53
|
method.
|
|
37
54
|
"""
|
|
38
|
-
_thunk: Callable[[], None]
|
|
39
55
|
|
|
40
|
-
|
|
56
|
+
_thunk: Callable[[], object]
|
|
57
|
+
_state: ItemState
|
|
58
|
+
|
|
59
|
+
def initWithFunction_andState_(
|
|
60
|
+
self, thunk: Callable[[], None], state: ItemState
|
|
61
|
+
) -> Actionable:
|
|
41
62
|
"""
|
|
42
63
|
Remember the given callable.
|
|
43
64
|
|
|
44
65
|
@param thunk: the callable to run in L{doIt_}.
|
|
45
66
|
"""
|
|
46
67
|
self._thunk = thunk
|
|
68
|
+
self._state = state
|
|
47
69
|
return self
|
|
48
70
|
|
|
49
71
|
@IBAction
|
|
@@ -52,10 +74,41 @@ class Actionable(NSObject):
|
|
|
52
74
|
Call the given callable; exposed as an C{IBAction} in case you want IB
|
|
53
75
|
to be able to see it.
|
|
54
76
|
"""
|
|
55
|
-
self._thunk()
|
|
77
|
+
result = self._thunk()
|
|
78
|
+
if isinstance(result, ItemState):
|
|
79
|
+
self._state = result
|
|
80
|
+
|
|
81
|
+
def validateMenuItem_(self, item: NSMenuItem) -> bool:
|
|
82
|
+
item.setState_(
|
|
83
|
+
NSControlStateValueOn if self._state.checked else NSControlStateValueOff
|
|
84
|
+
)
|
|
85
|
+
return self._state.enabled
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
ACTION_METHOD = asSelectorString(Actionable.doIt_)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _adjust(
|
|
92
|
+
items: Iterable[
|
|
93
|
+
tuple[str, Callable[[], object]] | tuple[str, Callable[[], object], ItemState]
|
|
94
|
+
],
|
|
95
|
+
) -> Iterable[tuple[str, Callable[[], object], ItemState]]:
|
|
96
|
+
for item in items:
|
|
97
|
+
if len(item) == 3:
|
|
98
|
+
yield item
|
|
99
|
+
else:
|
|
100
|
+
yield (*item, ItemState())
|
|
101
|
+
|
|
56
102
|
|
|
103
|
+
ItemSeq = Sequence[
|
|
104
|
+
tuple[str, Callable[[], object]] | tuple[str, Callable[[], object], ItemState]
|
|
105
|
+
]
|
|
57
106
|
|
|
58
|
-
|
|
107
|
+
|
|
108
|
+
def menu(
|
|
109
|
+
title: str,
|
|
110
|
+
items: ItemSeq,
|
|
111
|
+
) -> NSMenu:
|
|
59
112
|
"""
|
|
60
113
|
Construct an NSMenu from a list of tuples describing it.
|
|
61
114
|
|
|
@@ -68,11 +121,16 @@ def menu(title: str, items: list[tuple[str, Callable[[], object]]]) -> NSMenu:
|
|
|
68
121
|
@return: a new Menu tha is not attached to anything.
|
|
69
122
|
"""
|
|
70
123
|
result = NSMenu.alloc().initWithTitle_(title)
|
|
71
|
-
for
|
|
124
|
+
for subtitle, thunk, state in _adjust(items):
|
|
125
|
+
initialKeyEquivalent = subtitle[0].lower()
|
|
72
126
|
item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
|
|
73
|
-
subtitle,
|
|
127
|
+
subtitle,
|
|
128
|
+
ACTION_METHOD,
|
|
129
|
+
initialKeyEquivalent if state.key is None else state.key,
|
|
130
|
+
)
|
|
131
|
+
item.setTarget_(
|
|
132
|
+
Actionable.alloc().initWithFunction_andState_(thunk, state).retain()
|
|
74
133
|
)
|
|
75
|
-
item.setTarget_(Actionable.alloc().initWithFunction_(thunk).retain())
|
|
76
134
|
result.addItem_(item)
|
|
77
135
|
result.update()
|
|
78
136
|
return result
|
|
@@ -97,11 +155,12 @@ class Status:
|
|
|
97
155
|
self.item.button().setImage_(image)
|
|
98
156
|
elif text is None:
|
|
99
157
|
from __main__ import __file__ as default
|
|
158
|
+
|
|
100
159
|
text = os.path.basename(default)
|
|
101
160
|
if text is not None:
|
|
102
161
|
self.item.button().setTitle_(text)
|
|
103
162
|
|
|
104
|
-
def menu(self, items:
|
|
163
|
+
def menu(self, items: ItemSeq) -> None:
|
|
105
164
|
"""
|
|
106
165
|
Set the status drop-down menu.
|
|
107
166
|
|
|
@@ -183,6 +242,7 @@ class QuickApplication(NSApplication):
|
|
|
183
242
|
be more complicated in LSUIElement apps, but there might be a better
|
|
184
243
|
way to do this.)
|
|
185
244
|
"""
|
|
245
|
+
|
|
186
246
|
keyEquivalentHandler: NSResponder = ivar()
|
|
187
247
|
|
|
188
248
|
def sendEvent_(self, event: NSEvent) -> None:
|
|
@@ -210,6 +270,7 @@ class MainRunner(Protocol):
|
|
|
210
270
|
"""
|
|
211
271
|
A function which has been decorated with a runMain attribute.
|
|
212
272
|
"""
|
|
273
|
+
|
|
213
274
|
def __call__(self, reactor: Any) -> None:
|
|
214
275
|
"""
|
|
215
276
|
@param reactor: A Twisted reactor, which provides the usual suspects of
|
|
@@ -218,6 +279,7 @@ class MainRunner(Protocol):
|
|
|
218
279
|
|
|
219
280
|
runMain: Callable[[], None]
|
|
220
281
|
|
|
282
|
+
|
|
221
283
|
def mainpoint() -> Callable[[Callable[[Any], None]], MainRunner]:
|
|
222
284
|
"""
|
|
223
285
|
Add a .runMain attribute to function
|
|
@@ -227,10 +289,11 @@ def mainpoint() -> Callable[[Callable[[Any], None]], MainRunner]:
|
|
|
227
289
|
The runMain attribute starts a reactor and calls the original function
|
|
228
290
|
with a running, initialized, reactor.
|
|
229
291
|
"""
|
|
292
|
+
|
|
230
293
|
def wrapup(appmain: Callable[[Any], None]) -> MainRunner:
|
|
231
294
|
def doIt() -> None:
|
|
232
|
-
from twisted.internet import cfreactor
|
|
233
295
|
import PyObjCTools.AppHelper
|
|
296
|
+
from twisted.internet import cfreactor
|
|
234
297
|
|
|
235
298
|
QuickApplication.sharedApplication()
|
|
236
299
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
quickmacapp/__init__.py,sha256=WAfaenkgALceVKrSmVBoEOJER-SX65r4WjkaBGtmO24,363
|
|
2
|
+
quickmacapp/_background.py,sha256=M_ob3EF8v-Z_gpKuFDl2N9XrQz0eBLFfUp2XErDB3DU,5943
|
|
3
|
+
quickmacapp/_interactions.py,sha256=eLv_mVf5Jr-puNizlR8tDL_DlLy1Rc82XQ80o0GP5R4,3439
|
|
4
|
+
quickmacapp/_notifications.py,sha256=DNm4-vOF0wQNUUTBHqp3-RKXVQK98ef53isxwsWqyj8,16965
|
|
5
|
+
quickmacapp/_quickapp.py,sha256=cjMEzhofV8pq-rkcdjHTvUG1Omn2kQDKD4uzmAWLAAA,9273
|
|
6
|
+
quickmacapp/notifications.py,sha256=UCigVIurf-zWAqVXUYjTtz_xMjcoI23dqyJ4OzZurQM,10275
|
|
7
|
+
quickmacapp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
quickmacapp-2025.6.24.dist-info/licenses/LICENSE,sha256=7RIBNNvrnKHR3lw9z3KXv3Q6RRjhyxtNQoMnoUsf3_M,1091
|
|
9
|
+
quickmacapp-2025.6.24.dist-info/METADATA,sha256=9vY7FxxnBVFNeZJIEvJi2bN4ZEiEhiHThFjAQJlwp2Y,1344
|
|
10
|
+
quickmacapp-2025.6.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
quickmacapp-2025.6.24.dist-info/top_level.txt,sha256=_iJkekUYnuWhCZbFSQyo2d5_6B7OoPwx7k527bokzeA,12
|
|
12
|
+
quickmacapp-2025.6.24.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
quickmacapp/__init__.py,sha256=NsZW_cPvJTunDShN3RjOyK1gTwTKsghMb7wb6vRgTXI,335
|
|
2
|
-
quickmacapp/_background.py,sha256=M_ob3EF8v-Z_gpKuFDl2N9XrQz0eBLFfUp2XErDB3DU,5943
|
|
3
|
-
quickmacapp/_interactions.py,sha256=eLv_mVf5Jr-puNizlR8tDL_DlLy1Rc82XQ80o0GP5R4,3439
|
|
4
|
-
quickmacapp/_notifications.py,sha256=DNm4-vOF0wQNUUTBHqp3-RKXVQK98ef53isxwsWqyj8,16965
|
|
5
|
-
quickmacapp/_quickapp.py,sha256=Ed5n9rAw12nlHxyBMzyPc1Vt4K2OVIqCszWPqQyVElk,7571
|
|
6
|
-
quickmacapp/notifications.py,sha256=UCigVIurf-zWAqVXUYjTtz_xMjcoI23dqyJ4OzZurQM,10275
|
|
7
|
-
quickmacapp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
quickmacapp-2025.4.15.dist-info/licenses/LICENSE,sha256=7RIBNNvrnKHR3lw9z3KXv3Q6RRjhyxtNQoMnoUsf3_M,1091
|
|
9
|
-
quickmacapp-2025.4.15.dist-info/METADATA,sha256=KV6153Iy7rHC5Xrgs8RVtTtBauSRG9GNKzOk3btM-Rg,1344
|
|
10
|
-
quickmacapp-2025.4.15.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
11
|
-
quickmacapp-2025.4.15.dist-info/top_level.txt,sha256=_iJkekUYnuWhCZbFSQyo2d5_6B7OoPwx7k527bokzeA,12
|
|
12
|
-
quickmacapp-2025.4.15.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|