CTkFileDialog-plus 2.1.1__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.
@@ -0,0 +1,45 @@
1
+ """
2
+ This module is part of the CTkFileDialog library.
3
+
4
+ It defines system path constants that point to useful directories such as the
5
+ user's home, config, cache, and data folders, as well as the system PATH and temp directory.
6
+
7
+ These constants follow the XDG Base Directory Specification where possible,
8
+ and serve as a utility for file dialogs and other filesystem operations within the library.
9
+
10
+ Available constants:
11
+
12
+ - PWD: Current working directory where the program was launched.
13
+ - HOME: User's home directory.
14
+ - TEMP: Temporary directory, resolved from common environment variables or defaulting to /tmp.
15
+ - CONFIG_DIR: XDG-compliant user configuration directory (e.g., ~/.config).
16
+ - CACHE_DIR: XDG-compliant user cache directory (e.g., ~/.cache).
17
+ - DATA_DIR: XDG-compliant user data directory (e.g., ~/.local/share).
18
+ - PATH: List of directories in the system PATH environment variable.
19
+ - VENV: Path to the active Python virtual environment (VIRTUAL_ENV or CONDA_PREFIX).
20
+ - DOWNLOAD_DIR: Default download directory (e.g., ~/Downloads).
21
+ - DOWNLOAD_DIR_VIDEO: Default video download directory (e.g., ~/Downloads/Video).
22
+
23
+ Author: Flick
24
+ Repository: https://github.com/FlickGMD/CTkFileDialog
25
+
26
+ Modified: by abdelilah
27
+ https://github.com/hmidani-abdelilah/CTkFileDialog-plus
28
+
29
+ """
30
+
31
+ from .constants import PWD, HOME, PATH, TEMP, CONFIG_DIR, CACHE_DIR, DATA_DIR, VENV, PATHS ,DOWNLOAD_DIR, DOWNLOAD_DIR_VIDEO
32
+
33
+ __all__ = [
34
+ 'PWD',
35
+ 'HOME',
36
+ 'PATH',
37
+ 'TEMP',
38
+ 'CACHE_DIR',
39
+ 'CONFIG_DIR',
40
+ 'DATA_DIR',
41
+ 'VENV',
42
+ 'PATHS',
43
+ 'DOWNLOAD_DIR',
44
+ 'DOWNLOAD_DIR_VIDEO',
45
+ ]
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python
2
+ from pathlib import Path
3
+ import os
4
+
5
+ # Current working directory (e.g., where the program was launched)
6
+ PWD = str(Path.cwd())
7
+
8
+ # User's home directory (e.g., /home/user or C:\Users\user)
9
+ HOME = str(Path.home())
10
+
11
+
12
+
13
+ # System PATH split into a list of directories
14
+ PATH = os.getenv('PATH').split(os.pathsep)
15
+
16
+ # Temporary directory (fallback to /tmp if no env vars are set)
17
+ TEMP = os.getenv('TMPDIR') or os.getenv('TEMP') or os.getenv('TMP')
18
+
19
+ # XDG-compliant user configuration directory (default: ~/.config)
20
+ CONFIG_DIR = os.getenv('XDG_CONFIG_HOME', str(Path(HOME) / '.config'))
21
+
22
+ # XDG-compliant user cache directory (default: ~/.cache)
23
+ CACHE_DIR = os.getenv('XDG_CACHE_HOME', str(Path(HOME) / '.cache'))
24
+
25
+ # XDG-compliant user data directory (default: ~/.local/share)
26
+ DATA_DIR = os.getenv('XDG_DATA_HOME', str(Path(HOME) / '.local' / 'share'))
27
+
28
+ # Active Python virtual environment (venv or conda), fallback to PWD
29
+ VENV = os.getenv("VIRTUAL_ENV") or os.getenv("CONDA_PREFIX") or PWD
30
+
31
+ # Download directory windows and linux (default: ~/Downloads)
32
+ DOWNLOAD_DIR = str(Path(HOME) / 'Downloads')
33
+
34
+ # Download directory Video windows and linux (default: ~/Downloads/Video )
35
+ DOWNLOAD_DIR_VIDEO = str(Path(DOWNLOAD_DIR) / 'Video')
36
+ # create the directory if it doesn't exist
37
+ if not os.path.exists(DOWNLOAD_DIR_VIDEO):
38
+ os.makedirs(DOWNLOAD_DIR_VIDEO)
39
+
40
+
41
+ # All paths in a single dictionary for easy access
42
+ PATHS = {
43
+ "HOME": HOME,
44
+ "PWD": PWD,
45
+ "TEMP": TEMP,
46
+ "CONFIG_DIR": CONFIG_DIR,
47
+ "DATA_DIR": DATA_DIR,
48
+ "CACHE_DIR": CACHE_DIR,
49
+ "PATH": PATH,
50
+ 'VENV': VENV,
51
+ 'DOWNLOAD_DIR': DOWNLOAD_DIR,
52
+ 'DOWNLOAD_DIR_VIDEO': DOWNLOAD_DIR_VIDEO
53
+ }
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python
2
+ """Backward-compatibility shim.
3
+
4
+ Historically all dialog classes lived in this module. They have been
5
+ moved to ``CTkFileDialog.ui``. This file re-exports the public names so
6
+ any external ``from CTkFileDialog.Dialog import _DrawApp`` continues to
7
+ work.
8
+ """
9
+ from .ui.default_dialog import DrawApp, _DrawApp
10
+ from .ui.mini_dialog import MiniDialog, _MiniDialog
11
+ from .ui.tooltip import CustomToolTip
12
+ from .system.platform import System as _System
13
+
14
+ # Historical private name
15
+ _CustomToolTip = CustomToolTip
16
+
17
+ __all__ = [
18
+ "DrawApp",
19
+ "_DrawApp",
20
+ "MiniDialog",
21
+ "_MiniDialog",
22
+ "CustomToolTip",
23
+ "_CustomToolTip",
24
+ "_System",
25
+ ]
@@ -0,0 +1,36 @@
1
+ '''
2
+ File dialog created in custom Tkinter and inspired by the Tkinter dialog.
3
+
4
+ - Version: 0.3.3
5
+ - Author: Flick
6
+ - Github: https://github.com/FlickGMD/CTkFileDialog
7
+ - License: MIT
8
+ - Version: 0.1.0
9
+ - Author: abdelilah
10
+ - Github: https://github.com/hmidani-abdelilah/CTkFileDialog-plus
11
+ - License: MIT
12
+ '''
13
+ from ._functions import (
14
+ askopenfilename, askdirectory, askopenfile, askopenfiles, askopenfilenames,
15
+ asksaveasfile, asksaveasfilename,
16
+ askopendirname, askopendirnames,
17
+ askopenpathname, askopenpathnames,
18
+ )
19
+ from . import Constants
20
+
21
+ __version__ = '0.3.3'
22
+ __all__ = [
23
+ 'askopenfilename',
24
+ 'askdirectory',
25
+ 'askopenfile',
26
+ 'askopenfiles',
27
+ 'askopenfilenames',
28
+ 'asksaveasfile',
29
+ 'asksaveasfilename',
30
+ 'askopendirname',
31
+ 'askopendirnames',
32
+ 'askopenpathname',
33
+ 'askopenpathnames',
34
+ 'Constants'
35
+ ]
36
+
@@ -0,0 +1,521 @@
1
+ #!/usr/bin/env python
2
+ """Public dialog functions — API surface is unchanged."""
3
+ from __future__ import annotations
4
+
5
+ from typing import List, Literal, Optional, TextIO, Tuple, Union
6
+
7
+ from typeguard import typechecked
8
+
9
+ from .ui.default_dialog import _DrawApp
10
+ from .ui.mini_dialog import _MiniDialog
11
+ from .utils.helpers import apply_defaultext, normalize_filetypes
12
+
13
+
14
+ # Re-export helpers under historical private names for any external use
15
+ _normalize_filetypes = normalize_filetypes
16
+ _apply_defaultext = apply_defaultext
17
+
18
+
19
+ @typechecked
20
+ def askopenfilename(
21
+ style: Literal["Mini", "Default"] = "Default",
22
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
23
+ hidden: bool = False,
24
+ preview_img: bool = False,
25
+ autocomplete: bool = False,
26
+ video_preview: bool = False,
27
+ initial_dir: str = ".",
28
+ tool_tip: bool = False,
29
+ foldercreation: bool = True,
30
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
31
+ title: str = "CTkFileDialog",
32
+ ) -> str | None:
33
+ """
34
+ Displays a file dialog for selecting a single file and returns the file path.
35
+ """
36
+ normalized = normalize_filetypes(filetypes)
37
+ if style == "Default":
38
+ app = _DrawApp(
39
+ filetypes=normalized,
40
+ current_path=initial_dir,
41
+ hidden=hidden,
42
+ preview_img=preview_img,
43
+ method="askopenfilename",
44
+ autocomplete=autocomplete,
45
+ video_preview=video_preview,
46
+ tool_tip=tool_tip,
47
+ foldercreation=foldercreation,
48
+ geometry=geometry[0],
49
+ title=title,
50
+ )
51
+ app.app.wait_window()
52
+ return app.selected_file if app.selected_file else None
53
+ elif style == "Mini":
54
+ app = _MiniDialog(
55
+ method="askopenfilename",
56
+ filetypes=normalized,
57
+ initial_dir=initial_dir,
58
+ autocomplete=autocomplete,
59
+ hidden=hidden,
60
+ foldercreation=foldercreation,
61
+ geometry=geometry[1],
62
+ title=title,
63
+ )
64
+ return app.selected_path
65
+
66
+
67
+ @typechecked
68
+ def askdirectory(
69
+ style: Literal["Default", "Mini"] = "Default",
70
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
71
+ hidden: bool = False,
72
+ autocomplete: bool = False,
73
+ initial_dir: str = ".",
74
+ tool_tip: bool = False,
75
+ foldercreation: bool = True,
76
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
77
+ title: str = "CTkFileDialog",
78
+ ) -> str | None:
79
+ """Displays a directory selection dialog and returns the selected path."""
80
+ normalized = normalize_filetypes(filetypes)
81
+ if style == "Default":
82
+ app = _DrawApp(
83
+ filetypes=normalized,
84
+ current_path=initial_dir,
85
+ hidden=hidden,
86
+ method="askdirectory",
87
+ autocomplete=autocomplete,
88
+ tool_tip=tool_tip,
89
+ foldercreation=foldercreation,
90
+ geometry=geometry[0],
91
+ title=title,
92
+ )
93
+ app.app.wait_window()
94
+ return app.selected_file if app.selected_file else None
95
+ elif style == "Mini":
96
+ app = _MiniDialog(
97
+ filetypes=normalized,
98
+ initial_dir=initial_dir,
99
+ hidden=hidden,
100
+ method="askdirectory",
101
+ autocomplete=autocomplete,
102
+ foldercreation=foldercreation,
103
+ title=title,
104
+ geometry=geometry[1],
105
+ )
106
+ return app.selected_path if app.selected_path else None
107
+
108
+
109
+ @typechecked
110
+ def askopendirname(
111
+ style: Literal["Default", "Mini"] = "Default",
112
+ hidden: bool = False,
113
+ autocomplete: bool = False,
114
+ initial_dir: str = ".",
115
+ tool_tip: bool = False,
116
+ foldercreation: bool = True,
117
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
118
+ title: str = "CTkFileDialog",
119
+ ) -> str:
120
+ """Allow the user to choose a single directory."""
121
+ if style == "Default":
122
+ app = _DrawApp(
123
+ current_path=initial_dir,
124
+ hidden=hidden,
125
+ method="askdirectory",
126
+ autocomplete=autocomplete,
127
+ tool_tip=tool_tip,
128
+ foldercreation=foldercreation,
129
+ geometry=geometry[0],
130
+ title=title,
131
+ )
132
+ app.app.wait_window()
133
+ return app.selected_file if app.selected_file else ""
134
+ elif style == "Mini":
135
+ app = _MiniDialog(
136
+ initial_dir=initial_dir,
137
+ hidden=hidden,
138
+ method="askdirectory",
139
+ autocomplete=autocomplete,
140
+ foldercreation=foldercreation,
141
+ title=title,
142
+ geometry=geometry[1],
143
+ )
144
+ return app.selected_path if app.selected_path else ""
145
+
146
+
147
+ @typechecked
148
+ def askopendirnames(
149
+ style: Literal["Default", "Mini"] = "Default",
150
+ hidden: bool = False,
151
+ autocomplete: bool = False,
152
+ initial_dir: str = ".",
153
+ tool_tip: bool = False,
154
+ foldercreation: bool = True,
155
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
156
+ title: str = "CTkFileDialog",
157
+ ) -> tuple[str, ...]:
158
+ """Allow the user to choose multiple directories (Ctrl/Shift + click)."""
159
+ if style == "Default":
160
+ app = _DrawApp(
161
+ current_path=initial_dir,
162
+ hidden=hidden,
163
+ method="askdirectories",
164
+ autocomplete=autocomplete,
165
+ tool_tip=tool_tip,
166
+ foldercreation=foldercreation,
167
+ geometry=geometry[0],
168
+ title=title,
169
+ )
170
+ app.app.wait_window()
171
+ return tuple(app.selected_objects) if app.selected_objects else tuple()
172
+ elif style == "Mini":
173
+ app = _MiniDialog(
174
+ initial_dir=initial_dir,
175
+ hidden=hidden,
176
+ method="askdirectories",
177
+ autocomplete=autocomplete,
178
+ foldercreation=foldercreation,
179
+ title=title,
180
+ geometry=geometry[1],
181
+ )
182
+ return tuple(app.selected_paths) if app.selected_paths else tuple()
183
+
184
+
185
+ @typechecked
186
+ def askopenpathname(
187
+ style: Literal["Default", "Mini"] = "Default",
188
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
189
+ hidden: bool = False,
190
+ preview_img: bool = False,
191
+ autocomplete: bool = False,
192
+ video_preview: bool = False,
193
+ initial_dir: str = ".",
194
+ tool_tip: bool = False,
195
+ foldercreation: bool = True,
196
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
197
+ title: str = "CTkFileDialog",
198
+ ) -> str:
199
+ """Allow the user to choose a single file or folder."""
200
+ normalized = normalize_filetypes(filetypes)
201
+ if style == "Default":
202
+ app = _DrawApp(
203
+ filetypes=normalized,
204
+ current_path=initial_dir,
205
+ hidden=hidden,
206
+ preview_img=preview_img,
207
+ method="askopenpathname",
208
+ autocomplete=autocomplete,
209
+ video_preview=video_preview,
210
+ tool_tip=tool_tip,
211
+ foldercreation=foldercreation,
212
+ geometry=geometry[0],
213
+ title=title,
214
+ )
215
+ app.app.wait_window()
216
+ return app.selected_file if app.selected_file else ""
217
+ elif style == "Mini":
218
+ app = _MiniDialog(
219
+ method="askopenpathname",
220
+ filetypes=normalized,
221
+ initial_dir=initial_dir,
222
+ autocomplete=autocomplete,
223
+ hidden=hidden,
224
+ foldercreation=foldercreation,
225
+ geometry=geometry[1],
226
+ title=title,
227
+ )
228
+ return app.selected_path if app.selected_path else ""
229
+
230
+
231
+ @typechecked
232
+ def askopenpathnames(
233
+ style: Literal["Default", "Mini"] = "Default",
234
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
235
+ hidden: bool = False,
236
+ preview_img: bool = False,
237
+ autocomplete: bool = False,
238
+ video_preview: bool = False,
239
+ initial_dir: str = ".",
240
+ tool_tip: bool = False,
241
+ foldercreation: bool = True,
242
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
243
+ title: str = "CTkFileDialog",
244
+ ) -> tuple[str, ...]:
245
+ """Allow the user to choose multiple files and folders (Ctrl/Shift + click)."""
246
+ normalized = normalize_filetypes(filetypes)
247
+ if style == "Default":
248
+ app = _DrawApp(
249
+ filetypes=normalized,
250
+ current_path=initial_dir,
251
+ hidden=hidden,
252
+ preview_img=preview_img,
253
+ method="askopenpathnames",
254
+ autocomplete=autocomplete,
255
+ video_preview=video_preview,
256
+ tool_tip=tool_tip,
257
+ foldercreation=foldercreation,
258
+ geometry=geometry[0],
259
+ title=title,
260
+ )
261
+ app.app.wait_window()
262
+ return tuple(app.selected_objects) if app.selected_objects else tuple()
263
+ elif style == "Mini":
264
+ app = _MiniDialog(
265
+ filetypes=normalized,
266
+ initial_dir=initial_dir,
267
+ hidden=hidden,
268
+ autocomplete=autocomplete,
269
+ method="askopenpathnames",
270
+ foldercreation=foldercreation,
271
+ geometry=geometry[1],
272
+ title=title,
273
+ )
274
+ return tuple(app.selected_paths) if app.selected_paths else tuple()
275
+
276
+
277
+ @typechecked
278
+ def askopenfilenames(
279
+ style: Literal["Default", "Mini"] = "Default",
280
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
281
+ hidden: bool = False,
282
+ preview_img: bool = False,
283
+ autocomplete: bool = False,
284
+ video_preview: bool = False,
285
+ initial_dir: str = ".",
286
+ tool_tip: bool = False,
287
+ foldercreation: bool = True,
288
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
289
+ title: str = "CTkFileDialog",
290
+ ) -> tuple[str, ...] | None:
291
+ """Displays a file dialog for multiple file selection."""
292
+ normalized = normalize_filetypes(filetypes)
293
+ if style == "Default":
294
+ app = _DrawApp(
295
+ filetypes=normalized,
296
+ current_path=initial_dir,
297
+ hidden=hidden,
298
+ preview_img=preview_img,
299
+ method="askopenfilenames",
300
+ autocomplete=autocomplete,
301
+ video_preview=video_preview,
302
+ tool_tip=tool_tip,
303
+ foldercreation=foldercreation,
304
+ geometry=geometry[0],
305
+ title=title,
306
+ )
307
+ app.app.wait_window()
308
+ return tuple(app.selected_objects) if app.selected_objects else None
309
+ elif style == "Mini":
310
+ app = _MiniDialog(
311
+ filetypes=normalized,
312
+ initial_dir=initial_dir,
313
+ hidden=hidden,
314
+ method="askopenfilenames",
315
+ autocomplete=autocomplete,
316
+ foldercreation=foldercreation,
317
+ geometry=geometry[1],
318
+ title=title,
319
+ )
320
+ return tuple(app.selected_paths) if app.selected_paths else None
321
+
322
+
323
+ @typechecked
324
+ def asksaveasfilename(
325
+ style: Literal["Default", "Mini"] = "Default",
326
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
327
+ hidden: bool = False,
328
+ preview_img: bool = False,
329
+ autocomplete: bool = False,
330
+ video_preview: bool = False,
331
+ initial_dir: str = ".",
332
+ tool_tip: bool = False,
333
+ foldercreation: bool = True,
334
+ defaultext: Optional[str] = None,
335
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
336
+ title: str = "CTkFileDialog",
337
+ ) -> str | None:
338
+ """Displays a save file dialog and returns the selected path."""
339
+ normalized = normalize_filetypes(filetypes)
340
+ if style == "Default":
341
+ app = _DrawApp(
342
+ filetypes=normalized,
343
+ current_path=initial_dir,
344
+ hidden=hidden,
345
+ preview_img=preview_img,
346
+ method="asksaveasfilename",
347
+ autocomplete=autocomplete,
348
+ video_preview=video_preview,
349
+ tool_tip=tool_tip,
350
+ foldercreation=foldercreation,
351
+ geometry=geometry[0],
352
+ title=title,
353
+ )
354
+ app.app.wait_window()
355
+ return apply_defaultext(app.selected_file, defaultext) if app.selected_file else None
356
+ elif style == "Mini":
357
+ app = _MiniDialog(
358
+ filetypes=normalized,
359
+ initial_dir=initial_dir,
360
+ hidden=hidden,
361
+ method="asksaveasfilename",
362
+ autocomplete=autocomplete,
363
+ foldercreation=foldercreation,
364
+ geometry=geometry[1],
365
+ title=title,
366
+ )
367
+ return apply_defaultext(app.selected_path, defaultext) if app.selected_path else None
368
+
369
+
370
+ @typechecked
371
+ def asksaveasfile(
372
+ style: Literal["Default", "Mini"] = "Default",
373
+ mode: Literal["r", "rb", "r+", "rb+", "r+b", "w", "wb", "w+", "wb+", "a", "ab", "a+", "ab+", "x", "xb"] = "w",
374
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
375
+ hidden: bool = False,
376
+ preview_img: bool = False,
377
+ autocomplete: bool = False,
378
+ video_preview: bool = False,
379
+ initial_dir: str = ".",
380
+ tool_tip: bool = False,
381
+ foldercreation: bool = True,
382
+ defaultext: Optional[str] = None,
383
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
384
+ title: str = "CTkFileDialog",
385
+ **kwargs,
386
+ ) -> TextIO | None:
387
+ """Displays a save dialog and returns an open file object."""
388
+ normalized = normalize_filetypes(filetypes)
389
+ if style == "Default":
390
+ app = _DrawApp(
391
+ filetypes=normalized,
392
+ current_path=initial_dir,
393
+ hidden=hidden,
394
+ preview_img=preview_img,
395
+ method="asksaveasfile",
396
+ autocomplete=autocomplete,
397
+ video_preview=video_preview,
398
+ tool_tip=tool_tip,
399
+ foldercreation=foldercreation,
400
+ geometry=geometry[0],
401
+ title=title,
402
+ )
403
+ app.app.wait_window()
404
+ selected = apply_defaultext(app.selected_file, defaultext)
405
+ return open(selected, mode=mode, **kwargs) if selected else None
406
+ elif style == "Mini":
407
+ app = _MiniDialog(
408
+ filetypes=normalized,
409
+ initial_dir=initial_dir,
410
+ hidden=hidden,
411
+ method="asksaveasfile",
412
+ foldercreation=foldercreation,
413
+ geometry=geometry[1],
414
+ title=title,
415
+ )
416
+ selected = apply_defaultext(app.selected_path, defaultext)
417
+ return open(selected, mode=mode, **kwargs) if selected else None
418
+
419
+
420
+ @typechecked
421
+ def askopenfile(
422
+ style: Literal["Mini", "Default"] = "Default",
423
+ mode: Literal["r", "rb", "r+", "rb+", "r+b", "w", "wb", "w+", "wb+", "a", "ab", "a+", "ab+", "x", "xb"] = "r",
424
+ hidden: bool = False,
425
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
426
+ preview_img: bool = False,
427
+ autocomplete: bool = False,
428
+ video_preview: bool = False,
429
+ initial_dir: str = ".",
430
+ tool_tip: bool = False,
431
+ foldercreation: bool = True,
432
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
433
+ title: str = "CTkFileDialog",
434
+ **kwargs,
435
+ ) -> TextIO | None:
436
+ """Displays an open file dialog and returns an open file object."""
437
+ normalized = normalize_filetypes(filetypes)
438
+ if style == "Default":
439
+ app = _DrawApp(
440
+ filetypes=normalized,
441
+ current_path=initial_dir,
442
+ hidden=hidden,
443
+ preview_img=preview_img,
444
+ method="askopenfile",
445
+ autocomplete=autocomplete,
446
+ video_preview=video_preview,
447
+ tool_tip=tool_tip,
448
+ foldercreation=foldercreation,
449
+ geometry=geometry[0],
450
+ title=title,
451
+ )
452
+ app.app.wait_window()
453
+ return open(app.selected_file, mode=mode, **kwargs) if app.selected_file else None
454
+ elif style == "Mini":
455
+ app = _MiniDialog(
456
+ filetypes=normalized,
457
+ initial_dir=initial_dir,
458
+ hidden=hidden,
459
+ method="askopenfile",
460
+ autocomplete=autocomplete,
461
+ foldercreation=foldercreation,
462
+ geometry=geometry[1],
463
+ title=title,
464
+ )
465
+ return open(app.selected_path, mode=mode, **kwargs) if app.selected_path else None
466
+
467
+
468
+ @typechecked
469
+ def askopenfiles(
470
+ style: Literal["Default", "Mini"] = "Default",
471
+ mode: Literal["r", "rb", "r+", "rb+", "r+b", "w", "wb", "w+", "wb+", "a", "ab", "a+", "ab+", "x", "xb"] = "r",
472
+ hidden: bool = False,
473
+ filetypes: Optional[List[Union[str, Tuple[str, str]]]] = None,
474
+ preview_img: bool = False,
475
+ autocomplete: bool = False,
476
+ video_preview: bool = False,
477
+ initial_dir: str = ".",
478
+ tool_tip: bool = False,
479
+ foldercreation: bool = True,
480
+ geometry: Tuple[str, str] = ("1320x720", "500x400"),
481
+ title: str = "CTkFileDialog",
482
+ **kwargs,
483
+ ) -> tuple[TextIO, ...] | None:
484
+ """Displays a multi-file open dialog and returns multiple open file objects."""
485
+ normalized = normalize_filetypes(filetypes)
486
+ if style == "Default":
487
+ app = _DrawApp(
488
+ filetypes=normalized,
489
+ current_path=initial_dir,
490
+ hidden=hidden,
491
+ preview_img=preview_img,
492
+ method="askopenfilenames",
493
+ autocomplete=autocomplete,
494
+ video_preview=video_preview,
495
+ tool_tip=tool_tip,
496
+ foldercreation=foldercreation,
497
+ geometry=geometry[0],
498
+ title=title,
499
+ )
500
+ app.app.wait_window()
501
+ return (
502
+ tuple(open(f, mode=mode, **kwargs) for f in app.selected_objects)
503
+ if app.selected_objects
504
+ else None
505
+ )
506
+ elif style == "Mini":
507
+ app = _MiniDialog(
508
+ filetypes=normalized,
509
+ initial_dir=initial_dir,
510
+ hidden=hidden,
511
+ autocomplete=autocomplete,
512
+ method="askopenfilenames",
513
+ foldercreation=foldercreation,
514
+ geometry=geometry[1],
515
+ title=title,
516
+ )
517
+ return (
518
+ tuple(open(f, mode=mode, **kwargs) for f in app.selected_paths)
519
+ if app.selected_paths
520
+ else None
521
+ )
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env python
2
+ """Backward-compatibility shim for platform helpers."""
3
+ from .system.platform import find_owner, System
4
+
5
+ __all__ = ["find_owner", "System"]