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.
- CTkFileDialog/Constants/__init__.py +45 -0
- CTkFileDialog/Constants/constants.py +53 -0
- CTkFileDialog/Dialog.py +25 -0
- CTkFileDialog/__init__.py +36 -0
- CTkFileDialog/_functions.py +521 -0
- CTkFileDialog/_system.py +5 -0
- CTkFileDialog/core/__init__.py +13 -0
- CTkFileDialog/core/filesystem.py +97 -0
- CTkFileDialog/core/search.py +13 -0
- CTkFileDialog/core/sorting.py +41 -0
- CTkFileDialog/preview/__init__.py +4 -0
- CTkFileDialog/preview/media.py +126 -0
- CTkFileDialog/resources/__init__.py +14 -0
- CTkFileDialog/resources/icons.py +89 -0
- CTkFileDialog/system/__init__.py +4 -0
- CTkFileDialog/system/platform.py +88 -0
- CTkFileDialog/ui/__init__.py +5 -0
- CTkFileDialog/ui/default_dialog.py +1013 -0
- CTkFileDialog/ui/mini_dialog.py +454 -0
- CTkFileDialog/ui/tooltip.py +25 -0
- CTkFileDialog/utils/__init__.py +9 -0
- CTkFileDialog/utils/helpers.py +61 -0
- ctkfiledialog_plus-2.1.1.dist-info/METADATA +592 -0
- ctkfiledialog_plus-2.1.1.dist-info/RECORD +27 -0
- ctkfiledialog_plus-2.1.1.dist-info/WHEEL +5 -0
- ctkfiledialog_plus-2.1.1.dist-info/licenses/LICENSE +21 -0
- ctkfiledialog_plus-2.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CTkFileDialog-plus
|
|
3
|
+
Version: 2.1.1
|
|
4
|
+
Summary: A modern file dialog for CustomTkinter
|
|
5
|
+
Home-page: https://github.com/hmidani-abdelilah/CTkFileDialog-plus
|
|
6
|
+
Author: abdelilah
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.7
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: customtkinter
|
|
14
|
+
Requires-Dist: Pillow
|
|
15
|
+
Requires-Dist: opencv-python
|
|
16
|
+
Requires-Dist: CTkMessagebox
|
|
17
|
+
Requires-Dist: CTkToolTip
|
|
18
|
+
Requires-Dist: typeguard
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: classifier
|
|
21
|
+
Dynamic: description
|
|
22
|
+
Dynamic: description-content-type
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: requires-python
|
|
27
|
+
Dynamic: summary
|
|
28
|
+
|
|
29
|
+
<h1 align="center">CTkFileDialog</h1>
|
|
30
|
+
|
|
31
|
+
<h3 align="center">A modern and fully customizable File Dialog for CustomTkinter β a must-have extension pack!</h3>
|
|
32
|
+
|
|
33
|
+
> [!WARNING]
|
|
34
|
+
> Unfortunately parameters like `video_preview`, `preview_img`, and `tooltip` are not compatible with the mini dialog and will not be applied. View modes and sorting are exclusive to the Default dialog.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## π Features
|
|
39
|
+
|
|
40
|
+
- π Autocomplete in the path entry field (with `Tab`, `Up`, and `Down`)
|
|
41
|
+
- π§© Flexible filetype filters: accepts simple extensions **or** tkinter-style `(label, pattern)` tuples (patterns may contain multiple spaceβseparated globs). Wildcards like `*`/`*.*` are treated as matchβall.
|
|
42
|
+
- οΏ½ Search/filter files in real-time
|
|
43
|
+
- πΌοΈ Live image preview
|
|
44
|
+
- π₯ Video thumbnail preview
|
|
45
|
+
- π Directory selection (single or multiple)
|
|
46
|
+
- ππ Combined file-or-folder selection (single or multiple)
|
|
47
|
+
- β Create new folders from within the dialog (`foldercreation`)
|
|
48
|
+
- πΎ Save file dialog (return path or open file), with automatic extension (`defaultext`)
|
|
49
|
+
- β Tooltip support
|
|
50
|
+
- π₯οΈ Shell Path Syntax Support
|
|
51
|
+
- β¨οΈ Backspace using Alt + Left Arrow shortcut
|
|
52
|
+
- π Multiple view modes (Grid and List view in Default dialog)
|
|
53
|
+
- π Sort files by name, date, size, type, or last modified
|
|
54
|
+
- π‘ Data type validation at runtime and for static type analyzers
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## π¦ Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Using bash
|
|
62
|
+
git clone https://github.com/hmidani-abdelilah/CTkFileDialog-plus
|
|
63
|
+
cd CTkFileDialog-plus
|
|
64
|
+
python3 -m venv .venv
|
|
65
|
+
source .venv/bin/activate
|
|
66
|
+
pip3 install -r requirements.txt
|
|
67
|
+
|
|
68
|
+
# On Windows
|
|
69
|
+
git clone https://github.com/hmidani-abdelilah/CTkFileDialog-plus
|
|
70
|
+
cd CTkFileDialog-plus
|
|
71
|
+
python3 -m venv .venv
|
|
72
|
+
.\.venv\Scripts\activate.ps1 # In PowerShell
|
|
73
|
+
pip3 install -r requirements.txt
|
|
74
|
+
|
|
75
|
+
# Or using pip
|
|
76
|
+
python3 -m venv .venv
|
|
77
|
+
source .venv/bin/activate # On PowerShell use .\.venv\Scripts\activate.ps1
|
|
78
|
+
pip3 install CTkFileDialog-plus
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> [!WARNING]
|
|
83
|
+
> You should install the [Hack Nerd Fonts](https://github.com/ryanoasis/nerd-fonts/releases/download/v3.2.1/Hack.zip) if u wanna see the icons without problems :)
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## π Project structure
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
CTkFileDialog-plus/
|
|
91
|
+
βββ LICENSE # project license terms
|
|
92
|
+
βββ README.md # user and developer documentation
|
|
93
|
+
βββ requirements.txt # Python dependencies
|
|
94
|
+
βββ test.py # general package usage example
|
|
95
|
+
βββ test_save_as.py # save-as dialog regression/test example
|
|
96
|
+
βββ CTkFileDialog/ # package source code
|
|
97
|
+
β βββ __init__.py # public package API
|
|
98
|
+
β βββ _functions.py # dialog helper functions exposed to users
|
|
99
|
+
β βββ _system.py # cross-platform path handling support
|
|
100
|
+
β βββ Dialog.py # dialog imports and public component exports
|
|
101
|
+
β βββ Constants/ # reusable package constants
|
|
102
|
+
β β βββ __init__.py
|
|
103
|
+
β β βββ constants.py
|
|
104
|
+
β βββ core/ # core filesystem/search/sorting logic
|
|
105
|
+
β β βββ __init__.py
|
|
106
|
+
β β βββ filesystem.py
|
|
107
|
+
β β βββ search.py
|
|
108
|
+
β β βββ sorting.py
|
|
109
|
+
β βββ icons/ # icon assets for the dialogs
|
|
110
|
+
β β βββ _IconsMini/
|
|
111
|
+
β β βββ *.png
|
|
112
|
+
β βββ preview/ # image/video preview helpers
|
|
113
|
+
β β βββ __init__.py
|
|
114
|
+
β β βββ media.py
|
|
115
|
+
β βββ resources/ # shared resource loading utilities
|
|
116
|
+
β β βββ __init__.py
|
|
117
|
+
β β βββ icons.py
|
|
118
|
+
β βββ system/ # platform-specific system utilities
|
|
119
|
+
β β βββ __init__.py
|
|
120
|
+
β β βββ platform.py
|
|
121
|
+
β βββ ui/ # dialog UI implementations and widgets
|
|
122
|
+
β β βββ __init__.py
|
|
123
|
+
β β βββ default_dialog.py
|
|
124
|
+
β β βββ mini_dialog.py
|
|
125
|
+
β β βββ tooltip.py
|
|
126
|
+
β βββ utils/ # small helper utilities
|
|
127
|
+
β βββ __init__.py
|
|
128
|
+
β βββ helpers.py
|
|
129
|
+
βββ Images/ # README screenshots showing light and dark themes
|
|
130
|
+
β βββ MiniDialogDark.png
|
|
131
|
+
β βββ MiniDialogLight.png
|
|
132
|
+
β βββ NormalDialogDark.png
|
|
133
|
+
β βββ NormalDialogLight.png
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## π§ͺ Demo β All Methods
|
|
139
|
+
|
|
140
|
+
### ποΈ Open File
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
import customtkinter as ctk
|
|
144
|
+
from CTkFileDialog import askopenfilename
|
|
145
|
+
|
|
146
|
+
ctk.set_appearance_mode("Dark")
|
|
147
|
+
ctk.set_default_color_theme("blue")
|
|
148
|
+
|
|
149
|
+
def open_file():
|
|
150
|
+
# you can pass simple extensions...
|
|
151
|
+
# path = askopenfilename(preview_img=True, autocomplete=True)
|
|
152
|
+
# or tkinterβstyle tuples with labels and multiple globs:
|
|
153
|
+
path = askopenfilename(
|
|
154
|
+
filetypes=[
|
|
155
|
+
("Text files","*.txt"),
|
|
156
|
+
("Python","*.py *.pyw"),
|
|
157
|
+
("All","*.*"),
|
|
158
|
+
],
|
|
159
|
+
preview_img=True,
|
|
160
|
+
autocomplete=True,
|
|
161
|
+
)
|
|
162
|
+
if path:
|
|
163
|
+
result_label.configure(text=f"Selected file:\n{path}")
|
|
164
|
+
|
|
165
|
+
app = ctk.CTk()
|
|
166
|
+
app.title("askopenfilename Demo")
|
|
167
|
+
app.geometry("500x200")
|
|
168
|
+
|
|
169
|
+
ctk.CTkButton(app, text="Open File", command=open_file).pack(pady=20)
|
|
170
|
+
result_label = ctk.CTkLabel(app, text="Waiting for file selection...")
|
|
171
|
+
result_label.pack()
|
|
172
|
+
|
|
173
|
+
app.mainloop()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### ποΈ Open Multiple Files
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
import customtkinter as ctk
|
|
182
|
+
from CTkFileDialog import askopenfilenames
|
|
183
|
+
|
|
184
|
+
ctk.set_appearance_mode("Dark")
|
|
185
|
+
ctk.set_default_color_theme("blue")
|
|
186
|
+
|
|
187
|
+
def open_files():
|
|
188
|
+
paths = askopenfilenames(
|
|
189
|
+
filetypes=[("Images","*.jpg *.png"), ("All","*.*")],
|
|
190
|
+
preview_img=True,
|
|
191
|
+
autocomplete=True,
|
|
192
|
+
)
|
|
193
|
+
if paths:
|
|
194
|
+
result_label.configure(text="Selected files:\n" + "\n".join(paths))
|
|
195
|
+
|
|
196
|
+
app = ctk.CTk()
|
|
197
|
+
app.title("askopenfilenames Demo")
|
|
198
|
+
app.geometry("500x300")
|
|
199
|
+
|
|
200
|
+
ctk.CTkButton(app, text="Open Multiple Files", command=open_files).pack(pady=20)
|
|
201
|
+
result_label = ctk.CTkLabel(app, text="Waiting for file selection...", wraplength=450)
|
|
202
|
+
result_label.pack()
|
|
203
|
+
|
|
204
|
+
app.mainloop()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### π Select Directory
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
import customtkinter as ctk
|
|
213
|
+
from CTkFileDialog import askdirectory
|
|
214
|
+
|
|
215
|
+
ctk.set_appearance_mode("Dark")
|
|
216
|
+
ctk.set_default_color_theme("blue")
|
|
217
|
+
|
|
218
|
+
def select_directory():
|
|
219
|
+
folder = askdirectory(autocomplete=True)
|
|
220
|
+
if folder:
|
|
221
|
+
result_label.configure(text=f"Selected directory:\n{folder}")
|
|
222
|
+
|
|
223
|
+
app = ctk.CTk()
|
|
224
|
+
app.title("askdirectory Demo")
|
|
225
|
+
app.geometry("500x200")
|
|
226
|
+
|
|
227
|
+
ctk.CTkButton(app, text="Select Directory", command=select_directory).pack(pady=20)
|
|
228
|
+
result_label = ctk.CTkLabel(app, text="Waiting for directory selection...")
|
|
229
|
+
result_label.pack()
|
|
230
|
+
|
|
231
|
+
app.mainloop()
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### π Select Single Directory (askopendirname)
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
import customtkinter as ctk
|
|
240
|
+
from CTkFileDialog import askopendirname
|
|
241
|
+
|
|
242
|
+
ctk.set_appearance_mode("Dark")
|
|
243
|
+
ctk.set_default_color_theme("blue")
|
|
244
|
+
|
|
245
|
+
def select_directory():
|
|
246
|
+
folder = askopendirname(autocomplete=True)
|
|
247
|
+
if folder:
|
|
248
|
+
result_label.configure(text=f"Selected directory:\n{folder}")
|
|
249
|
+
|
|
250
|
+
app = ctk.CTk()
|
|
251
|
+
app.title("askopendirname Demo")
|
|
252
|
+
app.geometry("500x200")
|
|
253
|
+
|
|
254
|
+
ctk.CTkButton(app, text="Select Directory", command=select_directory).pack(pady=20)
|
|
255
|
+
result_label = ctk.CTkLabel(app, text="Waiting for directory selection...")
|
|
256
|
+
result_label.pack()
|
|
257
|
+
|
|
258
|
+
app.mainloop()
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### π Select Multiple Directories (askopendirnames)
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import customtkinter as ctk
|
|
267
|
+
from CTkFileDialog import askopendirnames
|
|
268
|
+
|
|
269
|
+
ctk.set_appearance_mode("Dark")
|
|
270
|
+
ctk.set_default_color_theme("blue")
|
|
271
|
+
|
|
272
|
+
def select_directories():
|
|
273
|
+
# Hold Ctrl or Shift while clicking to select several folders
|
|
274
|
+
folders = askopendirnames(autocomplete=True)
|
|
275
|
+
if folders:
|
|
276
|
+
result_label.configure(text="Selected directories:\n" + "\n".join(folders))
|
|
277
|
+
|
|
278
|
+
app = ctk.CTk()
|
|
279
|
+
app.title("askopendirnames Demo")
|
|
280
|
+
app.geometry("500x300")
|
|
281
|
+
|
|
282
|
+
ctk.CTkButton(app, text="Select Directories", command=select_directories).pack(pady=20)
|
|
283
|
+
result_label = ctk.CTkLabel(app, text="Waiting for directory selection...", wraplength=450)
|
|
284
|
+
result_label.pack()
|
|
285
|
+
|
|
286
|
+
app.mainloop()
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### ππ Select a File or a Folder (askopenpathname)
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
import customtkinter as ctk
|
|
295
|
+
from CTkFileDialog import askopenpathname
|
|
296
|
+
|
|
297
|
+
ctk.set_appearance_mode("Dark")
|
|
298
|
+
ctk.set_default_color_theme("blue")
|
|
299
|
+
|
|
300
|
+
def select_path():
|
|
301
|
+
path = askopenpathname(autocomplete=True)
|
|
302
|
+
if path:
|
|
303
|
+
result_label.configure(text=f"Selected:\n{path}")
|
|
304
|
+
|
|
305
|
+
app = ctk.CTk()
|
|
306
|
+
app.title("askopenpathname Demo")
|
|
307
|
+
app.geometry("500x200")
|
|
308
|
+
|
|
309
|
+
ctk.CTkButton(app, text="Select File or Folder", command=select_path).pack(pady=20)
|
|
310
|
+
result_label = ctk.CTkLabel(app, text="Waiting for selection...")
|
|
311
|
+
result_label.pack()
|
|
312
|
+
|
|
313
|
+
app.mainloop()
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### ππ Select Multiple Files and/or Folders (askopenpathnames)
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
import customtkinter as ctk
|
|
322
|
+
from CTkFileDialog import askopenpathnames
|
|
323
|
+
|
|
324
|
+
ctk.set_appearance_mode("Dark")
|
|
325
|
+
ctk.set_default_color_theme("blue")
|
|
326
|
+
|
|
327
|
+
def select_paths():
|
|
328
|
+
# Hold Ctrl or Shift while clicking to mix files and folders in one selection
|
|
329
|
+
items = askopenpathnames(autocomplete=True)
|
|
330
|
+
if items:
|
|
331
|
+
result_label.configure(text="Selected:\n" + "\n".join(items))
|
|
332
|
+
|
|
333
|
+
app = ctk.CTk()
|
|
334
|
+
app.title("askopenpathnames Demo")
|
|
335
|
+
app.geometry("500x300")
|
|
336
|
+
|
|
337
|
+
ctk.CTkButton(app, text="Select Files/Folders", command=select_paths).pack(pady=20)
|
|
338
|
+
result_label = ctk.CTkLabel(app, text="Waiting for selection...", wraplength=450)
|
|
339
|
+
result_label.pack()
|
|
340
|
+
|
|
341
|
+
app.mainloop()
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
import customtkinter as ctk
|
|
346
|
+
from CTkFileDialog import asksaveasfilename
|
|
347
|
+
|
|
348
|
+
ctk.set_appearance_mode("Dark")
|
|
349
|
+
ctk.set_default_color_theme("blue")
|
|
350
|
+
|
|
351
|
+
def save_as_filename():
|
|
352
|
+
path = asksaveasfilename(autocomplete=True)
|
|
353
|
+
if path:
|
|
354
|
+
result_label.configure(text=f"Save file as:\n{path}")
|
|
355
|
+
|
|
356
|
+
# You can also auto-append an extension if the user doesn't type one:
|
|
357
|
+
# path = asksaveasfilename(autocomplete=True, defaultext=".txt")
|
|
358
|
+
|
|
359
|
+
app = ctk.CTk()
|
|
360
|
+
app.title("asksaveasfilename Demo")
|
|
361
|
+
app.geometry("500x200")
|
|
362
|
+
|
|
363
|
+
ctk.CTkButton(app, text="Save As (Filename Only)", command=save_as_filename).pack(pady=20)
|
|
364
|
+
result_label = ctk.CTkLabel(app, text="Waiting for filename...")
|
|
365
|
+
result_label.pack()
|
|
366
|
+
|
|
367
|
+
app.mainloop()
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
### πΎ Save As (write to file)
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
import customtkinter as ctk
|
|
376
|
+
from CTkFileDialog import asksaveasfile
|
|
377
|
+
|
|
378
|
+
ctk.set_appearance_mode("Dark")
|
|
379
|
+
ctk.set_default_color_theme("blue")
|
|
380
|
+
|
|
381
|
+
def save_as_file():
|
|
382
|
+
file = asksaveasfile(autocomplete=True)
|
|
383
|
+
if file:
|
|
384
|
+
file.write("This file was created using the demo.")
|
|
385
|
+
file.close()
|
|
386
|
+
result_label.configure(text=f"File saved:\n{file.name}")
|
|
387
|
+
|
|
388
|
+
# Alternatively, asksaveasfile supports the context manager protocol:
|
|
389
|
+
# with asksaveasfile(autocomplete=True) as file:
|
|
390
|
+
# if file:
|
|
391
|
+
# file.write("This file was created using the demo.")
|
|
392
|
+
|
|
393
|
+
app = ctk.CTk()
|
|
394
|
+
app.title("asksaveasfile Demo")
|
|
395
|
+
app.geometry("500x200")
|
|
396
|
+
|
|
397
|
+
ctk.CTkButton(app, text="Save As (Real File)", command=save_as_file).pack(pady=20)
|
|
398
|
+
result_label = ctk.CTkLabel(app, text="Waiting for save location...")
|
|
399
|
+
result_label.pack()
|
|
400
|
+
|
|
401
|
+
app.mainloop()
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
### π Open File as Object
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
import customtkinter as ctk
|
|
410
|
+
from CTkFileDialog import askopenfile
|
|
411
|
+
|
|
412
|
+
ctk.set_appearance_mode("Dark")
|
|
413
|
+
ctk.set_default_color_theme("blue")
|
|
414
|
+
|
|
415
|
+
def open_file_obj():
|
|
416
|
+
f = askopenfile(mode='rb',
|
|
417
|
+
filetypes=[("Binary","*.bin"), ("All","*.*")])
|
|
418
|
+
if f:
|
|
419
|
+
data = f.read()
|
|
420
|
+
f.close()
|
|
421
|
+
result_label.configure(text=f"Read {len(data)} bytes from {f.name}")
|
|
422
|
+
|
|
423
|
+
app = ctk.CTk()
|
|
424
|
+
app.title("askopenfile Demo")
|
|
425
|
+
app.geometry("500x200")
|
|
426
|
+
|
|
427
|
+
ctk.CTkButton(app, text="Open File Object", command=open_file_obj).pack(pady=20)
|
|
428
|
+
result_label = ctk.CTkLabel(app, text="Waiting for file selection...")
|
|
429
|
+
result_label.pack()
|
|
430
|
+
|
|
431
|
+
app.mainloop()
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
### π Open Multiple Files as Objects
|
|
437
|
+
|
|
438
|
+
```python
|
|
439
|
+
import customtkinter as ctk
|
|
440
|
+
from CTkFileDialog import askopenfiles
|
|
441
|
+
|
|
442
|
+
ctk.set_appearance_mode("Dark")
|
|
443
|
+
ctk.set_default_color_theme("blue")
|
|
444
|
+
|
|
445
|
+
def open_files_obj():
|
|
446
|
+
files = askopenfiles(mode='r', filetypes=[("Text","*.txt")])
|
|
447
|
+
if files:
|
|
448
|
+
for f in files:
|
|
449
|
+
content = f.read()
|
|
450
|
+
f.close()
|
|
451
|
+
print(f"{f.name}: {len(content)} chars")
|
|
452
|
+
result_label.configure(text=f"Opened {len(files)} files, see console output.")
|
|
453
|
+
|
|
454
|
+
app = ctk.CTk()
|
|
455
|
+
app.title("askopenfiles Demo")
|
|
456
|
+
app.geometry("500x200")
|
|
457
|
+
|
|
458
|
+
ctk.CTkButton(app, text="Open Files Objects", command=open_files_obj).pack(pady=20)
|
|
459
|
+
result_label = ctk.CTkLabel(app, text="Waiting for file selection...")
|
|
460
|
+
result_label.pack()
|
|
461
|
+
|
|
462
|
+
app.mainloop()
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## π§© Parameters
|
|
468
|
+
|
|
469
|
+
<div align="center">
|
|
470
|
+
|
|
471
|
+
| Parameter | Description |
|
|
472
|
+
|----------------|-----------------------------------------------------------------------------|
|
|
473
|
+
| `filetypes` | Optional filter list: either `['.txt', '.md']` or `[('Text','*.txt'),('Py','*.py *.pyw'),('All','*.*')]`. Wildcards are normalized internally. |
|
|
474
|
+
| `hidden` | Show hidden files or directories (`False` by default). |
|
|
475
|
+
| `preview_img` | Enable image preview in the file dialog. |
|
|
476
|
+
| `video_preview` | Show first frame of video files as thumbnail (experimental). |
|
|
477
|
+
| `autocomplete` | Enable path autocompletion with `Tab`, `Up`, and `Down`. |
|
|
478
|
+
| `initial_dir` | Set the initial directory when opening the dialog. |
|
|
479
|
+
| `tool_tip` | Enable the tool tip. |
|
|
480
|
+
| `foldercreation`| Enable a "New Folder" button so the user can create folders from within the dialog (`True` by default). |
|
|
481
|
+
| `defaultext` | *(`asksaveasfilename`/`asksaveasfile` only)* Extension appended to the filename if the user didn't type one (default is none). |
|
|
482
|
+
| `style` | Defines the dialog style, by default it will be 'Default' but you can choose a small one ('Mini'). |
|
|
483
|
+
| `geometry` | Defines the dialog size. For functions that support both styles, pass a tuple `(default_geometry, mini_geometry)`. |
|
|
484
|
+
| `title` | Define the title for the dialog window. Defaults to `CTkFileDialog`. |
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
</div>
|
|
488
|
+
|
|
489
|
+
## π― Using New Features
|
|
490
|
+
|
|
491
|
+
### π Search/Filter Files
|
|
492
|
+
Both Default and Mini dialogs include a search bar. Simply type in the search field to filter files and directories in real-time:
|
|
493
|
+
```python
|
|
494
|
+
file = askopenfilename(style='Default')
|
|
495
|
+
# Use the search bar in the dialog to filter results
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### π View Modes (Default Dialog Only)
|
|
499
|
+
The Default dialog supports two view modes:
|
|
500
|
+
- **Grid View**: Icon-based grid layout (default)
|
|
501
|
+
- **List View**: Detailed list with file info (size, date modified, type)
|
|
502
|
+
|
|
503
|
+
Toggle between modes using the view buttons in the toolbar.
|
|
504
|
+
|
|
505
|
+
### π Sorting Options (Default Dialog Only)
|
|
506
|
+
Sort files by:
|
|
507
|
+
- Name (alphabetical)
|
|
508
|
+
- Date (creation/modification time)
|
|
509
|
+
- Type (file extension)
|
|
510
|
+
- Size (file size)
|
|
511
|
+
- Last Modified (most recent first)
|
|
512
|
+
|
|
513
|
+
Select a sort option from the sort menu in the toolbar.
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
This module has constants that can be used outside or inside the dialog, they are used to obtain paths like /home/user or /home/user/.config/
|
|
518
|
+
Here is a basic example
|
|
519
|
+
|
|
520
|
+
```python3
|
|
521
|
+
#!/usr/bin/env python3
|
|
522
|
+
import customtkinter as ctk
|
|
523
|
+
from CTkFileDialog import askopenfilename
|
|
524
|
+
from CTkFileDialog.Constants import HOME
|
|
525
|
+
|
|
526
|
+
root = ctk.CTk()
|
|
527
|
+
|
|
528
|
+
def open_file():
|
|
529
|
+
f = askopenfilename(initial_dir=HOME, autocomplete=True)
|
|
530
|
+
if f:
|
|
531
|
+
print(f"file selected: {f}")
|
|
532
|
+
|
|
533
|
+
ctk.CTkButton(master=root, command=open_file, text="Open File").pack(padx=10, pady=10, anchor=ctk.CENTER)
|
|
534
|
+
|
|
535
|
+
root.mainloop()
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
## And here are the constants available from the package
|
|
539
|
+
|
|
540
|
+
<div align="center">
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
| Parameter | Description |
|
|
544
|
+
|----------------|-----------------------------------------------------------------------------|
|
|
545
|
+
| `PWD` | Current working directory (e.g., where the program was launched) |
|
|
546
|
+
| `HOME` | User's home directory (e.g., /home/user or C:\Users\user) |
|
|
547
|
+
| `TEMP` | Temporary directory (fallback to /tmp if no env vars are set) |
|
|
548
|
+
| `CONFIG_DIR` | XDG-compliant user configuration directory (default: ~/.config) |
|
|
549
|
+
| `CACHE_DIR` | XDG-compliant user cache directory (default: ~/.cache) |
|
|
550
|
+
| `PATH` | System PATH split into a list of directories |
|
|
551
|
+
| `DATA_DIR` | XDG-compliant user data directory (default: ~/.local/share) |
|
|
552
|
+
| `VENV` | Active Python virtual environment (venv or conda), fallback to PWD |
|
|
553
|
+
| `DOWNLOAD_DIR` | Default download directory (e.g., ~/Downloads or C:\Users\user\Download). |
|
|
554
|
+
| `DOWNLOAD_DIR_VIDEO` | Default video download directory (e.g., ~/Downloads/Video or C:\Users\user\Download\Video).|
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
</div>
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## π Dark Mode Normal
|
|
562
|
+
|
|
563
|
+
<p align="center">
|
|
564
|
+
<img src="https://raw.githubusercontent.com/hmidani-abdelilah/CTkFileDialog-plus/refs/heads/main/Images/NormalDialogDark.png" width="80%">
|
|
565
|
+
</p>
|
|
566
|
+
|
|
567
|
+
## βοΈ Light Mode Preview
|
|
568
|
+
|
|
569
|
+
<p align="center">
|
|
570
|
+
<img src="https://raw.githubusercontent.com/hmidani-abdelilah/CTkFileDialog-plus/refs/heads/main/Images/NormalDialogLight.png" width="80%">
|
|
571
|
+
</p>
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
## π Dark Mode Mini
|
|
577
|
+
|
|
578
|
+
<p align="center">
|
|
579
|
+
<img src="https://raw.githubusercontent.com/hmidani-abdelilah/CTkFileDialog-plus/refs/heads/main/Images/MiniDialogDark.png" width="80%">
|
|
580
|
+
</p>
|
|
581
|
+
|
|
582
|
+
## βοΈ Light Mode Mini
|
|
583
|
+
|
|
584
|
+
<p align="center">
|
|
585
|
+
<img src="https://raw.githubusercontent.com/hmidani-abdelilah/CTkFileDialog-plus/refs/heads/main/Images/MiniDialogLight.png" width="80%">
|
|
586
|
+
</p>
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
The mini design wasn't made by me; it was made by this [user](https://github.com/limafresh). Additionally, I did not design the normal interface; it was developed by this [user](https://github.com/yoodreamer/CTkFileDialog), and they deserve all the credit. I would like to express my gratitude to them for developing that design beforehand.I revamped the interface, established a new framework, and incorporated additional features.
|
|
591
|
+
|
|
592
|
+
---
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
CTkFileDialog/Dialog.py,sha256=Dg3ArOxZwDKPcbD1Q7ijfjXORHNCjaThvQOcC8r27II,665
|
|
2
|
+
CTkFileDialog/__init__.py,sha256=CBUhyErpTSIpnV_AJWnTa9H3vjAgJlSaNC29U01PTJI,926
|
|
3
|
+
CTkFileDialog/_functions.py,sha256=UQv62NLdTjBQH9fzUqWntR2iSnJQ7qaDpG3NiZaFJoU,17597
|
|
4
|
+
CTkFileDialog/_system.py,sha256=ARJTvtdqI7022jictZozim6ZkD8eAwmR6U5UYqqGWvA,162
|
|
5
|
+
CTkFileDialog/Constants/__init__.py,sha256=8rgZGeWf_JCWLfFWp8xB-YJMWE3PWNFI6_DBZeIUc1E,1673
|
|
6
|
+
CTkFileDialog/Constants/constants.py,sha256=U8FCd9TFSaLYyAjfHlKg79GsJN9ZGxH9Z33cQP3tWe0,1680
|
|
7
|
+
CTkFileDialog/core/__init__.py,sha256=Hq2N-_2CmeLM_-p6FsHyI1ofIenVXTK4sfViCY3ne9o,361
|
|
8
|
+
CTkFileDialog/core/filesystem.py,sha256=rCAufoC7W1zoNN82GE5mcNo5v_rEHuIIu5vpbnji-Aw,3093
|
|
9
|
+
CTkFileDialog/core/search.py,sha256=V51zf6kpghrUGdO09Q06XbQfQFK6NhGNZ5KTgDgH1AY,365
|
|
10
|
+
CTkFileDialog/core/sorting.py,sha256=1AaG3RfIP8MGPkDTAaRivrTp9Smk9s8qR3AuBZ3wr-E,1210
|
|
11
|
+
CTkFileDialog/preview/__init__.py,sha256=dsw2QyO01IHdMpWICvWsrm2O_m_3ZNRYDDulPXZ2aiw,222
|
|
12
|
+
CTkFileDialog/preview/media.py,sha256=o7j6TGTChAX4SM8UMxG-MjW8g3ZApHzegiIKtjjVvzg,2955
|
|
13
|
+
CTkFileDialog/resources/__init__.py,sha256=wN99hJeXu6SIn2wwPLR2U05Slqbku9aWUYcsAyg2Yrw,258
|
|
14
|
+
CTkFileDialog/resources/icons.py,sha256=QdEf9X_ymJD3-JlIg4GQr-TMzpbY9E8nvOzUWkixl-Q,2454
|
|
15
|
+
CTkFileDialog/system/__init__.py,sha256=g5a0tNbBNLSyn7oiAZxq15b1CRxWTVvlH1uF_HzlNzU,110
|
|
16
|
+
CTkFileDialog/system/platform.py,sha256=PZgz_IERcgZwi9Q9Wq-FzyrRAzEN2OFWnGKo98PiPV8,2143
|
|
17
|
+
CTkFileDialog/ui/__init__.py,sha256=cBIQwkhviy7EbySbpmbLwIREtooswo52CyESugQPtNg,201
|
|
18
|
+
CTkFileDialog/ui/default_dialog.py,sha256=Mz6sHpVdeKcQ01HBhskDWnTSpHlKqIWrda78bhXpayk,35890
|
|
19
|
+
CTkFileDialog/ui/mini_dialog.py,sha256=WIa1Nx-ZeDWejK2coMG9TNVpmdmrSGAIsENZz9p8wW4,16041
|
|
20
|
+
CTkFileDialog/ui/tooltip.py,sha256=jYJdexJ8BuHjReXdlIQrF3aDeuOpU6JlzIENTSq7MYI,657
|
|
21
|
+
CTkFileDialog/utils/__init__.py,sha256=Rqmpg3kxA1Kd6yGZstg-HxUHxFwRfH_TDZnqBHExQc8,206
|
|
22
|
+
CTkFileDialog/utils/helpers.py,sha256=0fULuzBsMVBRGko2rAYz8xP1iph_KB57SY9Xi-sxBiE,1939
|
|
23
|
+
ctkfiledialog_plus-2.1.1.dist-info/licenses/LICENSE,sha256=-yP77ZlJiG2GIaFVx8f6KkUncC84D8RcW0lZEalE7og,1074
|
|
24
|
+
ctkfiledialog_plus-2.1.1.dist-info/METADATA,sha256=Ap8Ad-oLQYQw3wP9eQ2kfAQc-UgUEfWrVzrKJDvWcEM,18961
|
|
25
|
+
ctkfiledialog_plus-2.1.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
26
|
+
ctkfiledialog_plus-2.1.1.dist-info/top_level.txt,sha256=ghUwgLRHcaJhcemQYVMRWwbJ8_sWqVyl4S8icnMBI1s,14
|
|
27
|
+
ctkfiledialog_plus-2.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hmidani abdelilah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CTkFileDialog
|