forked from rushi-the-neural-arch/HandyView
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandyviewer.py
364 lines (312 loc) · 14.2 KB
/
handyviewer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
import os
import sys
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (QApplication, QDockWidget, QFileDialog, QGridLayout, QInputDialog, QLabel, QLineEdit,
QMainWindow, QToolBar, QWidget)
import actions as actions
from canvas import Canvas
from db import HVDB
from utils import ROOT_DIR
from widgets import HLine, MessageDialog, show_msg
class MainWindow(QMainWindow):
"""The main window."""
def __init__(self):
super(MainWindow, self).__init__()
# get initial path
try:
init_path = sys.argv[1]
except IndexError:
# show the icon image
init_path = os.path.join(ROOT_DIR, 'icon.png')
# initialize HVDB (handyview database), which stores the path info
self.hvdb = HVDB(init_path)
self.full_screen = False
self.canvas_type = 'main'
# initialize UI
self.setWindowTitle('HandyView')
self.init_menubar()
self.init_toolbar()
self.init_statusbar()
self.init_central_window()
self.add_dock_window()
def init_menubar(self):
# create menubar
menubar = self.menuBar()
# File
file_menu = menubar.addMenu('&File')
file_menu.addAction(actions.open(self))
file_menu.addAction(actions.history(self))
file_menu.addSeparator()
file_menu.addAction(actions.refresh(self))
file_menu.addAction(actions.goto_index(self))
file_menu.addSeparator()
file_menu.addAction(actions.include_file_name(self))
file_menu.addAction(actions.exclude_file_name(self))
# Edit
edit_menu = menubar.addMenu('&Edit') # noqa: F841
# Draw
draw_menu = menubar.addMenu('&Draw') # noqa: F841
# Compare
compare_menu = menubar.addMenu('&Compare')
compare_menu.addAction(actions.compare(self))
compare_menu.addAction(actions.clear_compare(self))
compare_menu.addAction(actions.set_fingerprint(self))
# Layouts
layout_menu = menubar.addMenu('&Layout')
layout_menu.addAction(actions.switch_main_canvas(self))
layout_menu.addAction(actions.switch_compare_canvas(self))
layout_menu.addAction(actions.switch_preview_canvas(self))
# Help
help_menu = menubar.addMenu('&Help')
help_menu.addAction(actions.show_instruction_msg(self))
def init_toolbar(self):
self.toolbar = QToolBar('ToolBar', self)
self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
# open and history
self.toolbar.addAction(actions.open(self))
self.toolbar.addAction(actions.history(self))
self.toolbar.addSeparator()
# refresh and index
self.toolbar.addAction(actions.refresh(self))
self.toolbar.addAction(actions.goto_index(self))
self.toolbar.addSeparator()
# include and exclude names
self.toolbar.addAction(actions.include_file_name(self))
self.toolbar.addAction(actions.exclude_file_name(self))
self.toolbar.addSeparator()
# compare and clear compare
self.toolbar.addAction(actions.compare(self))
self.toolbar.addAction(actions.clear_compare(self))
# canvas layout
self.toolbar.addSeparator()
self.toolbar.addSeparator()
self.toolbar.addAction(actions.switch_main_canvas(self))
self.toolbar.addAction(actions.switch_compare_canvas(self))
self.toolbar.addAction(actions.switch_preview_canvas(self))
# others
self.toolbar.addSeparator()
self.toolbar.addAction(actions.set_fingerprint(self))
# help
self.toolbar.addSeparator()
self.toolbar.addSeparator()
self.toolbar.addAction(actions.show_instruction_msg(self))
self.toolbar.setIconSize(QtCore.QSize(45, 45))
self.addToolBar(QtCore.Qt.LeftToolBarArea, self.toolbar)
def init_statusbar(self):
self.statusBar().showMessage('Welcome to HandyView.')
def set_statusbar(self, text):
self.statusBar().showMessage(text)
def init_central_window(self):
self.canvas = Canvas(self, self.hvdb)
self.setCentralWidget(self.canvas)
def switch_fullscreen(self):
if self.full_screen is False:
self.showFullScreen()
self.full_screen = True
else:
self.showMaximized()
self.full_screen = False
def add_dock_window(self):
# Info
self.dock_info = QDockWidget('Information Panel', self)
self.dock_info.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
self.dock_info.setFeatures(QDockWidget.DockWidgetMovable
| QDockWidget.DockWidgetFloatable
| QDockWidget.DockWidgetClosable)
dockedWidget = QWidget()
self.dock_info.setWidget(dockedWidget)
layout = QGridLayout()
layout.addWidget(self.canvas.zoom_label, 0, 0, 1, 3)
layout.addWidget(self.canvas.mouse_pos_label, 1, 0, 1, 3)
color_grid = QGridLayout()
color_grid.addWidget(self.canvas.mouse_color_title, 0, 0, 1, 1)
color_grid.addWidget(self.canvas.mouse_color_label, 0, 1, 1, 3)
color_grid.addWidget(self.canvas.mouse_rgb_label, 1, 0, 1, 3)
layout.addLayout(color_grid, 2, 0, 1, 3)
layout.addWidget(HLine(), 3, 0, 1, 3)
layout.addWidget(self.canvas.selection_pos_label, 4, 0, 1, 3)
layout.addWidget(HLine(), 5, 0, 1, 3)
layout.addWidget(self.canvas.include_names_label, 6, 0, 1, 3)
layout.addWidget(self.canvas.exclude_names_label, 7, 0, 1, 3)
layout.addWidget(HLine(), 8, 0, 1, 3)
layout.addWidget(self.canvas.comparison_label, 9, 0, 1, 3)
# update comparison info (for a second open)
_, img_len_list = self.hvdb.update_path_list()
show_str = 'Comparison:\n # for each folder:\n\t' + '\n\t'.join(map(str, img_len_list))
if len(img_len_list) > 1:
self.canvas.comparison_label.setText(show_str)
# for compact space
blank_qlabel = QLabel()
layout.addWidget(blank_qlabel, 10, 0, 20, 3)
dockedWidget.setLayout(layout)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock_info)
# ---------------------------------------
# slots: open and history
# ---------------------------------------
def open_file_dialog(self):
try:
with open(os.path.join(ROOT_DIR, 'history.txt'), 'r') as f:
history = f.readlines()[0]
history = history.strip()
except Exception:
history = '.'
key, ok = QFileDialog.getOpenFileName(self, 'Select an image', history)
if ok:
self.hvdb.init_path = key
self.hvdb.get_init_path_list()
self.canvas.show_image(init=True)
def open_history(self):
with open(os.path.join(ROOT_DIR, 'history.txt'), 'r') as f:
lines = f.readlines()
lines = [line.strip() for line in lines]
key, ok = QInputDialog().getItem(self, 'Open File History', 'History:', lines, 0, True)
if ok:
self.hvdb.init_path = key
self.hvdb.get_init_path_list()
self.canvas.show_image(init=True)
# ---------------------------------------
# slots: refresh and index
# ---------------------------------------
def refresh_img_list(self):
# should be used in Main Cavans
if self.canvas_type != 'main':
self.switch_main_canvas()
self.canvas.update_path_list()
self.canvas.show_image(init=False)
def goto_index(self):
index, ok = QInputDialog.getText(self, 'Go to index', 'Index:', QLineEdit.Normal, '1')
if ok:
if index == '':
index = 0
elif index.isdigit():
index = int(index) - 1
else:
return
self.canvas.goto_index(index)
# ---------------------------------------
# slots: include and exclude names
# ---------------------------------------
def include_file_name(self):
# show current include names as the default values
current_include_names = self.hvdb.include_names
if current_include_names is None:
current_include_names = ''
else:
current_include_names = ', '.join(current_include_names)
include_names, ok = QInputDialog.getText(self, 'Include file name', 'Key word (seprate by ,):',
QLineEdit.Normal, current_include_names)
if ok:
if include_names != '':
self.hvdb.include_names = [v.strip() for v in include_names.split(',')]
self.hvdb.exclude_names = None
else:
self.hvdb.include_names = None
self.refresh_img_list()
def exclude_file_name(self):
# show current exclude names as the default values
current_exclude_names = self.hvdb.exclude_names
if current_exclude_names is None:
current_exclude_names = ''
else:
current_exclude_names = ', '.join(current_exclude_names)
exclude_names, ok = QInputDialog.getText(self, 'Exclude file name', 'Key word (seprate by ,):',
QLineEdit.Normal, current_exclude_names)
if ok:
if exclude_names != '':
self.hvdb.exclude_names = [v.strip() for v in exclude_names.split(',')]
self.hvdb.include_names = None
else:
self.hvdb.exclude_names = None
self.refresh_img_list()
# ---------------------------------------
# slots: compare and clear compare
# ---------------------------------------
def compare_folder(self):
# Compare folder should be set in Main Cavans
if self.canvas_type != 'main':
self.switch_main_canvas()
key, ok = QFileDialog.getOpenFileName(self, 'Select an image', os.path.join(self.hvdb.get_folder(), '../'))
if ok:
self.canvas.add_cmp_folder(key)
def clear_compare(self):
# Compare folder should be set in Main Cavans
if self.canvas_type != 'main':
self.switch_main_canvas()
self.hvdb.folder_list = [self.hvdb.folder_list[0]]
self.hvdb.path_list = [self.hvdb.path_list[0]]
self.hvdb.fidx = 0
# ---------------------------------------
# slots: canvas layouts
# ---------------------------------------
def switch_main_canvas(self):
if self.canvas_type != 'main':
self.hvdb.interval = 0
self.canvas = Canvas(self, self.hvdb)
self.setCentralWidget(self.canvas)
self.add_dock_window()
self.canvas_type = 'main'
def switch_compare_canvas(self):
if self.canvas_type != 'compare':
num_compare = self.hvdb.get_folder_len()
if num_compare == 1:
num_view, ok = QInputDialog.getText(self, 'Compare Canvas', '# Compare Columns: (options: 2, 3, 4)',
QLineEdit.Normal, '2')
if ok:
try:
num_view = int(num_view)
except Exception:
show_msg(icon='Warning', title='Warning', text='# Compare Columns should be int.')
if num_view > 4 or num_view < 2:
show_msg(icon='Warning', title='Warning', text='# Compare Columns should be 2, 3, 4.')
self.hvdb.interval = num_view - 1
else: # default value
self.hvdb.interval = 1
num_view = 2
else:
if not self.hvdb.is_same_len:
show_msg('Critical', 'Error', ('Compare folders have different length, \n'
'Cannot enter compare canvas.'))
return
self.hvdb.fidx = 0
num_view = min(self.hvdb.get_folder_len(), 4)
show_msg('Information', 'Compare Canvas', f'Comparsion folder mode.\n # Compare Columns: {num_view}.')
self.dock_info.close()
self.canvas = Canvas(self, self.hvdb, num_view=num_view)
self.setCentralWidget(self.canvas)
self.canvas_type = 'compare'
def switch_preview_canvas(self):
show_msg('Information', '^_^', text=('Has not implemented yet.\n' 'Contributions are welcome!\n' '尚未实现, 欢迎贡献!'))
# ---------------------------------------
# slots: help
# ---------------------------------------
def show_instruction_msg(self):
from handyview.instruction_text import instruct_text, instruct_text_cn
msg = MessageDialog(self, instruct_text, instruct_text_cn)
# msg.setStyleSheet('QLabel{min-width:500 px; font-size: 20px;}')
msg.setWindowTitle('Instructions')
msg.exec_()
def set_fingerprint(self):
if self.canvas.show_fingerprint:
self.canvas.show_fingerprint = False
else:
self.canvas.show_fingerprint = True
self.canvas.show_image()
if __name__ == '__main__':
import platform
if platform.system() == 'Windows':
# set the icon in the task bar
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('HandyView')
print('Welcome to HandyView.')
app = QApplication(sys.argv)
screen = app.primaryScreen()
size = screen.size()
# rect = screen.availableGeometry()
main = MainWindow()
main.setWindowIcon(QIcon(os.path.join(ROOT_DIR, 'icon.ico')))
main.setGeometry(0, 0, size.width(), size.height()) # (left, top, width, height)
main.showMaximized()
# change status bar info
main.set_statusbar(f'Screen: {screen.name()} with size {size.width()} x {size.height()}.')
sys.exit(app.exec_())