1
1
import argparse
2
+ import json
2
3
import sys
3
4
from pathlib import Path
4
- from typing import Sequence , Union
5
+ from typing import Sequence , Union , Optional
5
6
6
7
import rawpy
7
- from PySide6 .QtCore import QFile , QIODevice , QDir , QFileInfo , QModelIndex
8
+ from PySide6 .QtCore import QFile , QIODevice , QDir , QFileInfo , QModelIndex , Qt , QStringListModel
8
9
from PySide6 .QtGui import QPixmap , QIcon
9
10
from PySide6 .QtUiTools import QUiLoader
10
11
from PySide6 .QtWidgets import (
11
- QApplication , QGraphicsScene , QFileDialog , QFileSystemModel , QListView , QFileIconProvider
12
+ QApplication , QGraphicsScene , QFileDialog , QFileSystemModel , QListView , QFileIconProvider , QCompleter
12
13
)
13
14
14
15
@@ -22,15 +23,45 @@ def get_parsed_args():
22
23
return args
23
24
24
25
25
- def list_dir_images (path : Path ) -> Sequence [Path ]:
26
+ def list_dir (path : Path , mask : str ) -> Sequence [Path ]:
26
27
if path .is_dir ():
27
- files = sorted (path .glob ('*.ARW' ))
28
+ files = sorted (path .glob (mask ))
28
29
else :
29
30
raise FileNotFoundError ('Path must be directory' )
30
31
31
32
return files
32
33
33
34
35
+ def list_dir_images (path : Path ) -> Sequence [Path ]:
36
+ return list_dir (path , '*.ARW' )
37
+
38
+
39
+ def list_dir_metadata (path : Path ) -> Optional [Sequence [Path ]]:
40
+ metadata_dir_path = Path (path , '.metadata' )
41
+
42
+ if metadata_dir_path .exists ():
43
+ return list_dir (metadata_dir_path , '*.json' )
44
+
45
+ return None
46
+
47
+
48
+ def load_metadata (data_root_path : Path ):
49
+ metadata_files = list_dir_metadata (data_root_path )
50
+
51
+ if not metadata_files :
52
+ return
53
+
54
+ metadata = {}
55
+
56
+ for metadata_file in metadata_files :
57
+ try :
58
+ with open (metadata_file , 'r' ) as f :
59
+ metadata [metadata_file .name .lower ()] = json .load (f )
60
+ except FileNotFoundError :
61
+ pass
62
+
63
+ return metadata
64
+
34
65
def get_raw_thumbnail (path : Union [str , Path ]):
35
66
with rawpy .imread (str (path )) as raw :
36
67
try :
@@ -74,7 +105,14 @@ def icon(self, file_info: QFileInfo) -> QIcon:
74
105
75
106
class MainWindow :
76
107
def __init__ (self , data_root_path : Path ):
77
- self .data_root_path = data_root_path
108
+ self .data_root_path = None
109
+ self .metadata = {}
110
+ self .types = set ()
111
+ self .makes = set ()
112
+ self .models = set ()
113
+ self .bodies = set ()
114
+ self .colors = set ()
115
+
78
116
ui_file_name = 'main_window.ui'
79
117
ui_file = QFile (Path (__file__ ).resolve ().parent / ui_file_name )
80
118
@@ -86,12 +124,32 @@ def __init__(self, data_root_path: Path):
86
124
self .window = loader .load (ui_file )
87
125
ui_file .close ()
88
126
89
- self .set_data_root_path (str (data_root_path ))
127
+ self .type_completer = QCompleter ()
128
+ self .type_completer .setCompletionMode (QCompleter .CompletionMode .PopupCompletion )
129
+ self .type_completer .setCaseSensitivity (Qt .CaseSensitivity .CaseInsensitive )
130
+ self .type_completer .setWidget (self .window .type_combo_box )
131
+ self .make_completer = QCompleter ()
132
+ self .make_completer .setCompletionMode (QCompleter .CompletionMode .PopupCompletion )
133
+ self .make_completer .setCaseSensitivity (Qt .CaseSensitivity .CaseInsensitive )
134
+ self .make_completer .setWidget (self .window .make_combo_box )
135
+ self .model_completer = QCompleter ()
136
+ self .model_completer .setCompletionMode (QCompleter .CompletionMode .PopupCompletion )
137
+ self .model_completer .setCaseSensitivity (Qt .CaseSensitivity .CaseInsensitive )
138
+ self .model_completer .setWidget (self .window .model_combo_box )
139
+ self .body_completer = QCompleter ()
140
+ self .body_completer .setCompletionMode (QCompleter .CompletionMode .PopupCompletion )
141
+ self .body_completer .setCaseSensitivity (Qt .CaseSensitivity .CaseInsensitive )
142
+ self .body_completer .setWidget (self .window .body_combo_box )
143
+ self .color_completer = QCompleter ()
144
+ self .color_completer .setCompletionMode (QCompleter .CompletionMode .PopupCompletion )
145
+ self .color_completer .setCaseSensitivity (Qt .CaseSensitivity .CaseInsensitive )
146
+ self .color_completer .setWidget (self .window .color_combo_box )
147
+
90
148
self .window .path_browser_button .clicked .connect (self .browse_directory )
91
- self .window .path_edit .textChanged .connect (self .load_images )
149
+ self .window .path_edit .textChanged .connect (self .on_data_root_path_changed )
92
150
93
- if self . data_root_path :
94
- self .load_images ( )
151
+ if data_root_path :
152
+ self .window . path_edit . setText ( str ( data_root_path ) )
95
153
96
154
if not self .window :
97
155
print (loader .errorString ())
@@ -103,7 +161,7 @@ def __init__(self, data_root_path: Path):
103
161
def browse_directory (self ):
104
162
path = QFileDialog .getExistingDirectory (self .window , 'Select dataset directory' , str (self .data_root_path ),
105
163
options = QFileDialog .Option .ShowDirsOnly )
106
- self .set_data_root_path (path )
164
+ self .window . path_edit . setText (path )
107
165
108
166
def on_file_selected (self , index : QModelIndex ):
109
167
file_name = index .data ()
@@ -118,17 +176,65 @@ def on_file_selected(self, index: QModelIndex):
118
176
self .window .photo_view .setScene (scene )
119
177
120
178
self .window .type_combo_box .setEnabled (True )
179
+ self .window .type_combo_box .setCompleter (self .type_completer )
121
180
self .window .make_combo_box .setEnabled (True )
181
+ self .window .make_combo_box .setCompleter (self .make_completer )
122
182
self .window .model_combo_box .setEnabled (True )
183
+ self .window .model_combo_box .setCompleter (self .model_completer )
123
184
self .window .body_combo_box .setEnabled (True )
185
+ self .window .body_combo_box .setCompleter (self .body_completer )
124
186
self .window .color_combo_box .setEnabled (True )
187
+ self .window .color_combo_box .setCompleter (self .color_completer )
125
188
126
- def set_data_root_path (self , path : str ):
127
- self .window .path_edit .setText (path )
128
- self .data_root_path = Path (path )
129
189
130
- def load_images (self ):
131
- data_root_path = Path (self .window .path_edit .text ())
190
+ def on_data_root_path_changed (self ):
191
+ self .data_root_path = Path (self .window .path_edit .text ())
192
+ self .load_images (self .data_root_path )
193
+ self .metadata = load_metadata (self .data_root_path )
194
+
195
+ self .types = set ()
196
+ self .makes = set ()
197
+ self .models = set ()
198
+ self .bodies = set ()
199
+ self .colors = set ()
200
+
201
+ for item in self .metadata .values ():
202
+ if _type := item .get ('type' ):
203
+ self .types .add (_type )
204
+
205
+ if make := item .get ('make' ):
206
+ self .makes .add (make )
207
+
208
+ if model := item .get ('model' ):
209
+ self .models .add (model )
210
+
211
+ if body := item .get ('body' ):
212
+ self .bodies .add (body )
213
+
214
+ if color := item .get ('color' ):
215
+ self .colors .add (color )
216
+
217
+ self .window .type_combo_box .clear ()
218
+ self .window .type_combo_box .addItems (sorted (self .types ))
219
+ self .type_completer .setModel (QStringListModel (sorted (self .types )))
220
+
221
+ self .window .make_combo_box .clear ()
222
+ self .window .make_combo_box .addItems (sorted (self .makes ))
223
+ self .make_completer .setModel (QStringListModel (sorted (self .makes )))
224
+
225
+ self .window .model_combo_box .clear ()
226
+ self .window .model_combo_box .addItems (sorted (self .models ))
227
+ self .model_completer .setModel (QStringListModel (sorted (self .models )))
228
+
229
+ self .window .body_combo_box .clear ()
230
+ self .window .body_combo_box .addItems (sorted (self .bodies ))
231
+ self .body_completer .setModel (QStringListModel (sorted (self .bodies )))
232
+
233
+ self .window .color_combo_box .clear ()
234
+ self .window .color_combo_box .addItems (sorted (self .colors ))
235
+ self .color_completer .setModel (QStringListModel (sorted (self .colors )))
236
+
237
+ def load_images (self , data_root_path : Path ):
132
238
image_file_paths = list_dir_images (data_root_path )
133
239
134
240
if image_file_paths :
0 commit comments