hytos / HYTOS / HYTOS / MainWindow.py @ 5bcb1a4f
이력 | 보기 | 이력해설 | 다운로드 (61.8 KB)
1 |
# -*- coding: utf-8 -*-
|
---|---|
2 |
""" This is MainWindow module """
|
3 |
|
4 |
import sys |
5 |
import os |
6 |
import subprocess |
7 |
from functools import partial |
8 |
|
9 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
10 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands') |
11 |
import CreateCommand |
12 |
import CropCommand |
13 |
import AreaZoomCommand |
14 |
import FenceCommand |
15 |
import PlaceStreamlineCommand |
16 |
|
17 |
import numpy as np |
18 |
|
19 |
from PyQt5.QtCore import * |
20 |
from PyQt5.QtGui import * |
21 |
from PyQt5.QtWidgets import * |
22 |
from PyQt5.QtSvg import * |
23 |
|
24 |
from PIL import Image |
25 |
|
26 |
import MainWindow_UI |
27 |
import QtImageViewer |
28 |
from SingletonInstance import SingletonInstane |
29 |
|
30 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes') |
31 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
32 |
from SymbolSvgItem import SymbolSvgItem |
33 |
|
34 |
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
35 |
from EngineeringTextItem import QEngineeringTextItem |
36 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
37 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
38 |
from EngineeringErrorItem import QEngineeringErrorItem |
39 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
40 |
from AppDocData import * |
41 |
import SymbolTreeWidget |
42 |
import uuid |
43 |
|
44 |
|
45 |
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane): |
46 |
""" This is MainWindow class """
|
47 |
addMessage = pyqtSignal(Enum, str)
|
48 |
|
49 |
'''
|
50 |
@brief initialize
|
51 |
@author
|
52 |
@date
|
53 |
@history humkyung 2018.04.12 add splitter widget
|
54 |
Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
|
55 |
Jeongwoo 2018.05.09 Initialize Action group
|
56 |
Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
|
57 |
Add QActionGroup for managing checkable action
|
58 |
Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
|
59 |
humkyung 2018.08.23 add labelStatus to statusbar
|
60 |
|
61 |
'''
|
62 |
|
63 |
def __init__(self): |
64 |
try:
|
65 |
super(self.__class__, self).__init__() |
66 |
self.setupUi(self) |
67 |
|
68 |
self._label_mouse = QLabel(self.statusbar) |
69 |
self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0))) |
70 |
self.statusbar.addWidget(self._label_mouse) |
71 |
self.addMessage.connect(self.onAddMessage) |
72 |
self.showMaximized()
|
73 |
|
74 |
self.setMainWindowTitle()
|
75 |
|
76 |
self.graphicsView = QtImageViewer.QtImageViewer(self) |
77 |
self.graphicsView.setParent(self.centralwidget) |
78 |
self.graphicsView.useDefaultCommand()
|
79 |
self.graphicsView.setMouseTracking(True) |
80 |
self.graphicsView.viewport().installEventFilter(self) |
81 |
self.verticalLayout.addWidget(self.graphicsView) |
82 |
|
83 |
# Add Symbol TreeWidget
|
84 |
self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
|
85 |
self.symbolTreeWidget.header().hide()
|
86 |
self.verticalLayoutSymbolList.addWidget(self.symbolTreeWidget) |
87 |
|
88 |
# Initialize Action group
|
89 |
self.actionGroup = QActionGroup(self) |
90 |
self.actionGroup.addAction(self.actionLine) |
91 |
self.actionGroup.addAction(self.actionZoom) |
92 |
self.actionGroup.addAction(self.actionFitWindow) |
93 |
self.actionGroup.addAction(self.actionSave) |
94 |
|
95 |
# connect signals and slots
|
96 |
self.actionGroup.triggered.connect(self.actionGroupTriggered) |
97 |
self.actionClose.triggered.connect(self.close) |
98 |
self.actionNew.triggered.connect(self.on_new_drawing) |
99 |
self.actionOpen.triggered.connect(self.on_open_drawing) |
100 |
self.actionSave.triggered.connect(self.actionSaveCliked) |
101 |
self.actionCalculation.triggered.connect(self.calculation) |
102 |
self.actionLine.triggered.connect(self.onPlaceLine) |
103 |
self.actionConfiguration.triggered.connect(self.configuration) |
104 |
self.actionInitialize.triggered.connect(self.onInitializeScene) |
105 |
self.actionOptions.triggered.connect(self.onOptions) |
106 |
self.actionZoom.triggered.connect(self.onAreaZoom) |
107 |
self.actionFitWindow.triggered.connect(self.fitWindow) |
108 |
self.actionSymbol_Editor.triggered.connect(self.showSymbolEditor) |
109 |
self.toolButton_ClearLog.clicked.connect(self.clearlogs) |
110 |
self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged) |
111 |
|
112 |
self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
|
113 |
self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu) |
114 |
self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing) |
115 |
|
116 |
self.initTreeWidgetDrawingList()
|
117 |
self.initTableWidgetHMB()
|
118 |
self.load_drawing_list()
|
119 |
|
120 |
self.load_stylesheet_file()
|
121 |
self.load_language_file()
|
122 |
except Exception as ex: |
123 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
124 |
sys.exc_info()[-1].tb_lineno)
|
125 |
self.addMessage.emit(MessageType.Error, message)
|
126 |
|
127 |
def load_stylesheet_file(self): |
128 |
# load stylesheet file list
|
129 |
stylesheet_name = QtWidgets.qApp.stylesheet_name |
130 |
files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if |
131 |
os.path.splitext(file)[1] == '.qss'] |
132 |
for file in files: |
133 |
action = self.menuTheme.addAction(file) |
134 |
action.setCheckable(True)
|
135 |
action.setChecked(True) if stylesheet_name == file else action.setChecked(False) |
136 |
action.triggered.connect(partial(self.load_stylesheet, file)) |
137 |
# up to here
|
138 |
|
139 |
def load_language_file(self): |
140 |
# load language files
|
141 |
language_name = QtWidgets.qApp.language_name |
142 |
files = ['en_us'] # englisgh is default language |
143 |
files.extend([os.path.splitext(file)[0] for file in |
144 |
os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if |
145 |
os.path.splitext(file)[1] == '.qm']) |
146 |
for file in files: |
147 |
action = self.menuLanguage.addAction(file) |
148 |
action.setCheckable(True)
|
149 |
action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False) |
150 |
action.triggered.connect(partial(self.load_language, file)) |
151 |
# up to here
|
152 |
|
153 |
def setMainWindowTitle(self, drawingName=None): |
154 |
try:
|
155 |
_translate = QCoreApplication.translate |
156 |
|
157 |
version = QCoreApplication.applicationVersion() |
158 |
if drawingName is None: |
159 |
self.setWindowTitle(_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version))) |
160 |
else:
|
161 |
self.setWindowTitle(
|
162 |
_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)) + ' - {}'.format( |
163 |
drawingName)) |
164 |
except Exception as ex: |
165 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
166 |
sys.exc_info()[-1].tb_lineno)
|
167 |
self.addMessage.emit(MessageType.Error, message)
|
168 |
|
169 |
def clearlogs(self): |
170 |
try:
|
171 |
self.listWidgetLogs.clear()
|
172 |
except Exception as ex: |
173 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
174 |
sys.exc_info()[-1].tb_lineno)
|
175 |
self.addMessage.emit(MessageType.Error, message)
|
176 |
finally:
|
177 |
logs = self.listWidgetLogs.count()
|
178 |
if logs:
|
179 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs)) |
180 |
else:
|
181 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs') |
182 |
|
183 |
def openContextMenu(self, position): |
184 |
indexes = self.treeWidgetDrawingList.selectedIndexes()
|
185 |
if len(indexes) > 0: |
186 |
level = 0
|
187 |
index = indexes[0]
|
188 |
while index.parent().isValid():
|
189 |
index = index.parent() |
190 |
level += 1
|
191 |
|
192 |
menu = QMenu() |
193 |
|
194 |
itemPosition = self.mapTo(self, position) |
195 |
item = self.treeWidgetDrawingList.itemAt(itemPosition)
|
196 |
|
197 |
if level == 0: |
198 |
newDrawingAction = menu.addAction(self.tr('New...')) |
199 |
newDrawingAction.triggered.connect(lambda: self.newDrawingActionClickEvent(item)) |
200 |
menu.addAction(newDrawingAction) |
201 |
elif level == 1: |
202 |
# saveAsDrawingAction = menu.addAction(self.tr("Save As..."))
|
203 |
# saveAsDrawingAction.triggered.connect(lambda: self.saveAsDrawingActionClickEvent(item))
|
204 |
# menu.addAction(saveAsDrawingAction)
|
205 |
|
206 |
deleteDrawingAction = menu.addAction(self.tr("Delete")) |
207 |
deleteDrawingAction.triggered.connect(lambda: self.deleteDrawingActionClickEvent(item)) |
208 |
menu.addAction(deleteDrawingAction) |
209 |
|
210 |
menu.exec_(self.treeWidgetDrawingList.viewport().mapToGlobal(position))
|
211 |
|
212 |
def on_new_drawing(self): |
213 |
self.new_drawing()
|
214 |
|
215 |
def newDrawingActionClickEvent(self, item): |
216 |
self.new_drawing()
|
217 |
|
218 |
def saveAsDrawingActionClickEvent(self, item): |
219 |
sourceDb = item.text(2)
|
220 |
|
221 |
self.saveAs_drawing(sourceDb)
|
222 |
|
223 |
def deleteDrawingActionClickEvent(self, item): |
224 |
""" delete selected drawing """
|
225 |
try:
|
226 |
msg = QMessageBox(self)
|
227 |
msg.setIcon(QMessageBox.Question) |
228 |
msg.setText(self.tr('Do you want to delete drawing on list?\nHowever, Actual drawing is not deleted.')) |
229 |
msg.setWindowTitle(self.tr("Delete")) |
230 |
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) |
231 |
|
232 |
if QMessageBox.Ok == msg.exec_():
|
233 |
drawingName = item.text(0)
|
234 |
drawingPath = item.text(2)
|
235 |
|
236 |
app_doc_data = AppDocData.instance() |
237 |
app_doc_data.deleteDrawingByName(drawingPath) |
238 |
|
239 |
if app_doc_data.activeDrawing:
|
240 |
if drawingName == app_doc_data.activeDrawing.name and drawingPath == app_doc_data.activeDrawing.path: |
241 |
app_doc_data.activeDrawing = None
|
242 |
|
243 |
if self.graphicsView.hasImage(): |
244 |
self.graphicsView.clearImage()
|
245 |
self.graphicsView.scene.clear()
|
246 |
|
247 |
self.initTableWidgetHMB()
|
248 |
|
249 |
self.load_drawing_list()
|
250 |
except Exception as ex: |
251 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
252 |
sys.exc_info()[-1].tb_lineno)
|
253 |
self.addMessage.emit(MessageType.Error, message)
|
254 |
|
255 |
def clear_data(self): |
256 |
self.clear_HMB()
|
257 |
|
258 |
def eventFilter(self, source, event): |
259 |
""" display mouse position of graphics view """
|
260 |
if (event.type() == QEvent.MouseMove):
|
261 |
pos = self.graphicsView.mapToScene(event.pos())
|
262 |
self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y()))) |
263 |
|
264 |
return QWidget.eventFilter(self, source, event) |
265 |
|
266 |
def load_stylesheet(self, file): |
267 |
"""
|
268 |
@brief load stylesheets
|
269 |
@author humkyung
|
270 |
@date 2018.10.29
|
271 |
"""
|
272 |
|
273 |
QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
|
274 |
|
275 |
app_doc_data = AppDocData.instance() |
276 |
configs = [Config('app', 'stylesheet', file)] |
277 |
app_doc_data.saveAppConfigs(configs) |
278 |
|
279 |
for action in self.menuTheme.actions(): |
280 |
if action.text() == file: continue |
281 |
action.setChecked(False)
|
282 |
|
283 |
def load_language(self, file): |
284 |
"""
|
285 |
load language file and then apply selected language
|
286 |
"""
|
287 |
try:
|
288 |
|
289 |
qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file)) |
290 |
QtWidgets.qApp.load_language(qm_file) |
291 |
|
292 |
app_doc_data = AppDocData.instance() |
293 |
configs = [Config('app', 'language', file)] |
294 |
app_doc_data.saveAppConfigs(configs) |
295 |
|
296 |
for action in self.menuLanguage.actions(): |
297 |
if action.text().lower() == file.lower(): continue |
298 |
action.setChecked(False)
|
299 |
finally:
|
300 |
self.retranslateUi(self) |
301 |
|
302 |
def initTreeWidgetDrawingList(self): |
303 |
|
304 |
self.treeWidgetDrawingList.setHeaderHidden(False) |
305 |
self.treeWidgetDrawingList.header().setStretchLastSection(True) |
306 |
self.treeWidgetDrawingList.header().setDefaultAlignment(Qt.AlignCenter)
|
307 |
self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime'), self.tr('Path')]) |
308 |
self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) |
309 |
self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents) |
310 |
self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents) |
311 |
self.treeWidgetDrawingList.hideColumn(2) |
312 |
|
313 |
def initTableWidgetHMB(self): |
314 |
app_doc_data = AppDocData.instance() |
315 |
|
316 |
columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression() |
317 |
count = len(columnInfos)
|
318 |
self.tableWidgetHMB.setRowCount(count)
|
319 |
if len(columnInfos) > 0: |
320 |
self.tableWidgetHMB.setColumnCount(2) |
321 |
else:
|
322 |
self.tableWidgetHMB.setColumnCount(0) |
323 |
self.tableWidgetHMB.hideRow(0) # uid |
324 |
self.tableWidgetHMB.hideRow(1) # components_uid |
325 |
self.tableWidgetHMB.hideRow(2) # stream no |
326 |
self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
327 |
self.tableWidgetHMB.verticalHeader().setVisible(False) |
328 |
|
329 |
col_names = ['Stream No.', 'Unit'] |
330 |
self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
|
331 |
|
332 |
rowIndex = 0
|
333 |
for columnInfo in columnInfos: |
334 |
name = columnInfo[0]
|
335 |
unit = self.convertToUnits(columnInfo[1]) |
336 |
|
337 |
self.tableWidgetHMB.setItem(rowIndex, 0, |
338 |
self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
|
339 |
QColor(230, 230, 230))) |
340 |
self.tableWidgetHMB.setItem(rowIndex, 1, |
341 |
self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
|
342 |
QColor(230, 230, 230))) |
343 |
|
344 |
rowIndex += 1
|
345 |
|
346 |
self.tableWidgetHMB.resizeColumnsToContents()
|
347 |
self.tableWidgetHMB.resizeRowsToContents()
|
348 |
|
349 |
'''
|
350 |
@brief Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
|
351 |
@author yeonjin
|
352 |
@date 19.08.30
|
353 |
'''
|
354 |
|
355 |
def findValue(self, key): |
356 |
value = None
|
357 |
|
358 |
key = key.replace("{", "").replace("}", "") |
359 |
for attr in AppDocData.instance().activeDrawing.attrs: |
360 |
if attr[0] == 'Units': |
361 |
if key in attr[1]: |
362 |
value = attr[1][key]
|
363 |
break
|
364 |
|
365 |
return value
|
366 |
|
367 |
'''
|
368 |
@brief Convert UnitsExpression To Units Value
|
369 |
@author yeonjin
|
370 |
@date 19.08.29
|
371 |
'''
|
372 |
|
373 |
def convertToUnits(self, unitsExpression): |
374 |
import re |
375 |
|
376 |
if unitsExpression is None or AppDocData.instance().activeDrawing is None: |
377 |
return '' |
378 |
|
379 |
found = re.findall('{.*?}', unitsExpression)
|
380 |
for f in found: |
381 |
key = f |
382 |
val = self.findValue(key)
|
383 |
if val:
|
384 |
unitsExpression = unitsExpression.replace(key, val) |
385 |
|
386 |
return unitsExpression
|
387 |
|
388 |
'''
|
389 |
@brief Clear TreeWidget and Set Current PID
|
390 |
@author Jeongwoo
|
391 |
@date 18.04.11
|
392 |
@history 2018.04.26 Jeongwoo Add Child [SYMBOLS, NOTES] into root item
|
393 |
2018.05.09 Jeongwoo Change method to add default tree items
|
394 |
humkyung 2018.06.10 add tree item for Line No and Unknown Item
|
395 |
'''
|
396 |
|
397 |
def load_drawing_list(self): |
398 |
"""
|
399 |
@brief load p&id drawing list
|
400 |
@author humkyung
|
401 |
@date 18.11.02
|
402 |
"""
|
403 |
|
404 |
try:
|
405 |
app_doc_data = AppDocData.instance() |
406 |
drawings = app_doc_data.getDrawings() |
407 |
|
408 |
self.treeWidgetDrawingList.clear()
|
409 |
self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), '']) |
410 |
|
411 |
for drawing in drawings: |
412 |
item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
|
413 |
item.setData(0, Qt.UserRole, drawing)
|
414 |
|
415 |
self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format( |
416 |
self.treeWidgetDrawingList.root.childCount()))
|
417 |
self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root) |
418 |
self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder) |
419 |
self.treeWidgetDrawingList.resizeColumnToContents(0) |
420 |
|
421 |
except Exception as ex: |
422 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
423 |
sys.exc_info()[-1].tb_lineno)
|
424 |
self.addMessage.emit(MessageType.Error, message)
|
425 |
|
426 |
def open_selected_drawing(self, item): |
427 |
""" open selected drawing """
|
428 |
path = item.text(2)
|
429 |
if os.path.exists(path):
|
430 |
self.open_drawing(path)
|
431 |
|
432 |
'''
|
433 |
@brief action save click event
|
434 |
@author kyouho
|
435 |
@date 2018.08.09
|
436 |
@history 2018.11.02 euisung add line data list db update
|
437 |
humkyung save saved time to database
|
438 |
2018.11.05 euisung add note data list db update
|
439 |
2018.11.05 euisung add db delete process before save
|
440 |
2018.11.12 euisung db part move new method to dbUpdate
|
441 |
'''
|
442 |
|
443 |
def actionSaveCliked(self): |
444 |
from datetime import datetime |
445 |
from AppDocData import AppDocData |
446 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
447 |
from SaveWorkCommand import SaveWorkCommand |
448 |
|
449 |
try:
|
450 |
app_doc_data = AppDocData.instance() |
451 |
if app_doc_data.activeDrawing is None: |
452 |
self.showImageSelectionMessageBox()
|
453 |
return
|
454 |
|
455 |
app_doc_data.activeDrawing.clearItemList() |
456 |
|
457 |
items = self.graphicsView.scene.items()
|
458 |
for item in items: |
459 |
if issubclass(type(item), QEngineeringAbstractItem): |
460 |
app_doc_data.activeDrawing.allItems.append(item) |
461 |
if issubclass(type(item), QEngineeringTextItem): |
462 |
app_doc_data.texts.append(item) |
463 |
|
464 |
count = len(app_doc_data.activeDrawing.allItems)
|
465 |
if count > 0: |
466 |
try:
|
467 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, |
468 |
self) if not hasattr(self, 'progress') else self.progress |
469 |
self.progress.setWindowModality(Qt.WindowModal)
|
470 |
self.progress.setAutoReset(True) |
471 |
self.progress.setAutoClose(True) |
472 |
self.progress.setMinimum(0) |
473 |
self.progress.resize(600, 100) |
474 |
self.progress.setWindowTitle(self.tr("Save")) |
475 |
self.progress.show()
|
476 |
|
477 |
self.save_drawing_data()
|
478 |
finally:
|
479 |
self.load_drawing_list()
|
480 |
self.progress.setValue(self.progress.maximum()) |
481 |
self.progress.hide()
|
482 |
|
483 |
except Exception as ex: |
484 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
485 |
sys.exc_info()[-1].tb_lineno)
|
486 |
self.addMessage.emit(MessageType.Error, message)
|
487 |
|
488 |
def save_drawing_data(self): |
489 |
""" save drawing data """
|
490 |
from datetime import datetime |
491 |
from AppDocData import AppDocData |
492 |
from SymbolSvgItem import SymbolSvgItem |
493 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
494 |
|
495 |
try:
|
496 |
app_doc_data = AppDocData.instance() |
497 |
items = app_doc_data.activeDrawing.allItems |
498 |
|
499 |
maxValue = len(items)
|
500 |
self.progress.setMaximum(maxValue)
|
501 |
|
502 |
index = 0
|
503 |
for item in items: |
504 |
if type(item) is SymbolSvgItem or type(item) is QEngineeringStreamlineItem: |
505 |
app_doc_data.saveToDatabase(item, index) |
506 |
self.progress.setValue(index)
|
507 |
index += 1
|
508 |
|
509 |
QApplication.processEvents() |
510 |
|
511 |
if app_doc_data.activeDrawing:
|
512 |
app_doc_data.activeDrawing.hmbTable.saveData() |
513 |
|
514 |
""" update drawing's modified time """
|
515 |
drawings = app_doc_data.getDrawings() |
516 |
drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing] |
517 |
if drawing:
|
518 |
drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
519 |
appDocData.updateDrawing(drawing) |
520 |
|
521 |
except Exception as ex: |
522 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
523 |
sys.exc_info()[-1].tb_lineno)
|
524 |
self.addMessage.emit(MessageType.Error, message)
|
525 |
|
526 |
'''
|
527 |
@brief add message listwidget
|
528 |
@author humkyung
|
529 |
@date 2018.07.31
|
530 |
'''
|
531 |
|
532 |
def onAddMessage(self, messageType, message): |
533 |
from AppDocData import MessageType |
534 |
|
535 |
try:
|
536 |
current = QDateTime.currentDateTime() |
537 |
|
538 |
item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message)) |
539 |
if messageType == MessageType.Error:
|
540 |
item.setForeground(Qt.red) |
541 |
elif messageType == MessageType.Information:
|
542 |
item.setForeground(Qt.blue) |
543 |
|
544 |
self.listWidgetLogs.insertItem(0, item) |
545 |
except Exception as ex: |
546 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
547 |
sys.exc_info()[-1].tb_lineno))
|
548 |
finally:
|
549 |
logs = self.listWidgetLogs.count()
|
550 |
if logs:
|
551 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs)) |
552 |
else:
|
553 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs') |
554 |
|
555 |
'''
|
556 |
@brief Area Zoom
|
557 |
@author Jeongwoo
|
558 |
@date 2018.06.27
|
559 |
@history connect command's rejected signal
|
560 |
'''
|
561 |
|
562 |
def onAreaZoom(self, action): |
563 |
if self.actionZoom.isChecked(): |
564 |
cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
|
565 |
cmd.onRejected.connect(self.onCommandRejected)
|
566 |
self.graphicsView.command = cmd
|
567 |
|
568 |
'''
|
569 |
@brief Fit Window
|
570 |
@author Jeongwoo
|
571 |
@date 2018.06.27
|
572 |
@history 2018.06.27 Jeongwoo Chnage method to initialize command [Set None → DefaultCommand]
|
573 |
'''
|
574 |
|
575 |
def fitWindow(self, action): |
576 |
self.graphicsView.useDefaultCommand()
|
577 |
self.graphicsView.zoomImageInit()
|
578 |
|
579 |
'''
|
580 |
@brief selection changed
|
581 |
@author humkyung
|
582 |
@date 2018.06.27
|
583 |
@history humkung 2018.07.08 call tree widget's findItem
|
584 |
'''
|
585 |
|
586 |
def onSelectionChanged(self): |
587 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
588 |
|
589 |
items = [item for item in self.graphicsView.scene.selectedItems() if |
590 |
issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem] |
591 |
if items:
|
592 |
item = items[-1]
|
593 |
|
594 |
if type(item) is QEngineeringErrorItem: |
595 |
for index in range(self.tableWidgetHMB.rowCount()): |
596 |
|
597 |
if self.tableWidgetHMB.item(index, 1).tag is item: |
598 |
self.tableWidgetHMB.selectRow(index)
|
599 |
break
|
600 |
|
601 |
'''
|
602 |
@brief Initialize scene and itemTreeWidget
|
603 |
@author Jeongwoo
|
604 |
|
605 |
@date 2018.06.14
|
606 |
@history humkyung 2018.08.16 ask to delete recognized items before remove
|
607 |
'''
|
608 |
|
609 |
def onInitializeScene(self, action): |
610 |
|
611 |
if not self.graphicsView.hasImage(): |
612 |
self.showImageSelectionMessageBox()
|
613 |
return
|
614 |
|
615 |
try:
|
616 |
msg = QMessageBox(self)
|
617 |
msg.setIcon(QMessageBox.Question) |
618 |
msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.')) |
619 |
msg.setWindowTitle(self.tr("Clear Screen")) |
620 |
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) |
621 |
if QMessageBox.Ok == msg.exec_():
|
622 |
|
623 |
appDocData = AppDocData.instance() |
624 |
appDocData.activeDrawing.hmbTable.reset() |
625 |
appDocData.clearItemList(True)
|
626 |
|
627 |
items = self.graphicsView.scene.items()
|
628 |
for item in items: |
629 |
if type(item) is not QGraphicsPixmapItem and item.scene() is not None: |
630 |
self.graphicsView.scene.removeItem(item)
|
631 |
|
632 |
appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID) |
633 |
|
634 |
self.initTableWidgetHMB()
|
635 |
|
636 |
except Exception as ex: |
637 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
638 |
sys.exc_info()[-1].tb_lineno)
|
639 |
self.addMessage.emit(MessageType.Error, message)
|
640 |
|
641 |
'''
|
642 |
@brief Manage Checkable Action statement
|
643 |
@author Jeongwoo
|
644 |
@date 2018.05.10
|
645 |
@history 2018.06.27 Jeongwoo Chnage method to initialize command [Set None → DefaultCommand]
|
646 |
'''
|
647 |
|
648 |
def actionGroupTriggered(self, action): |
649 |
if hasattr(self.actionLine, 'tag'): |
650 |
self.actionLine.tag.onRejected.emit(None) |
651 |
|
652 |
if self.graphicsView.command is not None: |
653 |
self.graphicsView.useDefaultCommand()
|
654 |
|
655 |
for _action in [x for x in self.actionGroup.actions() if x is not action]: |
656 |
_action.setChecked(False)
|
657 |
if _action is self.actionLine: |
658 |
for item in self.graphicsView.scene.items(): |
659 |
if not hasattr(item, 'connectors'): continue |
660 |
for connector in item.connectors: connector.hide() |
661 |
|
662 |
action.setChecked(True)
|
663 |
if action is self.actionLine: |
664 |
for item in self.graphicsView.scene.items(): |
665 |
if not hasattr(item, 'connectors'): continue |
666 |
for connector in item.connectors: connector.setVisible(True) |
667 |
|
668 |
def showSymbolEditor(self): |
669 |
from SymbolEditorDialog import QSymbolEditorDialog |
670 |
|
671 |
dlg = QSymbolEditorDialog() |
672 |
dlg.exec_() |
673 |
|
674 |
def onOptions(self): |
675 |
from OptionsDialog import QOptionsDialog |
676 |
|
677 |
self.dlgOptions = QOptionsDialog(self) |
678 |
self.dlgOptions.exec_()
|
679 |
|
680 |
def calculation(self): |
681 |
""" execute hydro calculation """
|
682 |
from AppDocData import AppDocData |
683 |
from Calculation import Calculation |
684 |
from HydroCalculationCommand import HydroCalculationCommand |
685 |
|
686 |
try:
|
687 |
appDocData = AppDocData.instance() |
688 |
if appDocData.activeDrawing is None: |
689 |
self.showImageSelectionMessageBox()
|
690 |
return
|
691 |
|
692 |
hmbs = appDocData.activeDrawing.hmbTable._hmbs |
693 |
if hmbs is not None: |
694 |
try:
|
695 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, |
696 |
self) if not hasattr(self, 'progress') else self.progress |
697 |
self.progress.setWindowModality(Qt.WindowModal)
|
698 |
self.progress.setAutoReset(True) |
699 |
self.progress.setAutoClose(True) |
700 |
self.progress.setMinimum(0) |
701 |
self.progress.resize(600, 100) |
702 |
self.progress.setWindowTitle(self.tr("Calculate data...")) |
703 |
self.progress.show()
|
704 |
|
705 |
maxValue = len(hmbs)
|
706 |
self.progress.setMaximum(maxValue)
|
707 |
|
708 |
for hmb in hmbs: |
709 |
self.progress.setValue(self.progress.value() + 1) |
710 |
|
711 |
if hmb.phase_type:
|
712 |
Calculation(hmb) |
713 |
|
714 |
QApplication.processEvents() |
715 |
|
716 |
""" generate loop """
|
717 |
cmd = HydroCalculationCommand(self.graphicsView)
|
718 |
cmd.execute(None)
|
719 |
self.display_loops(cmd.loops)
|
720 |
|
721 |
self.load_HMB()
|
722 |
finally:
|
723 |
self.progress.setValue(self.progress.maximum()) |
724 |
self.progress.hide()
|
725 |
except Exception as ex: |
726 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
727 |
sys.exc_info()[-1].tb_lineno)
|
728 |
self.addMessage.emit(MessageType.Error, message)
|
729 |
|
730 |
def display_loops(self, loops): |
731 |
""" display loops """
|
732 |
drawing = AppDocData.instance().activeDrawing |
733 |
if drawing is None: return |
734 |
|
735 |
if loops:
|
736 |
self.tableWidgetLoop.clear()
|
737 |
self.tableWidgetLoop.setColumnCount(len(loops) * 4) |
738 |
|
739 |
_col_names = [[loop.name, 'pressure', 'dP', 'density\nelevation'] for loop in loops] |
740 |
col_names = [] |
741 |
for col_name in _col_names: col_names.extend(col_name) |
742 |
self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
|
743 |
|
744 |
max_rows = 0
|
745 |
for col in range(len(loops)): |
746 |
rows = len(loops[col].items)
|
747 |
max_rows = max(max_rows, rows)
|
748 |
self.tableWidgetLoop.setRowCount(max_rows)
|
749 |
|
750 |
for row in range(len(loops[col].items)): |
751 |
item = QTableWidgetItem(str(loops[col].items[row]))
|
752 |
item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) |
753 |
self.tableWidgetLoop.setItem(row, col * 4, item) |
754 |
|
755 |
# display calcuation values
|
756 |
for row in range(len(loops[col].items)): |
757 |
if loops[col].items[row] in loops[col].pressures: |
758 |
item = QTableWidgetItem(str(loops[col].pressures[loops[col].items[row]]))
|
759 |
if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red) |
760 |
self.tableWidgetLoop.setItem(row, col * 4 + 1, item) |
761 |
|
762 |
if loops[col].items[row] in loops[col].pressure_drops: |
763 |
item = QTableWidgetItem(str(loops[col].pressure_drops[loops[col].items[row]]))
|
764 |
if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red) |
765 |
self.tableWidgetLoop.setItem(row, col * 4 + 2, item) |
766 |
|
767 |
if loops[col].items[row] in loops[col].density_elevations: |
768 |
item = QTableWidgetItem(str(loops[col].density_elevations[loops[col].items[row]]))
|
769 |
if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red) |
770 |
self.tableWidgetLoop.setItem(row, col * 4 + 3, item) |
771 |
|
772 |
'''
|
773 |
@brief configuration
|
774 |
'''
|
775 |
|
776 |
def configuration(self): |
777 |
from ConfigurationDialog import QConfigurationDialog |
778 |
try:
|
779 |
appDocData = AppDocData.instance() |
780 |
if appDocData.activeDrawing is None: |
781 |
self.showImageSelectionMessageBox()
|
782 |
return
|
783 |
|
784 |
dlg = QConfigurationDialog(self)
|
785 |
(isAccepted, isDataConversion, decimal) = dlg.showDialog() |
786 |
if isAccepted == True: |
787 |
if isDataConversion == True: |
788 |
self.data_conversion(decimal)
|
789 |
else:
|
790 |
self.reload_units()
|
791 |
|
792 |
except Exception as ex: |
793 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
794 |
sys.exc_info()[-1].tb_lineno)
|
795 |
self.addMessage.emit(MessageType.Error, message)
|
796 |
|
797 |
def data_conversion(self, decimal): |
798 |
from Drawing import Drawing |
799 |
from Calculation import Conversion |
800 |
|
801 |
try:
|
802 |
Conversion(decimal) |
803 |
|
804 |
self.load_HMB()
|
805 |
self.reload_units()
|
806 |
|
807 |
except Exception as ex: |
808 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
809 |
sys.exc_info()[-1].tb_lineno)
|
810 |
self.addMessage.emit(MessageType.Error, message)
|
811 |
|
812 |
'''
|
813 |
@brief Show Image Selection Guide MessageBox
|
814 |
@author Jeongwoo
|
815 |
@date 2018.05.02
|
816 |
'''
|
817 |
|
818 |
def showImageSelectionMessageBox(self): |
819 |
QMessageBox.information(self, self.tr("Notice"), self.tr("First select image drawing")) |
820 |
|
821 |
def display_colors(self, value): |
822 |
""" display colors """
|
823 |
from DisplayColors import DisplayColors |
824 |
from DisplayColors import DisplayOptions |
825 |
|
826 |
DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType |
827 |
if hasattr(self, 'graphicsView'): |
828 |
self.graphicsView.scene.update(self.graphicsView.sceneRect()) |
829 |
DisplayColors.instance().save_data() |
830 |
|
831 |
'''
|
832 |
@brief Open Border file
|
833 |
@author yeonjin
|
834 |
@date 2019.07.10
|
835 |
'''
|
836 |
|
837 |
def open_border_file(self): |
838 |
app_doc_data = AppDocData.instance() |
839 |
borderFile = app_doc_data.border_file_path |
840 |
if not os.path.exists(borderFile): |
841 |
self.create_border_file(borderFile)
|
842 |
|
843 |
self.graphicsView.loadImageFromFile(fileName=borderFile)
|
844 |
|
845 |
'''
|
846 |
@brief Create Border file
|
847 |
@author yeonjin
|
848 |
@date 2019.07.10
|
849 |
'''
|
850 |
|
851 |
def create_border_file(self, border): |
852 |
|
853 |
from PIL import Image |
854 |
# A4 size : 210, 297
|
855 |
# A3 size : 297, 420
|
856 |
# A2 size : 420, 594
|
857 |
# A1 size : 594, 841
|
858 |
# A0 size : 841, 1189
|
859 |
# color : 0, 128, 128 진한 청록
|
860 |
# color : 255, 255, 255 White
|
861 |
img = Image.new('RGBA', (1189, 841), (255, 255, 255)) |
862 |
img.save(border) |
863 |
|
864 |
def setAttributes(self, drawing): |
865 |
drawing.setAttributes() |
866 |
|
867 |
'''
|
868 |
@brief Reload HMB Units
|
869 |
@author yeonjin
|
870 |
@date 2019.07.10
|
871 |
'''
|
872 |
|
873 |
def reload_units(self): |
874 |
from Drawing import Drawing |
875 |
|
876 |
try:
|
877 |
app_doc_data = AppDocData.instance() |
878 |
drawing = app_doc_data.activeDrawing |
879 |
|
880 |
self.setAttributes(drawing)
|
881 |
|
882 |
columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression() |
883 |
|
884 |
rowIndex = 0
|
885 |
for columnInfo in columnInfos: |
886 |
name = columnInfo[0]
|
887 |
unit = self.convertToUnits(columnInfo[1]) |
888 |
|
889 |
self.tableWidgetHMB.setItem(rowIndex, 0, |
890 |
self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
|
891 |
QColor(230, 230, 230))) |
892 |
self.tableWidgetHMB.setItem(rowIndex, 1, |
893 |
self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
|
894 |
QColor(230, 230, 230))) |
895 |
|
896 |
rowIndex += 1
|
897 |
|
898 |
self.tableWidgetHMB.resizeColumnsToContents()
|
899 |
self.tableWidgetHMB.resizeRowsToContents()
|
900 |
|
901 |
except Exception as ex: |
902 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
903 |
sys.exc_info()[-1].tb_lineno)
|
904 |
self.addMessage.emit(MessageType.Error, message)
|
905 |
|
906 |
def load_data(self, drawing): |
907 |
""" load data from drawing """
|
908 |
from Drawing import Drawing |
909 |
|
910 |
try:
|
911 |
app_doc_data = AppDocData.instance() |
912 |
|
913 |
## Set appDocData
|
914 |
app_doc_data.clear() |
915 |
self.onCommandRejected()
|
916 |
|
917 |
app_doc_data.activeDrawing = drawing |
918 |
|
919 |
self.setAttributes(drawing)
|
920 |
self.setMainWindowTitle(drawing.path)
|
921 |
self.initTableWidgetHMB()
|
922 |
## Load data on database
|
923 |
|
924 |
self.symbolTreeWidget.initSymbolTreeWidget()
|
925 |
|
926 |
components = app_doc_data.getComponentListByDrawingUID(drawing) |
927 |
count = len(components)
|
928 |
|
929 |
if count > 0: |
930 |
try:
|
931 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, |
932 |
self) if not hasattr(self, 'progress') else self.progress |
933 |
self.progress.setWindowModality(Qt.WindowModal)
|
934 |
self.progress.setAutoReset(True) |
935 |
self.progress.setAutoClose(True) |
936 |
self.progress.setMinimum(0) |
937 |
self.progress.resize(600, 100) |
938 |
self.progress.setWindowTitle(self.tr("Load data...")) |
939 |
self.progress.show()
|
940 |
|
941 |
self.load_components(components)
|
942 |
|
943 |
self.load_HMB()
|
944 |
finally:
|
945 |
self.progress.setValue(self.progress.maximum()) |
946 |
self.progress.hide()
|
947 |
|
948 |
# self.changeViewCheckedState(False)
|
949 |
|
950 |
except Exception as ex: |
951 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
952 |
sys.exc_info()[-1].tb_lineno)
|
953 |
self.addMessage.emit(MessageType.Error, message)
|
954 |
|
955 |
def saveAs_drawing(self, sourceDb): |
956 |
import uuid |
957 |
from shutil import copyfile |
958 |
from datetime import datetime |
959 |
from Drawing import Drawing |
960 |
|
961 |
workspace = self.getWorkSpace()
|
962 |
|
963 |
options = QFileDialog.Options() |
964 |
options |= QFileDialog.DontUseNativeDialog |
965 |
name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)', |
966 |
options=options) |
967 |
if name:
|
968 |
if os.path.splitext(name)[1] != '.hytos': name += '.hytos' |
969 |
|
970 |
app_doc_data = AppDocData.instance() |
971 |
# copy template.db to name
|
972 |
copyfile(sourceDb, name) |
973 |
|
974 |
matches = [drawing for drawing in app_doc_data.getDrawings() if |
975 |
os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
|
976 |
if not matches: |
977 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
978 |
app_doc_data.saveDrawing(drawing) |
979 |
else:
|
980 |
drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
981 |
app_doc_data.updateDrawing(drawing) |
982 |
|
983 |
self.load_drawing_list()
|
984 |
self.open_border_file()
|
985 |
self.load_data(drawing)
|
986 |
|
987 |
'''
|
988 |
@brief create new drawing
|
989 |
@author yeonjin
|
990 |
@date 2019.07.03
|
991 |
'''
|
992 |
|
993 |
def new_drawing(self): |
994 |
import uuid |
995 |
from shutil import copyfile |
996 |
from datetime import datetime |
997 |
from Drawing import Drawing |
998 |
|
999 |
workspace = self.getWorkSpace()
|
1000 |
|
1001 |
options = QFileDialog.Options() |
1002 |
options |= QFileDialog.DontUseNativeDialog |
1003 |
name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options) |
1004 |
if name:
|
1005 |
|
1006 |
if os.path.splitext(name)[1] != '.hytos': name += '.hytos' |
1007 |
|
1008 |
app_doc_data = AppDocData.instance() |
1009 |
# copy template.db to name
|
1010 |
copyfile(app_doc_data.getTemplateDbPath(), name) |
1011 |
|
1012 |
matches = [drawing for drawing in app_doc_data.getDrawings() if |
1013 |
os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
|
1014 |
if not matches: |
1015 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
1016 |
app_doc_data.saveDrawing(drawing) |
1017 |
else:
|
1018 |
drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
1019 |
app_doc_data.updateDrawing(drawing) |
1020 |
|
1021 |
self.load_drawing_list()
|
1022 |
self.open_border_file()
|
1023 |
self.load_data(drawing)
|
1024 |
|
1025 |
def on_open_drawing(self): |
1026 |
""" open selected drawing by user """
|
1027 |
workspace = self.getWorkSpace()
|
1028 |
|
1029 |
options = QFileDialog.Options() |
1030 |
options |= QFileDialog.DontUseNativeDialog |
1031 |
name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options) |
1032 |
if name: self.open_drawing(name) |
1033 |
|
1034 |
def open_drawing(self, name): |
1035 |
""" open given drawing has name """
|
1036 |
import uuid |
1037 |
from Drawing import Drawing |
1038 |
from datetime import datetime |
1039 |
|
1040 |
app_doc_data = AppDocData.instance() |
1041 |
drawings = app_doc_data.getDrawings() |
1042 |
matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)] |
1043 |
if not matches: |
1044 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
1045 |
app_doc_data.saveDrawing(drawing) |
1046 |
|
1047 |
self.load_drawing_list()
|
1048 |
else:
|
1049 |
drawing = matches[0]
|
1050 |
|
1051 |
self.open_border_file()
|
1052 |
self.load_data(drawing)
|
1053 |
|
1054 |
def getWorkSpace(self): |
1055 |
""" get work space path """
|
1056 |
app_doc_data = AppDocData.instance() |
1057 |
|
1058 |
configs = app_doc_data.getAppConfigs('option', 'WorkSpace') |
1059 |
if configs and len(configs) == 1: |
1060 |
return configs[0].value |
1061 |
else:
|
1062 |
return os.getcwd()
|
1063 |
|
1064 |
def changeViewCheckedState(self, checked, clear=True): |
1065 |
'''
|
1066 |
@brief change view checked state
|
1067 |
@author euisung
|
1068 |
@date 2019.03.06
|
1069 |
'''
|
1070 |
if clear:
|
1071 |
self.initTableWidgetHMB()
|
1072 |
# self.clear_data()
|
1073 |
|
1074 |
'''
|
1075 |
@brief create a line
|
1076 |
@author humkyung
|
1077 |
@history Jeongwoo 2018.05.10 Change method for Checkable action
|
1078 |
'''
|
1079 |
|
1080 |
def onPlaceLine(self): |
1081 |
self.actionLine.setChecked(True) |
1082 |
if not hasattr(self.actionLine, 'tag'): |
1083 |
self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView) |
1084 |
self.actionLine.tag.onSuccess.connect(self.onLineCreated) |
1085 |
self.actionLine.tag.onRejected.connect(self.onCommandRejected) |
1086 |
|
1087 |
self.graphicsView.command = self.actionLine.tag |
1088 |
|
1089 |
'''
|
1090 |
@brief add created lines to scene
|
1091 |
@author humkyung
|
1092 |
@date 2018.07.23
|
1093 |
'''
|
1094 |
|
1095 |
def onLineCreated(self): |
1096 |
try:
|
1097 |
count = len(self.actionLine.tag.streamline._vertices) |
1098 |
if count > 1: |
1099 |
self.add_hmb_data(self.actionLine.tag.streamline) |
1100 |
self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed) |
1101 |
self.load_HMB()
|
1102 |
finally:
|
1103 |
self.actionLine.tag.reset()
|
1104 |
|
1105 |
def on_stream_line_deleted(self, stream_line): |
1106 |
""" callback after stream line is deleted """
|
1107 |
app_doc_data = AppDocData.instance() |
1108 |
activeDrawing = app_doc_data.activeDrawing |
1109 |
if activeDrawing:
|
1110 |
activeDrawing.hmbTable.deleteByUID(stream_line.uid) |
1111 |
|
1112 |
self.load_HMB()
|
1113 |
|
1114 |
def add_hmb_data(self, stream_line): |
1115 |
""" add a new hmb data associated with given stream line """
|
1116 |
from HMBTable import HMBTable |
1117 |
import uuid |
1118 |
|
1119 |
try:
|
1120 |
drawing = AppDocData.instance().activeDrawing |
1121 |
if drawing:
|
1122 |
components_uid = stream_line.uid |
1123 |
stream_no = self.getNextStreamNo(drawing)
|
1124 |
stream_line.stream_no = stream_no |
1125 |
drawing.hmbTable.add(components_uid, stream_no) |
1126 |
except Exception as ex: |
1127 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1128 |
sys.exc_info()[-1].tb_lineno)
|
1129 |
self.addMessage.emit(MessageType.Error, message)
|
1130 |
|
1131 |
def getNextStreamNo(self, drawing): |
1132 |
|
1133 |
if len(list(drawing.hmbTable.streamNos())) == 0: |
1134 |
return 1 |
1135 |
else:
|
1136 |
streamNos = sorted(list(drawing.hmbTable.streamNos())) |
1137 |
lastStreamNo = streamNos[-1]
|
1138 |
return lastStreamNo + 1 |
1139 |
|
1140 |
def clear_HMB(self): |
1141 |
self.tableWidgetHMB.clearContents()
|
1142 |
self.tableWidgetHMB.setColumnCount(0) |
1143 |
|
1144 |
def load_HMB(self): |
1145 |
drawing = AppDocData.instance().activeDrawing |
1146 |
if drawing is None: return |
1147 |
|
1148 |
hmbs = drawing.hmbTable._hmbs |
1149 |
if hmbs is not None: |
1150 |
self.tableWidgetHMB.setColumnCount(2) |
1151 |
|
1152 |
col_names = ['Stream No.', 'Unit'] |
1153 |
for hmb in hmbs: |
1154 |
columnCount = self.tableWidgetHMB.columnCount()
|
1155 |
self.tableWidgetHMB.setColumnCount(columnCount + 1) |
1156 |
col_names.append(str(hmb.stream_no))
|
1157 |
|
1158 |
self.tableWidgetHMB.setItem(0, columnCount, self.setTableWidgetItemProperties(hmb.uid, |
1159 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1160 |
self.tableWidgetHMB.setItem(1, columnCount, self.setTableWidgetItemProperties(hmb.components_uid, |
1161 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1162 |
self.tableWidgetHMB.setItem(2, columnCount, self.setTableWidgetItemProperties(hmb.stream_no, |
1163 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1164 |
self.tableWidgetHMB.setItem(3, columnCount, self.setTableWidgetItemProperties(hmb.phase_type, |
1165 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1166 |
self.tableWidgetHMB.setItem(4, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_mass, |
1167 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1168 |
self.tableWidgetHMB.setItem(5, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_volume, |
1169 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1170 |
self.tableWidgetHMB.setItem(6, columnCount, self.setTableWidgetItemProperties(hmb.density, |
1171 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1172 |
self.tableWidgetHMB.setItem(7, columnCount, self.setTableWidgetItemProperties(hmb.viscosity, |
1173 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1174 |
self.tableWidgetHMB.setItem(8, columnCount, self.setTableWidgetItemProperties(hmb.temperature, |
1175 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1176 |
self.tableWidgetHMB.setItem(9, columnCount, self.setTableWidgetItemProperties(hmb.molecular_weight, |
1177 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1178 |
self.tableWidgetHMB.setItem(10, columnCount, self.setTableWidgetItemProperties(hmb.specific_heat_ratio, |
1179 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1180 |
self.tableWidgetHMB.setItem(11, columnCount, self.setTableWidgetItemProperties(hmb.compress_factor, |
1181 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1182 |
self.tableWidgetHMB.setItem(12, columnCount, self.setTableWidgetItemProperties(hmb.nominal_pipe_size, |
1183 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1184 |
self.tableWidgetHMB.setItem(13, columnCount, self.setTableWidgetItemProperties(hmb.inside_pipe_size, |
1185 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1186 |
self.tableWidgetHMB.setItem(14, columnCount, self.setTableWidgetItemProperties(hmb.schedule_no, |
1187 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1188 |
self.tableWidgetHMB.setItem(15, columnCount, self.setTableWidgetItemProperties(hmb.straight_length, |
1189 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1190 |
self.tableWidgetHMB.setItem(16, columnCount, |
1191 |
self.setTableWidgetItemProperties(hmb.equivalent_length_input,
|
1192 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1193 |
self.tableWidgetHMB.setItem(17, columnCount, self.setTableWidgetItemProperties(hmb.fitting_length, |
1194 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1195 |
self.tableWidgetHMB.setItem(18, columnCount, self.setTableWidgetItemProperties(hmb.fitting_K, |
1196 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1197 |
self.tableWidgetHMB.setItem(19, columnCount, |
1198 |
self.setTableWidgetItemProperties(hmb.equivalent_length_cal,
|
1199 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1200 |
self.tableWidgetHMB.setItem(20, columnCount, self.setTableWidgetItemProperties(hmb.roughness, |
1201 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1202 |
self.tableWidgetHMB.setItem(21, columnCount, self.setTableWidgetItemProperties(hmb.limitation_velocity, |
1203 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1204 |
self.tableWidgetHMB.setItem(22, columnCount, |
1205 |
self.setTableWidgetItemProperties(hmb.limitation_pressure_drop,
|
1206 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1207 |
self.tableWidgetHMB.setItem(23, columnCount, self.setTableWidgetItemProperties(hmb.velocity, |
1208 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1209 |
self.tableWidgetHMB.setItem(24, columnCount, self.setTableWidgetItemProperties(hmb.reynolds, |
1210 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1211 |
self.tableWidgetHMB.setItem(25, columnCount, self.setTableWidgetItemProperties(hmb.friction_factor, |
1212 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1213 |
self.tableWidgetHMB.setItem(26, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop, |
1214 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1215 |
self.tableWidgetHMB.setItem(27, columnCount, |
1216 |
self.setTableWidgetItemProperties(hmb.pressure_drop_friction,
|
1217 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1218 |
self.tableWidgetHMB.setItem(28, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop_static, |
1219 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1220 |
self.tableWidgetHMB.setItem(29, columnCount, |
1221 |
self.setTableWidgetItemProperties(hmb.pressure_pipe_end_point,
|
1222 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1223 |
self.tableWidgetHMB.setItem(30, columnCount, self.setTableWidgetItemProperties(hmb.power, |
1224 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
1225 |
|
1226 |
if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount) |
1227 |
|
1228 |
self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
|
1229 |
|
1230 |
self.tableWidgetHMB.resizeColumnsToContents()
|
1231 |
self.tableWidgetHMB.resizeRowsToContents()
|
1232 |
|
1233 |
'''
|
1234 |
@brief refresh scene
|
1235 |
@author humkyung
|
1236 |
@date 2018.07.23
|
1237 |
'''
|
1238 |
|
1239 |
def onCommandRejected(self, cmd=None): |
1240 |
try:
|
1241 |
if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand: |
1242 |
if self.actionLine.tag.streamline: |
1243 |
self.graphicsView.scene.removeItem(self.actionLine.tag.streamline) |
1244 |
self.graphicsView.scene.update()
|
1245 |
self.actionLine.tag.reset()
|
1246 |
|
1247 |
self.actionLine.setChecked(False) |
1248 |
elif type(cmd) is AreaZoomCommand.AreaZoomCommand: |
1249 |
self.actionZoom.setChecked(False) |
1250 |
else:
|
1251 |
if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline: |
1252 |
self.graphicsView.scene.removeItem(self.actionLine.tag.streamline) |
1253 |
self.graphicsView.scene.update()
|
1254 |
self.actionLine.tag.reset()
|
1255 |
|
1256 |
self.actionLine.setChecked(False) |
1257 |
self.actionZoom.setChecked(False) |
1258 |
finally:
|
1259 |
self.graphicsView.useDefaultCommand()
|
1260 |
|
1261 |
'''
|
1262 |
@brief restore to default command when user press Escape key
|
1263 |
@author humkyung
|
1264 |
@date 2018.08.09
|
1265 |
|
1266 |
'''
|
1267 |
|
1268 |
def keyPressEvent(self, event): |
1269 |
try:
|
1270 |
if event.key() == Qt.Key_Escape:
|
1271 |
# already catched in command
|
1272 |
pass
|
1273 |
# checked = self.actionGroup.checkedAction()
|
1274 |
# if checked:
|
1275 |
# checked.setChecked(False)
|
1276 |
# self.graphicsView.useDefaultCommand()
|
1277 |
|
1278 |
QMainWindow.keyPressEvent(self, event)
|
1279 |
except Exception as ex: |
1280 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1281 |
sys.exc_info()[-1].tb_lineno)
|
1282 |
self.addMessage.emit(MessageType.Error, message)
|
1283 |
|
1284 |
'''
|
1285 |
@brief remove item from tree widget and then remove from scene
|
1286 |
@date 2018.05.25
|
1287 |
@author Jeongwoo
|
1288 |
'''
|
1289 |
|
1290 |
def on_item_removed(self, item): |
1291 |
try:
|
1292 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \ |
1293 |
[connector for connector in _item.connectors if |
1294 |
connector.connectedItem is not None and connector.connectedItem.parentItem() is item]] |
1295 |
for match in matches: |
1296 |
for connector in match.connectors: |
1297 |
if connector.connectedItem is item: connector.connect(None) |
1298 |
|
1299 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')] |
1300 |
for match in matches: |
1301 |
if match.owner is item: |
1302 |
match.owner = None
|
1303 |
|
1304 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')] |
1305 |
done = False
|
1306 |
for match in matches: |
1307 |
for assoc in match.associations(): |
1308 |
if item is assoc: |
1309 |
match.remove_assoc_item(item) |
1310 |
for attr in match.attrs.keys(): |
1311 |
if str(item.uid) == str(attr.AssocItem.uid): |
1312 |
attr.AssocItem = None
|
1313 |
match.attrs[attr] = ''
|
1314 |
done = True
|
1315 |
break
|
1316 |
break
|
1317 |
if done: break |
1318 |
|
1319 |
if type(item) is QEngineeringStreamlineItem: |
1320 |
self.on_stream_line_deleted(item)
|
1321 |
|
1322 |
if item.scene() is not None: |
1323 |
item.scene().removeItem(item) |
1324 |
del item
|
1325 |
except Exception as ex: |
1326 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1327 |
sys.exc_info()[-1].tb_lineno)
|
1328 |
self.addMessage.emit(MessageType.Error, message)
|
1329 |
|
1330 |
'''
|
1331 |
@brief load components
|
1332 |
@author yeonjin
|
1333 |
@date 2019.07.30.
|
1334 |
'''
|
1335 |
|
1336 |
def load_components(self, componentsUID): |
1337 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
1338 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
1339 |
|
1340 |
try:
|
1341 |
app_doc_data = AppDocData.instance() |
1342 |
|
1343 |
maxValue = len(componentsUID)
|
1344 |
self.progress.setMaximum(maxValue)
|
1345 |
|
1346 |
for componentUID in componentsUID: |
1347 |
componentInfos = app_doc_data.getComponentByComponentUID(componentUID) |
1348 |
if (len(componentInfos)) > 0: |
1349 |
category = componentInfos[0][3] # Category@SymbolType |
1350 |
|
1351 |
if category == 'Stream Line': |
1352 |
item = QEngineeringStreamlineItem.fromDatabase(componentInfos) |
1353 |
if item is not None: |
1354 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
1355 |
self.graphicsView.scene.addItem(item)
|
1356 |
else:
|
1357 |
item = SymbolSvgItem.fromDatabase(componentInfos) |
1358 |
if item is not None: |
1359 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
1360 |
app_doc_data.symbols.append(item) |
1361 |
self.addSvgItemToScene(item)
|
1362 |
|
1363 |
self.progress.setValue(self.progress.value() + 1) |
1364 |
|
1365 |
QApplication.processEvents() |
1366 |
|
1367 |
# """ update scene """
|
1368 |
self.graphicsView.scene.update(self.graphicsView.sceneRect()) |
1369 |
for item in self.graphicsView.scene.items(): |
1370 |
item.setVisible(True)
|
1371 |
|
1372 |
except Exception as ex: |
1373 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1374 |
sys.exc_info()[-1].tb_lineno)
|
1375 |
self.addMessage.emit(MessageType.Error, message)
|
1376 |
finally:
|
1377 |
pass
|
1378 |
|
1379 |
'''
|
1380 |
@brief Remove added item on same place and Add GraphicsItem
|
1381 |
@author Jeongwoo
|
1382 |
@date 2018.05.25
|
1383 |
@history 2018.05.29 Jeongwoo Moved from QRecognitionDialog
|
1384 |
2018.06.18 Jeongwoo Set Z-index
|
1385 |
'''
|
1386 |
|
1387 |
def addSvgItemToScene(self, svgItem): |
1388 |
svgItem.addSvgItemToScene(self.graphicsView.scene)
|
1389 |
|
1390 |
'''
|
1391 |
@brief Remove added item on same place and Add GraphicsItem
|
1392 |
@author Jeongwoo
|
1393 |
@date 2018.05.25
|
1394 |
@history 2018.05.29 Jeongwoo Moved from QRecognitionDialog
|
1395 |
2018.06.05 Jeongwoo Remove Size condition
|
1396 |
2018.06.18 Jeongwoo Set Z-index
|
1397 |
'''
|
1398 |
|
1399 |
def addTextItemToScene(self, textItem): |
1400 |
textItem.addTextItemToScene(self.graphicsView.scene)
|
1401 |
|
1402 |
'''
|
1403 |
@brief Remove added item on same place and Add GraphicsItem
|
1404 |
@author Jeongwoo
|
1405 |
@date 2018.05.29
|
1406 |
@history 2018.06.18 Jeongwoo Set Z-index
|
1407 |
'''
|
1408 |
|
1409 |
def addLineItemToScene(self, lineItem): |
1410 |
self.graphicsView.scene.addItem(lineItem)
|
1411 |
|
1412 |
'''
|
1413 |
@brief Check Number
|
1414 |
@author kyouho
|
1415 |
@date 2018.08.20
|
1416 |
'''
|
1417 |
|
1418 |
def isNumber(self, num): |
1419 |
p = re.compile('(^[0-9]+$)')
|
1420 |
result = p.match(num) |
1421 |
|
1422 |
if result:
|
1423 |
return True |
1424 |
else:
|
1425 |
return False |
1426 |
|
1427 |
'''
|
1428 |
@brief find overlap Connector
|
1429 |
@author kyouho
|
1430 |
@date 2018.08.28
|
1431 |
'''
|
1432 |
|
1433 |
def findOverlapConnector(self, connectorItem): |
1434 |
from shapely.geometry import Point |
1435 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
1436 |
itemList = [] |
1437 |
|
1438 |
x = connectorItem.center()[0]
|
1439 |
y = connectorItem.center()[1]
|
1440 |
|
1441 |
connectors = [item for item in self.graphicsView.scene.items() if |
1442 |
type(item) is QEngineeringConnectorItem and item != connectorItem] |
1443 |
for connector in connectors: |
1444 |
if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5: |
1445 |
itemList.append(connector.parent) |
1446 |
|
1447 |
return itemList
|
1448 |
|
1449 |
def setTableWidgetItemProperties(self, name, alignment, color=None): |
1450 |
if name is None: |
1451 |
name = ''
|
1452 |
|
1453 |
item = QTableWidgetItem(str(name))
|
1454 |
item.setTextAlignment(alignment) |
1455 |
if color:
|
1456 |
item.setBackground(color) |
1457 |
|
1458 |
return item
|
1459 |
|
1460 |
|
1461 |
if __name__ == '__main__': |
1462 |
import locale |
1463 |
from PyQt5.QtCore import QTranslator |
1464 |
from App import App |
1465 |
|
1466 |
app = App(sys.argv) |
1467 |
try:
|
1468 |
app._mainWnd = MainWindow.instance() |
1469 |
if len(sys.argv) == 2: app._mainWnd.open_drawing(sys.argv[1]) |
1470 |
app._mainWnd.show() |
1471 |
sys.exit(app.exec_()) |
1472 |
except Exception as ex: |
1473 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1474 |
sys.exc_info()[-1].tb_lineno))
|
1475 |
finally:
|
1476 |
pass
|